custom message type for VM_INFO
[minix3.git] / drivers / atl2 / atl2.c
blobb07e3536c5a38886f8502026fb200de64c0c4cc2
1 /* Attansic/Atheros L2 FastEthernet driver, by D.C. van Moolenbroek */
3 /* No documentation is available for this card. The FreeBSD driver is based
4 * heavily on the official Linux driver; this driver is based heavily on both.
5 */
7 #include <minix/drivers.h>
8 #include <minix/netdriver.h>
10 #include <sys/mman.h>
11 #include <minix/ds.h>
12 #include <minix/vm.h>
13 #include <machine/pci.h>
14 #include <net/gen/ether.h>
15 #include <net/gen/eth_io.h>
16 #include <assert.h>
18 #include "atl2.h"
20 #define VERBOSE 0 /* Verbose debugging output */
21 #define ATL2_FKEY 1 /* Register Shift+F11 for dumping statistics */
23 #if VERBOSE
24 #define ATL2_DEBUG(x) printf x
25 #else
26 #define ATL2_DEBUG(x)
27 #endif
29 typedef struct {
30 u32_t hdr;
31 u32_t vtag;
32 u8_t data[ATL2_RXD_SIZE - sizeof(u32_t) * 2];
33 } rxd_t;
35 static struct {
36 int devind; /* PCI device index */
37 int irq; /* IRQ number */
38 int hook_id; /* IRQ hook ID */
39 int mode; /* datalink mode */
40 volatile u8_t *base; /* base address of memory-mapped registers */
41 u32_t size; /* size of memory-mapped area */
42 u32_t hwaddr[2]; /* MAC address, in register representation */
44 u8_t *txd_base; /* local address of TxD ring buffer base */
45 u32_t *txs_base; /* local address of TxS ring buffer base */
46 u8_t *rxd_base_u; /* unaligned base address of RxD ring buffer */
47 rxd_t *rxd_base; /* local address of RxD ring buffer base */
49 int rxd_align; /* alignment offset of RxD ring buffer */
51 vir_bytes txd_phys; /* physical address of TxD ring buffer */
52 vir_bytes txs_phys; /* physical address of TxS ring buffer */
53 vir_bytes rxd_phys; /* physical address of RxD ring buffer */
55 int txd_tail; /* tail index into TxD, in bytes */
56 int txd_num; /* head-tail offset into TxD, in bytes */
57 int txs_tail; /* tail index into TxS, in elements */
58 int txs_num; /* head-tail offset into TxS, in elements */
59 int rxd_tail; /* tail index into RxD, in elements */
61 int flags; /* state flags (ATL2_FLAG_) */
62 message read_msg; /* suspended read request (READ_PEND) */
63 message write_msg; /* suspended write request (WRITE_PEND) */
64 endpoint_t task_endpt; /* requester endpoint (PACK_RCVD|PACK_SENT) */
65 size_t recv_count; /* packet size (PACK_RCVD) */
67 eth_stat_t stat; /* statistics */
68 } state;
70 #define ATL2_FLAG_RX_AVAIL 0x01 /* packet available for receipt */
71 #define ATL2_FLAG_READ_PEND 0x02 /* read request pending */
72 #define ATL2_FLAG_WRITE_PEND 0x04 /* write request pending */
73 #define ATL2_FLAG_PACK_RCVD 0x08 /* packet received */
74 #define ATL2_FLAG_PACK_SENT 0x10 /* packet transmitted */
76 #define ATL2_READ_U8(off) (* (u8_t *) (state.base + (off)))
77 #define ATL2_READ_U16(off) (* (u16_t *) (state.base + (off)))
78 #define ATL2_READ_U32(off) (* (u32_t *) (state.base + (off)))
79 #define ATL2_WRITE_U8(off, val) * (u8_t *) (state.base + (off)) = (val);
80 #define ATL2_WRITE_U16(off, val) * (u16_t *) (state.base + (off)) = (val);
81 #define ATL2_WRITE_U32(off, val) * (u32_t *) (state.base + (off)) = (val);
83 #define ATL2_ALIGN_32(n) (((n) + 3) & ~3)
85 static iovec_s_t iovec[NR_IOREQS];
87 static int instance;
89 /*===========================================================================*
90 * atl2_read_vpd *
91 *===========================================================================*/
92 static int atl2_read_vpd(int index, u32_t *res)
94 /* Read a value from the VPD register area.
96 u32_t off, val;
97 int i;
99 ATL2_WRITE_U32(ATL2_VPD_DATA_REG, 0);
101 off = ATL2_VPD_REGBASE + index * sizeof(u32_t);
103 ATL2_WRITE_U32(ATL2_VPD_CAP_REG,
104 (off << ATL2_VPD_CAP_ADDR_SHIFT) & ATL2_VPD_CAP_ADDR_MASK);
106 for (i = 0; i < ATL2_VPD_NTRIES; i++) {
107 micro_delay(ATL2_VPD_DELAY);
109 val = ATL2_READ_U32(ATL2_VPD_CAP_REG);
110 if (val & ATL2_VPD_CAP_DONE)
111 break;
114 if (i == ATL2_VPD_NTRIES) {
115 printf("ATL2: timeout reading EEPROM register %d\n", index);
116 return FALSE;
119 *res = ATL2_READ_U32(ATL2_VPD_DATA_REG);
120 return TRUE;
123 /*===========================================================================*
124 * atl2_get_vpd_hwaddr *
125 *===========================================================================*/
126 static int atl2_get_vpd_hwaddr(void)
128 /* Read the MAC address from the EEPROM, using the Vital Product Data
129 * register interface.
131 u32_t key, val;
132 int i, n, found[2];
134 /* No idea, copied from FreeBSD which copied it from Linux. */
135 val = ATL2_READ_U32(ATL2_SPICTL_REG);
136 if (val & ATL2_SPICTL_VPD_EN) {
137 val &= ~ATL2_SPICTL_VPD_EN;
138 ATL2_WRITE_U32(ATL2_SPICTL_REG, val);
141 /* Is VPD supported? */
142 #ifdef PCI_CAP_VPD /* FIXME: just a guess at the future name */
143 if (!pci_find_cap(state.devind, PCI_CAP_VPD, &n))
144 return FALSE;
145 #endif
147 /* Read out the set of key/value pairs. Look for the two parts that
148 * make up the MAC address.
150 found[0] = found[1] = FALSE;
151 for (i = 0; i < ATL2_VPD_NREGS; i += 2) {
152 if (!atl2_read_vpd(i, &key))
153 break;
155 if ((key & ATL2_VPD_SIG_MASK) != ATL2_VPD_SIG)
156 break;
158 key >>= ATL2_VPD_REG_SHIFT;
160 if (key != ATL2_HWADDR0_REG && key != ATL2_HWADDR1_REG)
161 continue;
163 if (!atl2_read_vpd(i + 1, &val))
164 break;
166 n = (key == ATL2_HWADDR1_REG);
167 state.hwaddr[n] = val;
168 found[n] = TRUE;
170 if (found[1 - n]) break;
173 return found[0] && found[1];
176 /*===========================================================================*
177 * atl2_get_hwaddr *
178 *===========================================================================*/
179 static void atl2_get_hwaddr(void)
181 /* Get the MAC address of the card. First try the EEPROM; if that
182 * fails, just use whatever the card was already set to.
185 if (!atl2_get_vpd_hwaddr()) {
186 printf("ATL2: unable to read from VPD\n");
188 state.hwaddr[0] = ATL2_READ_U32(ATL2_HWADDR0_REG);
189 state.hwaddr[1] = ATL2_READ_U32(ATL2_HWADDR1_REG) & 0xffff;
192 ATL2_DEBUG(("ATL2: MAC address %04lx%08lx\n",
193 state.hwaddr[1], state.hwaddr[0]));
196 /*===========================================================================*
197 * atl2_read_mdio *
198 *===========================================================================*/
199 static int atl2_read_mdio(int addr, u16_t *res)
201 /* Read a MII PHY register using MDIO.
203 u32_t rval;
204 int i;
206 rval = ((addr << ATL2_MDIO_ADDR_SHIFT) & ATL2_MDIO_ADDR_MASK) |
207 ATL2_MDIO_START | ATL2_MDIO_READ | ATL2_MDIO_SUP_PREAMBLE |
208 ATL2_MDIO_CLK_25_4;
210 ATL2_WRITE_U32(ATL2_MDIO_REG, rval);
212 for (i = 0; i < ATL2_MDIO_NTRIES; i++) {
213 micro_delay(ATL2_MDIO_DELAY);
215 rval = ATL2_READ_U32(ATL2_MDIO_REG);
217 if (!(rval & (ATL2_MDIO_START | ATL2_MDIO_BUSY)))
218 break;
221 if (i == ATL2_MDIO_NTRIES) return FALSE;
223 *res = (u16_t) (rval & ATL2_MDIO_DATA_MASK);
224 return TRUE;
227 /*===========================================================================*
228 * atl2_alloc_dma *
229 *===========================================================================*/
230 static int atl2_alloc_dma(void)
232 /* Allocate DMA ring buffers.
235 state.txd_base = alloc_contig(ATL2_TXD_BUFSIZE,
236 AC_ALIGN4K, &state.txd_phys);
237 state.txs_base = alloc_contig(ATL2_TXS_COUNT * sizeof(u32_t),
238 AC_ALIGN4K, &state.txs_phys);
240 /* The data buffer in each RxD descriptor must be 128-byte aligned.
241 * The two Tx buffers merely require a 4-byte start alignment.
243 state.rxd_align = 128 - offsetof(rxd_t, data);
244 state.rxd_base_u =
245 alloc_contig(state.rxd_align + ATL2_RXD_COUNT * ATL2_RXD_SIZE,
246 AC_ALIGN4K, &state.rxd_phys);
248 /* Unlike mmap, alloc_contig returns NULL on failure. */
249 if (!state.txd_base || !state.txs_base || !state.rxd_base_u)
250 return ENOMEM;
252 state.rxd_base = (rxd_t *) (state.rxd_base_u + state.rxd_align);
253 state.rxd_phys += state.rxd_align;
255 /* Zero out just in case. */
256 memset(state.txd_base, 0, ATL2_TXD_BUFSIZE);
257 memset(state.txs_base, 0, ATL2_TXS_COUNT * sizeof(u32_t));
258 memset(state.rxd_base, 0, ATL2_RXD_COUNT * ATL2_RXD_SIZE);
260 return OK;
263 /*===========================================================================*
264 * atl2_stop *
265 *===========================================================================*/
266 static int atl2_stop(void)
268 /* Stop the device.
270 u32_t val;
271 int i;
273 /* Clear and disable interrupts. */
274 ATL2_WRITE_U32(ATL2_IMR_REG, 0);
275 ATL2_WRITE_U32(ATL2_ISR_REG, 0xffffffff);
277 /* Stop Rx/Tx MACs. */
278 val = ATL2_READ_U32(ATL2_MAC_REG);
279 if (val & (ATL2_MAC_RX_EN | ATL2_MAC_TX_EN)) {
280 val &= ~(ATL2_MAC_RX_EN | ATL2_MAC_TX_EN);
281 ATL2_WRITE_U32(ATL2_MAC_REG, val);
284 ATL2_WRITE_U8(ATL2_DMAWRITE_REG, 0);
285 ATL2_WRITE_U8(ATL2_DMAREAD_REG, 0);
287 /* Wait until everything is idle. */
288 for (i = 0; i < ATL2_IDLE_NTRIES; i++) {
289 if (ATL2_READ_U32(ATL2_IDLE_REG) == 0)
290 break;
292 micro_delay(ATL2_IDLE_DELAY);
295 /* The caller will generally ignore this return value. */
296 return (i < ATL2_IDLE_NTRIES);
299 /*===========================================================================*
300 * atl2_reset *
301 *===========================================================================*/
302 static int atl2_reset(void)
304 /* Reset the device to a known good state.
306 u32_t val;
307 int i;
309 /* Issue a soft reset, and wait for the device to respond. */
310 ATL2_WRITE_U32(ATL2_MASTER_REG, ATL2_MASTER_SOFT_RESET);
312 for (i = 0; i < ATL2_RESET_NTRIES; i++) {
313 val = ATL2_READ_U32(ATL2_MASTER_REG);
314 if (!(val & ATL2_MASTER_SOFT_RESET))
315 break;
317 micro_delay(ATL2_RESET_DELAY);
320 if (i == ATL2_RESET_NTRIES)
321 return FALSE;
323 /* Wait until everything is idle. */
324 for (i = 0; i < ATL2_IDLE_NTRIES; i++) {
325 if (ATL2_READ_U32(ATL2_IDLE_REG) == 0)
326 break;
328 micro_delay(ATL2_IDLE_DELAY);
331 return (i < ATL2_IDLE_NTRIES);
334 /*===========================================================================*
335 * atl2_set_mode *
336 *===========================================================================*/
337 static void atl2_set_mode(void)
339 /* Reconfigure the device's promiscuity, multicast, and broadcast mode
340 * settings.
342 u32_t val;
344 val = ATL2_READ_U32(ATL2_MAC_REG);
345 val &= ~(ATL2_MAC_PROMISC_EN | ATL2_MAC_MCAST_EN | ATL2_MAC_BCAST_EN);
347 if (state.mode & DL_PROMISC_REQ)
348 val |= ATL2_MAC_PROMISC_EN;
349 if (state.mode & DL_MULTI_REQ)
350 val |= ATL2_MAC_MCAST_EN;
351 if (state.mode & DL_BROAD_REQ)
352 val |= ATL2_MAC_BCAST_EN;
354 ATL2_WRITE_U32(ATL2_MAC_REG, val);
357 /*===========================================================================*
358 * atl2_setup *
359 *===========================================================================*/
360 static int atl2_setup(void)
362 /* Set up the device for normal operation.
364 u32_t val;
366 atl2_stop();
368 if (!atl2_reset())
369 return FALSE;
371 /* Initialize PCIE module. Magic. */
372 ATL2_WRITE_U32(ATL2_LTSSM_TESTMODE_REG, ATL2_LTSSM_TESTMODE_DEFAULT);
373 ATL2_WRITE_U32(ATL2_DLL_TX_CTRL_REG, ATL2_DLL_TX_CTRL_DEFAULT);
375 /* Enable PHY. */
376 ATL2_WRITE_U32(ATL2_PHY_ENABLE_REG, ATL2_PHY_ENABLE);
377 micro_delay(1000);
379 /* Clear and disable interrupts. */
380 ATL2_WRITE_U32(ATL2_ISR_REG, 0xffffffff);
382 /* Set the MAC address. */
383 ATL2_WRITE_U32(ATL2_HWADDR0_REG, state.hwaddr[0]);
384 ATL2_WRITE_U32(ATL2_HWADDR1_REG, state.hwaddr[1]);
386 /* Initialize ring buffer addresses and sizes. */
387 ATL2_WRITE_U32(ATL2_DESC_ADDR_HI_REG, 0); /* no 64 bit */
388 ATL2_WRITE_U32(ATL2_TXD_ADDR_LO_REG, state.txd_phys);
389 ATL2_WRITE_U32(ATL2_TXS_ADDR_LO_REG, state.txs_phys);
390 ATL2_WRITE_U32(ATL2_RXD_ADDR_LO_REG, state.rxd_phys);
392 ATL2_WRITE_U16(ATL2_RXD_COUNT_REG, ATL2_RXD_COUNT);
393 ATL2_WRITE_U16(ATL2_TXD_BUFSIZE_REG, ATL2_TXD_BUFSIZE / sizeof(u32_t));
394 ATL2_WRITE_U16(ATL2_TXS_COUNT_REG, ATL2_TXS_COUNT);
396 /* A whole lot of other initialization copied from Linux/FreeBSD. */
397 ATL2_WRITE_U32(ATL2_IFG_REG, ATL2_IFG_DEFAULT);
399 ATL2_WRITE_U32(ATL2_HDPX_REG, ATL2_HDPX_DEFAULT);
401 ATL2_WRITE_U16(ATL2_IMT_REG, ATL2_IMT_DEFAULT);
402 val = ATL2_READ_U32(ATL2_MASTER_REG);
403 ATL2_WRITE_U32(ATL2_MASTER_REG, val | ATL2_MASTER_IMT_EN);
405 ATL2_WRITE_U16(ATL2_ICT_REG, ATL2_ICT_DEFAULT);
407 ATL2_WRITE_U32(ATL2_CUT_THRESH_REG, ATL2_CUT_THRESH_DEFAULT);
409 ATL2_WRITE_U16(ATL2_FLOW_THRESH_HI_REG, (ATL2_RXD_COUNT / 8) * 7);
410 ATL2_WRITE_U16(ATL2_FLOW_THRESH_LO_REG, ATL2_RXD_COUNT / 12);
412 /* Set MTU. */
413 ATL2_WRITE_U16(ATL2_MTU_REG, ATL2_MTU_DEFAULT);
415 /* Reset descriptors, and enable DMA. */
416 state.txd_tail = state.txs_tail = state.rxd_tail = 0;
417 state.txd_num = state.txs_num = 0;
418 state.flags &= ~ATL2_FLAG_RX_AVAIL;
419 ATL2_WRITE_U16(ATL2_TXD_IDX_REG, 0);
420 ATL2_WRITE_U16(ATL2_RXD_IDX_REG, 0);
422 ATL2_WRITE_U8(ATL2_DMAREAD_REG, ATL2_DMAREAD_EN);
423 ATL2_WRITE_U8(ATL2_DMAWRITE_REG, ATL2_DMAWRITE_EN);
425 /* Did everything go alright? */
426 val = ATL2_READ_U32(ATL2_ISR_REG);
427 if (val & ATL2_ISR_PHY_LINKDOWN) {
428 printf("ATL2: initialization failed\n");
429 return FALSE;
432 /* Clear interrupt status. */
433 ATL2_WRITE_U32(ATL2_ISR_REG, 0x3fffffff);
434 ATL2_WRITE_U32(ATL2_ISR_REG, 0);
436 /* Enable interrupts. */
437 ATL2_WRITE_U32(ATL2_IMR_REG, ATL2_IMR_DEFAULT);
439 /* Configure MAC. */
440 ATL2_WRITE_U32(ATL2_MAC_REG, ATL2_MAC_DEFAULT);
442 /* Inet does not tell us about the multicast addresses that it is
443 * interested in, so we have to simply accept all multicast packets.
445 ATL2_WRITE_U32(ATL2_MHT0_REG, 0xffffffff);
446 ATL2_WRITE_U32(ATL2_MHT1_REG, 0xffffffff);
448 atl2_set_mode();
450 /* Enable Tx/Rx. */
451 val = ATL2_READ_U32(ATL2_MAC_REG);
452 ATL2_WRITE_U32(ATL2_MAC_REG, val | ATL2_MAC_TX_EN | ATL2_MAC_RX_EN);
454 return TRUE;
457 /*===========================================================================*
458 * atl2_probe *
459 *===========================================================================*/
460 static int atl2_probe(int skip)
462 /* Find a matching PCI device.
464 u16_t vid, did;
465 #if VERBOSE
466 char *dname;
467 #endif
468 int r, devind;
470 pci_init();
472 r = pci_first_dev(&devind, &vid, &did);
473 if (r <= 0)
474 return -1;
476 while (skip--) {
477 r = pci_next_dev(&devind, &vid, &did);
478 if (r <= 0)
479 return -1;
482 #if VERBOSE
483 dname = pci_dev_name(vid, did);
484 ATL2_DEBUG(("ATL2: found %s (%x/%x) at %s\n",
485 dname ? dname : "<unknown>", vid, did,
486 pci_slot_name(devind)));
487 #endif
489 pci_reserve(devind);
491 return devind;
494 /*===========================================================================*
495 * atl2_init *
496 *===========================================================================*/
497 static void atl2_init(int devind)
499 /* Initialize the device.
501 u32_t bar;
502 int r, flag;
504 /* Initialize global state. */
505 state.devind = devind;
506 state.mode = DL_NOMODE;
507 state.flags = 0;
508 state.recv_count = 0;
510 memset(&state.stat, 0, sizeof(state.stat));
512 if ((r = pci_get_bar(devind, PCI_BAR, &bar, &state.size, &flag)) != OK)
513 panic("unable to retrieve bar: %d", r);
515 if (state.size < ATL2_MIN_MMAP_SIZE || flag)
516 panic("invalid register bar");
518 state.base = vm_map_phys(SELF, (void *) bar, state.size);
519 if (state.base == MAP_FAILED)
520 panic("unable to map in registers");
522 if ((r = atl2_alloc_dma()) != OK)
523 panic("unable to allocate DMA buffers: %d", r);
525 state.irq = pci_attr_r8(devind, PCI_ILR);
526 state.hook_id = 0;
528 if ((r = sys_irqsetpolicy(state.irq, 0, &state.hook_id)) != OK)
529 panic("unable to register IRQ: %d", r);
531 if (!atl2_reset())
532 panic("unable to reset hardware");
534 if ((r = sys_irqenable(&state.hook_id)) != OK)
535 panic("unable to enable IRQ: %d", r);
537 atl2_get_hwaddr();
539 atl2_setup();
542 /*===========================================================================*
543 * atl2_tx_stat *
544 *===========================================================================*/
545 static void atl2_tx_stat(u32_t stat)
547 /* Update statistics for packet transmission.
550 if (stat & ATL2_TXS_SUCCESS)
551 state.stat.ets_packetT++;
552 else
553 state.stat.ets_recvErr++;
555 if (stat & ATL2_TXS_DEFER)
556 state.stat.ets_transDef++;
557 if (stat & (ATL2_TXS_EXCDEFER | ATL2_TXS_ABORTCOL))
558 state.stat.ets_transAb++;
559 if (stat & ATL2_TXS_SINGLECOL)
560 state.stat.ets_collision++;
561 if (stat & ATL2_TXS_MULTICOL)
562 state.stat.ets_collision++;
563 if (stat & ATL2_TXS_LATECOL)
564 state.stat.ets_OWC++;
565 if (stat & ATL2_TXS_UNDERRUN)
566 state.stat.ets_fifoUnder++;
569 /*===========================================================================*
570 * atl2_rx_stat *
571 *===========================================================================*/
572 static void atl2_rx_stat(u32_t stat)
574 /* Update statistics for packet receipt.
577 if (stat & ATL2_RXD_SUCCESS)
578 state.stat.ets_packetR++;
579 else
580 state.stat.ets_recvErr++;
582 if (stat & ATL2_RXD_CRCERR)
583 state.stat.ets_CRCerr++;
584 if (stat & ATL2_RXD_FRAG)
585 state.stat.ets_collision++;
586 if (stat & ATL2_RXD_TRUNC)
587 state.stat.ets_fifoOver++;
588 if (stat & ATL2_RXD_ALIGN)
589 state.stat.ets_frameAll++;
592 /*===========================================================================*
593 * atl2_tx_advance *
594 *===========================================================================*/
595 static int atl2_tx_advance(void)
597 /* Advance the TxD/TxS tails by as many sent packets as found.
599 u32_t stat, size, dsize;
600 int advanced;
602 advanced = FALSE;
604 while (state.txs_num > 0) {
605 /* Has the tail packet been processed by the driver? */
606 stat = state.txs_base[state.txs_tail];
608 if (!(stat & ATL2_TXS_UPDATE))
609 break;
611 /* The packet size from the status must match the packet size
612 * we put in. If they don't, there's not much we can do..
614 size = stat & ATL2_TXS_SIZE_MASK;
616 assert((u32_t) state.txd_tail <=
617 ATL2_TXD_BUFSIZE - sizeof(u32_t));
618 dsize = * (u32_t *) (state.txd_base + state.txd_tail);
619 if (size != dsize)
620 printf("ATL2: TxD/TxS size mismatch (%x vs %x)\n",
621 size, dsize);
623 /* Advance tails accordingly. */
624 size = sizeof(u32_t) + ATL2_ALIGN_32(dsize);
625 assert((u32_t) state.txd_num >= size);
626 state.txd_tail = (state.txd_tail + size) % ATL2_TXD_BUFSIZE;
627 state.txd_num -= size;
629 state.txs_tail = (state.txs_tail + 1) % ATL2_TXS_COUNT;
630 state.txs_num--;
632 if (stat & ATL2_TXS_SUCCESS) {
633 ATL2_DEBUG(("ATL2: successfully sent packet\n"));
634 } else {
635 ATL2_DEBUG(("ATL2: failed to send packet\n"));
638 /* Update statistics. */
639 atl2_tx_stat(stat);
641 advanced = TRUE;
644 return advanced;
647 /*===========================================================================*
648 * atl2_rx_advance *
649 *===========================================================================*/
650 static void atl2_rx_advance(int next)
652 /* Advance the RxD tail by as many failed receipts as possible, and
653 * see if there is an actual packet left to receive. If 'next' is set,
654 * the packet at the current tail has been processed.
656 int update_tail;
657 rxd_t *rxd;
658 u32_t hdr, size;
660 update_tail = FALSE;
662 if (next) {
663 state.rxd_tail = (state.rxd_tail + 1) % ATL2_RXD_COUNT;
664 update_tail = TRUE;
666 ATL2_DEBUG(("ATL2: successfully received packet\n"));
668 state.flags &= ~ATL2_FLAG_RX_AVAIL;
671 assert(!(state.flags & ATL2_FLAG_RX_AVAIL));
673 for (;;) {
674 /* Check the RxD tail for updates. */
675 rxd = &state.rxd_base[state.rxd_tail];
677 hdr = rxd->hdr;
679 if (!(hdr & ATL2_RXD_UPDATE))
680 break;
682 rxd->hdr = hdr & ~(ATL2_RXD_UPDATE);
684 /* Update statistics. */
685 atl2_rx_stat(hdr);
687 /* Stop at the first successful receipt. The packet will be
688 * picked up by Inet later.
690 size = hdr & ATL2_RXD_SIZE_MASK;
692 if ((hdr & ATL2_RXD_SUCCESS) && size >= ETH_MIN_PACK_SIZE) {
693 ATL2_DEBUG(("ATL2: packet available, size %ld\n",
694 size));
696 state.flags |= ATL2_FLAG_RX_AVAIL;
697 break;
700 ATL2_DEBUG(("ATL2: packet receipt failed\n"));
702 /* Advance tail. */
703 state.rxd_tail = (state.rxd_tail + 1) % ATL2_RXD_COUNT;
704 update_tail = TRUE;
707 /* If new RxD descriptors are now up for reuse, tell the device. */
708 if (update_tail) {
709 __insn_barrier();
711 ATL2_WRITE_U32(ATL2_RXD_IDX_REG, state.rxd_tail);
715 /*===========================================================================*
716 * atl2_reply *
717 *===========================================================================*/
718 static void atl2_reply(void)
720 /* Send a task reply to Inet.
722 message m;
723 int r, flags;
725 flags = DL_NOFLAGS;
726 if (state.flags & ATL2_FLAG_PACK_SENT)
727 flags |= DL_PACK_SEND;
728 if (state.flags & ATL2_FLAG_PACK_RCVD)
729 flags |= DL_PACK_RECV;
731 m.m_type = DL_TASK_REPLY;
732 m.m_netdrv_net_dl_task.flags = flags;
733 m.m_netdrv_net_dl_task.count = state.recv_count;
735 ATL2_DEBUG(("ATL2: sending reply, flags %x count %d\n", flags,
736 m.m_netdrv_net_dl_task.count));
738 if ((r = ipc_send(state.task_endpt, &m)) != OK)
739 panic("unable to reply: %d", r);
741 state.flags &= ~(ATL2_FLAG_PACK_SENT | ATL2_FLAG_PACK_RCVD);
742 state.recv_count = 0;
745 /*===========================================================================*
746 * atl2_readv *
747 *===========================================================================*/
748 static void atl2_readv(const message *m, int from_int)
750 /* Read packet data.
752 rxd_t *rxd;
753 iovec_s_t *iovp;
754 size_t count, off, left, size;
755 u8_t *pos;
756 int i, j, r, batch;
758 /* We can deal with only one read request from Inet at a time. */
759 assert(from_int || !(state.flags & ATL2_FLAG_READ_PEND));
761 state.task_endpt = m->m_source;
763 /* Are there any packets available at all? */
764 if (!(state.flags & ATL2_FLAG_RX_AVAIL))
765 goto suspend;
767 /* Get the first available packet's size. Cut off the CRC. */
768 rxd = &state.rxd_base[state.rxd_tail];
770 count = rxd->hdr & ATL2_RXD_SIZE_MASK;
771 count -= ETH_CRC_SIZE;
773 ATL2_DEBUG(("ATL2: readv: found packet with length %d\n", count));
775 /* Copy out the packet. */
776 off = 0;
777 left = count;
778 pos = rxd->data;
780 for (i = 0; i < m->m_net_netdrv_dl_readv_s.count && left > 0; i += batch) {
781 /* Copy in the next batch. */
782 batch = MIN(m->m_net_netdrv_dl_readv_s.count - i, NR_IOREQS);
784 r = sys_safecopyfrom(m->m_source,
785 m->m_net_netdrv_dl_readv_s.grant, off, (vir_bytes) iovec,
786 batch * sizeof(iovec[0]));
787 if (r != OK)
788 panic("vector copy failed: %d", r);
790 /* Copy out each element in the batch, until we run out. */
791 for (j = 0, iovp = iovec; j < batch && left > 0; j++, iovp++) {
792 size = MIN(iovp->iov_size, left);
794 r = sys_safecopyto(m->m_source, iovp->iov_grant, 0,
795 (vir_bytes) pos, size);
796 if (r != OK)
797 panic("safe copy failed: %d", r);
799 pos += size;
800 left -= size;
803 off += batch * sizeof(iovec[0]);
806 /* Not sure what to do here. Inet shouldn't mess this up anyway. */
807 if (left > 0) {
808 printf("ATL2: truncated packet of %d bytes by %d bytes\n",
809 count, left);
810 count -= left;
813 /* We are done with this packet. Move on to the next. */
814 atl2_rx_advance(TRUE /*next*/);
816 /* We have now successfully received a packet. */
817 state.flags &= ~ATL2_FLAG_READ_PEND;
818 state.flags |= ATL2_FLAG_PACK_RCVD;
819 state.recv_count = count;
821 /* If called from the interrupt handler, the caller will reply. */
822 if (!from_int)
823 atl2_reply();
825 return;
827 suspend:
828 /* No packets are available at this time. If we were not already
829 * trying to resume receipt, save the read request for later, and tell
830 * Inet that the request has been suspended.
832 if (from_int)
833 return;
835 state.flags |= ATL2_FLAG_READ_PEND;
836 state.read_msg = *m;
838 atl2_reply();
841 /*===========================================================================*
842 * atl2_writev *
843 *===========================================================================*/
844 static void atl2_writev(const message *m, int from_int)
846 /* Write packet data.
848 iovec_s_t *iovp;
849 size_t off, count, left, pos, skip;
850 vir_bytes size;
851 u8_t *sizep;
852 int i, j, r, batch, maxnum;
854 /* We can deal with only one write request from Inet at a time. */
855 assert(from_int || !(state.flags & ATL2_FLAG_WRITE_PEND));
857 state.task_endpt = m->m_source;
859 /* If we are already certain that the packet won't fit, bail out.
860 * Keep at least some space between TxD head and tail, as it is not
861 * clear whether the device deals well with the case that they collide.
863 if (state.txs_num >= ATL2_TXS_COUNT)
864 goto suspend;
865 maxnum = ATL2_TXD_BUFSIZE - ETH_MIN_PACK_SIZE - sizeof(u32_t);
866 if (state.txd_num >= maxnum)
867 goto suspend;
869 /* Optimistically try to copy in the data; suspend if it turns out
870 * that it does not fit.
872 off = 0;
873 count = 0;
874 left = state.txd_num - sizeof(u32_t);
875 pos = (state.txd_tail + state.txd_num +
876 sizeof(u32_t)) % ATL2_TXD_BUFSIZE;
878 for (i = 0; i < m->m_net_netdrv_dl_writev_s.count; i += batch) {
879 /* Copy in the next batch. */
880 batch = MIN(m->m_net_netdrv_dl_writev_s.count - i, NR_IOREQS);
882 r = sys_safecopyfrom(m->m_source,
883 m->m_net_netdrv_dl_writev_s.grant, off, (vir_bytes) iovec,
884 batch * sizeof(iovec[0]));
885 if (r != OK)
886 panic("vector copy failed: %d", r);
888 /* Copy in each element in the batch. */
889 for (j = 0, iovp = iovec; j < batch; j++, iovp++) {
890 size = iovp->iov_size;
891 if (size > left)
892 goto suspend;
894 skip = 0;
895 if (size > ATL2_TXD_BUFSIZE - pos) {
896 skip = ATL2_TXD_BUFSIZE - pos;
897 r = sys_safecopyfrom(m->m_source,
898 iovp->iov_grant, 0,
899 (vir_bytes) (state.txd_base + pos),
900 skip);
901 if (r != OK)
902 panic("safe copy failed: %d", r);
903 pos = 0;
906 r = sys_safecopyfrom(m->m_source, iovp->iov_grant,
907 skip, (vir_bytes) (state.txd_base + pos),
908 size - skip);
909 if (r != OK)
910 panic("safe copy failed: %d", r);
912 pos = (pos + size - skip) % ATL2_TXD_BUFSIZE;
913 left -= size;
914 count += size;
917 off += batch * sizeof(iovec[0]);
920 assert(count <= ETH_MAX_PACK_SIZE_TAGGED);
922 /* Write the length to the DWORD right before the packet. */
923 sizep = state.txd_base +
924 (state.txd_tail + state.txd_num) % ATL2_TXD_BUFSIZE;
925 * (u32_t *) sizep = count;
927 /* Update the TxD head. */
928 state.txd_num += sizeof(u32_t) + ATL2_ALIGN_32(count);
929 pos = ATL2_ALIGN_32(pos) % ATL2_TXD_BUFSIZE;
930 assert((int) pos ==
931 (state.txd_tail + state.txd_num) % ATL2_TXD_BUFSIZE);
933 /* Initialize and update the TxS head. */
934 state.txs_base[(state.txs_tail + state.txs_num) % ATL2_TXS_COUNT] = 0;
935 state.txs_num++;
937 /* Tell the device about our new position. */
938 __insn_barrier();
940 ATL2_WRITE_U32(ATL2_TXD_IDX_REG, pos / sizeof(u32_t));
942 /* We have now successfully set up the transmission of a packet. */
943 state.flags &= ~ATL2_FLAG_WRITE_PEND;
944 state.flags |= ATL2_FLAG_PACK_SENT;
946 /* If called from the interrupt handler, the caller will reply. */
947 if (!from_int)
948 atl2_reply();
950 return;
952 suspend:
953 /* We cannot transmit the packet at this time. If we were not already
954 * trying to resume transmission, save the write request for later,
955 * and tell Inet that the request has been suspended.
957 if (from_int)
958 return;
960 state.flags |= ATL2_FLAG_WRITE_PEND;
961 state.write_msg = *m;
963 atl2_reply();
966 /*===========================================================================*
967 * atl2_intr *
968 *===========================================================================*/
969 static void atl2_intr(const message *UNUSED(m))
971 /* Interrupt received.
973 u32_t val;
974 int r, try_write, try_read;
976 /* Clear and disable interrupts. */
977 val = ATL2_READ_U32(ATL2_ISR_REG);
979 ATL2_WRITE_U32(ATL2_ISR_REG, val | ATL2_ISR_DISABLE);
981 ATL2_DEBUG(("ATL2: interrupt (0x%08lx)\n", val));
983 /* If an error occurred, reset the card. */
984 if (val & (ATL2_ISR_DMAR_TIMEOUT | ATL2_ISR_DMAW_TIMEOUT |
985 ATL2_ISR_PHY_LINKDOWN)) {
986 atl2_setup();
989 try_write = try_read = FALSE;
991 /* Process sent data, and possibly send pending data. */
992 if (val & ATL2_ISR_TX_EVENT) {
993 if (atl2_tx_advance())
994 try_write = (state.flags & ATL2_FLAG_WRITE_PEND);
997 /* Receive new data, and possible satisfy a pending receive request. */
998 if (val & ATL2_ISR_RX_EVENT) {
999 if (!(state.flags & ATL2_FLAG_RX_AVAIL)) {
1000 atl2_rx_advance(FALSE /*next*/);
1002 try_read = (state.flags & ATL2_FLAG_READ_PEND);
1006 /* Reenable interrupts. */
1007 ATL2_WRITE_U32(ATL2_ISR_REG, 0);
1009 if ((r = sys_irqenable(&state.hook_id)) != OK)
1010 panic("unable to enable IRQ: %d", r);
1012 /* Attempt to satisfy pending write and read requests. */
1013 if (try_write)
1014 atl2_writev(&state.write_msg, TRUE /*from_int*/);
1015 if (try_read)
1016 atl2_readv(&state.read_msg, TRUE /*from_int*/);
1017 if (state.flags & (ATL2_FLAG_PACK_SENT | ATL2_FLAG_PACK_RCVD))
1018 atl2_reply();
1021 /*===========================================================================*
1022 * atl2_conf *
1023 *===========================================================================*/
1024 static void atl2_conf(message *m)
1026 /* Configure the mode of the card.
1028 ether_addr_t addr;
1029 int r;
1031 state.mode = m->m_net_netdrv_dl_conf.mode;
1033 atl2_set_mode();
1035 addr.ea_addr[0] = state.hwaddr[1] >> 8;
1036 addr.ea_addr[1] = state.hwaddr[1] & 0xff;
1037 addr.ea_addr[2] = state.hwaddr[0] >> 24;
1038 addr.ea_addr[3] = (state.hwaddr[0] >> 16) & 0xff;
1039 addr.ea_addr[4] = (state.hwaddr[0] >> 8) & 0xff;
1040 addr.ea_addr[5] = state.hwaddr[0] & 0xff;
1042 memcpy(m->m_netdrv_net_dl_conf.hw_addr, &addr,
1043 sizeof(m->m_netdrv_net_dl_conf.hw_addr));
1045 m->m_type = DL_CONF_REPLY;
1046 m->m_netdrv_net_dl_conf.stat = OK;
1048 if ((r = ipc_send(m->m_source, m)) != OK)
1049 printf("ATL2: unable to send reply (%d)\n", r);
1052 /*===========================================================================*
1053 * atl2_getstat *
1054 *===========================================================================*/
1055 static void atl2_getstat(message *m)
1057 /* Copy out statistics.
1059 int r;
1061 sys_safecopyto(m->m_source, m->m_net_netdrv_dl_getstat_s.grant, 0,
1062 (vir_bytes) &state.stat, sizeof(state.stat));
1064 m->m_type = DL_STAT_REPLY;
1066 if ((r = ipc_send(m->m_source, m)) != OK)
1067 printf("ATL2: unable to send reply (%d)\n", r);
1070 /*===========================================================================*
1071 * atl2_dump_link *
1072 *===========================================================================*/
1073 static void atl2_dump_link(void)
1075 /* Dump link status.
1077 u16_t val;
1078 int link_up;
1080 /* The link status bit is latched. Read the status register twice. */
1081 atl2_read_mdio(ATL2_MII_BMSR, &val);
1082 if (!atl2_read_mdio(ATL2_MII_BMSR, &val)) return;
1084 link_up = val & ATL2_MII_BMSR_LSTATUS;
1085 printf("link status: %4s\t", link_up ? "up" : "down");
1087 if (!link_up) return;
1089 if (!atl2_read_mdio(ATL2_MII_PSSR, &val)) return;
1091 if (!(val & ATL2_MII_PSSR_RESOLVED)) {
1092 printf("(not resolved)\n");
1094 return;
1097 switch (val & ATL2_MII_PSSR_SPEED) {
1098 case ATL2_MII_PSSR_10: printf("(10Mbps "); break;
1099 case ATL2_MII_PSSR_100: printf("(100Mbps "); break;
1100 case ATL2_MII_PSSR_1000: printf("(1000Mbps "); break;
1101 default: printf("(unknown, ");
1104 printf("%s duplex)", (val & ATL2_MII_PSSR_DUPLEX) ? "full" : "half");
1107 /*===========================================================================*
1108 * atl2_dump *
1109 *===========================================================================*/
1110 static void atl2_dump(void)
1112 /* Dump statistics.
1115 printf("\n");
1116 printf("Attansic L2 statistics:\n");
1118 printf("recvErr: %8ld\t", state.stat.ets_recvErr);
1119 printf("sendErr: %8ld\t", state.stat.ets_sendErr);
1120 printf("OVW: %8ld\n", state.stat.ets_OVW);
1122 printf("CRCerr: %8ld\t", state.stat.ets_CRCerr);
1123 printf("frameAll: %8ld\t", state.stat.ets_frameAll);
1124 printf("missedP: %8ld\n", state.stat.ets_missedP);
1126 printf("packetR: %8ld\t", state.stat.ets_packetR);
1127 printf("packetT: %8ld\t", state.stat.ets_packetT);
1128 printf("transDef: %8ld\n", state.stat.ets_transDef);
1130 printf("collision: %8ld\t", state.stat.ets_collision);
1131 printf("transAb: %8ld\t", state.stat.ets_transAb);
1132 printf("carrSense: %8ld\n", state.stat.ets_carrSense);
1134 printf("fifoUnder: %8ld\t", state.stat.ets_fifoUnder);
1135 printf("fifoOver: %8ld\t", state.stat.ets_fifoOver);
1136 printf("CDheartbeat: %8ld\n", state.stat.ets_CDheartbeat);
1138 printf("OWC: %8ld\t", state.stat.ets_OWC);
1139 printf("TxD tail: %8d\t", state.txd_tail);
1140 printf("TxD count: %8d\n", state.txd_num);
1142 printf("RxD tail: %8d\t", state.rxd_tail);
1143 printf("TxS tail: %8d\t", state.txs_tail);
1144 printf("TxS count: %8d\n", state.txs_num);
1146 printf("flags: 0x%04x\t", state.flags);
1147 atl2_dump_link();
1148 printf("\n");
1151 /*===========================================================================*
1152 * sef_cb_init_fresh *
1153 *===========================================================================*/
1154 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
1156 /* Initialize the atl2 driver.
1158 int r, devind;
1159 long v;
1160 #if ATL2_FKEY
1161 int fkeys, sfkeys;
1162 #endif
1164 /* How many matching devices should we skip? */
1165 v = 0;
1166 (void) env_parse("instance", "d", 0, &v, 0, 255);
1167 instance = (int) v;
1169 /* Try to find a recognized device. */
1170 devind = atl2_probe(instance);
1172 if (devind < 0)
1173 panic("no matching device found");
1175 /* Initialize the device. */
1176 atl2_init(devind);
1178 /* Announce we are up! */
1179 netdriver_announce();
1181 #if ATL2_FKEY
1182 /* Register debug dump function key. */
1183 fkeys = sfkeys = 0;
1184 bit_set(sfkeys, 11);
1185 if ((r = fkey_map(&fkeys, &sfkeys)) != OK)
1186 printf("ATL2: warning, could not map Shift+F11 key (%d)\n", r);
1187 #endif
1189 return(OK);
1192 /*===========================================================================*
1193 * sef_cb_signal_handler *
1194 *===========================================================================*/
1195 static void sef_cb_signal_handler(int signo)
1197 /* In case of a termination signal, shut down this driver.
1198 * Stop the device, and deallocate resources as proof of concept.
1200 int r;
1202 /* Only check for termination signal, ignore anything else. */
1203 if (signo != SIGTERM) return;
1205 atl2_stop();
1207 if ((r = sys_irqrmpolicy(&state.hook_id)) != OK)
1208 panic("unable to deregister IRQ: %d", r);
1210 free_contig(state.txd_base, ATL2_TXD_BUFSIZE);
1211 free_contig(state.txs_base, ATL2_TXS_COUNT * sizeof(u32_t));
1212 free_contig(state.rxd_base_u,
1213 state.rxd_align + ATL2_RXD_COUNT * ATL2_RXD_SIZE);
1215 vm_unmap_phys(SELF, (void *) state.base, state.size);
1217 /* We cannot free the PCI device at this time. */
1219 exit(0);
1222 /*===========================================================================*
1223 * sef_local_startup *
1224 *===========================================================================*/
1225 static void sef_local_startup(void)
1227 /* Register init callbacks. */
1228 sef_setcb_init_fresh(sef_cb_init_fresh);
1229 sef_setcb_init_lu(sef_cb_init_fresh);
1230 sef_setcb_init_restart(sef_cb_init_fresh);
1232 /* Register live update callbacks. */
1233 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
1234 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
1236 /* Register signal callbacks. */
1237 sef_setcb_signal_handler(sef_cb_signal_handler);
1239 /* Let SEF perform startup. */
1240 sef_startup();
1243 /*===========================================================================*
1244 * main *
1245 *===========================================================================*/
1246 int main(int argc, char **argv)
1248 /* Driver task.
1250 message m;
1251 int ipc_status;
1252 int r;
1254 /* Initialize SEF. */
1255 env_setargs(argc, argv);
1256 sef_local_startup();
1258 while (TRUE) {
1259 if ((r = netdriver_receive(ANY, &m, &ipc_status)) != OK)
1260 panic("netdriver_receive failed: %d", r);
1262 if (is_ipc_notify(ipc_status)) {
1263 switch (m.m_source) {
1264 case HARDWARE: /* interrupt */
1265 atl2_intr(&m);
1267 break;
1269 case TTY_PROC_NR: /* function key */
1270 atl2_dump();
1272 break;
1274 default:
1275 printf("ATL2: illegal notify from %d\n",
1276 m.m_source);
1279 continue;
1282 /* Process requests from Inet. */
1283 switch (m.m_type) {
1284 case DL_CONF: atl2_conf(&m); break;
1285 case DL_GETSTAT_S: atl2_getstat(&m); break;
1286 case DL_WRITEV_S: atl2_writev(&m, FALSE); break;
1287 case DL_READV_S: atl2_readv(&m, FALSE); break;
1288 default:
1289 printf("ATL2: illegal message %d from %d\n",
1290 m.m_type, m.m_source);