xref: /minix/minix/drivers/net/atl2/atl2.c (revision 7f5f010b)
1 /* Attansic/Atheros L2 FastEthernet driver, by D.C. van Moolenbroek */
2 
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  */
6 
7 #include <minix/drivers.h>
8 #include <minix/netdriver.h>
9 
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>
17 
18 #include "atl2.h"
19 
20 #define VERBOSE		0	/* Verbose debugging output */
21 #define ATL2_FKEY	1	/* Register Shift+F11 for dumping statistics */
22 
23 #if VERBOSE
24 #define ATL2_DEBUG(x) printf x
25 #else
26 #define ATL2_DEBUG(x)
27 #endif
28 
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;
34 
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 */
43 
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 */
48 
49 	int rxd_align;		/* alignment offset of RxD ring buffer */
50 
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 */
54 
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 */
60 
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) */
66 
67 	eth_stat_t stat;	/* statistics */
68 } state;
69 
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 */
75 
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);
82 
83 #define ATL2_ALIGN_32(n) (((n) + 3) & ~3)
84 
85 static iovec_s_t iovec[NR_IOREQS];
86 
87 static int instance;
88 
89 /*===========================================================================*
90  *				atl2_read_vpd				     *
91  *===========================================================================*/
92 static int atl2_read_vpd(int index, u32_t *res)
93 {
94 	/* Read a value from the VPD register area.
95 	 */
96 	u32_t off, val;
97 	int i;
98 
99 	ATL2_WRITE_U32(ATL2_VPD_DATA_REG, 0);
100 
101 	off = ATL2_VPD_REGBASE + index * sizeof(u32_t);
102 
103 	ATL2_WRITE_U32(ATL2_VPD_CAP_REG,
104 		(off << ATL2_VPD_CAP_ADDR_SHIFT) & ATL2_VPD_CAP_ADDR_MASK);
105 
106 	for (i = 0; i < ATL2_VPD_NTRIES; i++) {
107 		micro_delay(ATL2_VPD_DELAY);
108 
109 		val = ATL2_READ_U32(ATL2_VPD_CAP_REG);
110 		if (val & ATL2_VPD_CAP_DONE)
111 			break;
112 	}
113 
114 	if (i == ATL2_VPD_NTRIES) {
115 		printf("ATL2: timeout reading EEPROM register %d\n", index);
116 		return FALSE;
117 	}
118 
119 	*res = ATL2_READ_U32(ATL2_VPD_DATA_REG);
120 	return TRUE;
121 }
122 
123 /*===========================================================================*
124  *				atl2_get_vpd_hwaddr			     *
125  *===========================================================================*/
126 static int atl2_get_vpd_hwaddr(void)
127 {
128 	/* Read the MAC address from the EEPROM, using the Vital Product Data
129 	 * register interface.
130 	 */
131 	u32_t key, val;
132 	int i, n, found[2];
133 
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);
139 	}
140 
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
146 
147 	/* Read out the set of key/value pairs. Look for the two parts that
148 	 * make up the MAC address.
149 	 */
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;
154 
155 		if ((key & ATL2_VPD_SIG_MASK) != ATL2_VPD_SIG)
156 			break;
157 
158 		key >>= ATL2_VPD_REG_SHIFT;
159 
160 		if (key != ATL2_HWADDR0_REG && key != ATL2_HWADDR1_REG)
161 			continue;
162 
163 		if (!atl2_read_vpd(i + 1, &val))
164 			break;
165 
166 		n = (key == ATL2_HWADDR1_REG);
167 		state.hwaddr[n] = val;
168 		found[n] = TRUE;
169 
170 		if (found[1 - n]) break;
171 	}
172 
173 	return found[0] && found[1];
174 }
175 
176 /*===========================================================================*
177  *				atl2_get_hwaddr				     *
178  *===========================================================================*/
179 static void atl2_get_hwaddr(void)
180 {
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.
183 	 */
184 
185 	if (!atl2_get_vpd_hwaddr()) {
186 		printf("ATL2: unable to read from VPD\n");
187 
188 		state.hwaddr[0] = ATL2_READ_U32(ATL2_HWADDR0_REG);
189 		state.hwaddr[1] = ATL2_READ_U32(ATL2_HWADDR1_REG) & 0xffff;
190 	}
191 
192 	ATL2_DEBUG(("ATL2: MAC address %04lx%08lx\n",
193 		state.hwaddr[1], state.hwaddr[0]));
194 }
195 
196 /*===========================================================================*
197  *				atl2_read_mdio				     *
198  *===========================================================================*/
199 static int atl2_read_mdio(int addr, u16_t *res)
200 {
201 	/* Read a MII PHY register using MDIO.
202 	 */
203 	u32_t rval;
204 	int i;
205 
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;
209 
210 	ATL2_WRITE_U32(ATL2_MDIO_REG, rval);
211 
212 	for (i = 0; i < ATL2_MDIO_NTRIES; i++) {
213 		micro_delay(ATL2_MDIO_DELAY);
214 
215 		rval = ATL2_READ_U32(ATL2_MDIO_REG);
216 
217 		if (!(rval & (ATL2_MDIO_START | ATL2_MDIO_BUSY)))
218 			break;
219 	}
220 
221 	if (i == ATL2_MDIO_NTRIES) return FALSE;
222 
223 	*res = (u16_t) (rval & ATL2_MDIO_DATA_MASK);
224 	return TRUE;
225 }
226 
227 /*===========================================================================*
228  *				atl2_alloc_dma				     *
229  *===========================================================================*/
230 static int atl2_alloc_dma(void)
231 {
232 	/* Allocate DMA ring buffers.
233 	 */
234 
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);
239 
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.
242 	 */
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);
247 
248 	/* Unlike mmap, alloc_contig returns NULL on failure. */
249 	if (!state.txd_base || !state.txs_base || !state.rxd_base_u)
250 		return ENOMEM;
251 
252 	state.rxd_base = (rxd_t *) (state.rxd_base_u + state.rxd_align);
253 	state.rxd_phys += state.rxd_align;
254 
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);
259 
260 	return OK;
261 }
262 
263 /*===========================================================================*
264  *				atl2_stop				     *
265  *===========================================================================*/
266 static int atl2_stop(void)
267 {
268 	/* Stop the device.
269 	 */
270 	u32_t val;
271 	int i;
272 
273 	/* Clear and disable interrupts. */
274 	ATL2_WRITE_U32(ATL2_IMR_REG, 0);
275 	ATL2_WRITE_U32(ATL2_ISR_REG, 0xffffffff);
276 
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);
282 	}
283 
284 	ATL2_WRITE_U8(ATL2_DMAWRITE_REG, 0);
285 	ATL2_WRITE_U8(ATL2_DMAREAD_REG, 0);
286 
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;
291 
292 		micro_delay(ATL2_IDLE_DELAY);
293 	}
294 
295 	/* The caller will generally ignore this return value. */
296 	return (i < ATL2_IDLE_NTRIES);
297 }
298 
299 /*===========================================================================*
300  *				atl2_reset				     *
301  *===========================================================================*/
302 static int atl2_reset(void)
303 {
304 	/* Reset the device to a known good state.
305 	 */
306 	u32_t val;
307 	int i;
308 
309 	/* Issue a soft reset, and wait for the device to respond. */
310 	ATL2_WRITE_U32(ATL2_MASTER_REG, ATL2_MASTER_SOFT_RESET);
311 
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;
316 
317 		micro_delay(ATL2_RESET_DELAY);
318 	}
319 
320 	if (i == ATL2_RESET_NTRIES)
321 		return FALSE;
322 
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;
327 
328 		micro_delay(ATL2_IDLE_DELAY);
329 	}
330 
331 	return (i < ATL2_IDLE_NTRIES);
332 }
333 
334 /*===========================================================================*
335  *				atl2_set_mode				     *
336  *===========================================================================*/
337 static void atl2_set_mode(void)
338 {
339 	/* Reconfigure the device's promiscuity, multicast, and broadcast mode
340 	 * settings.
341 	 */
342 	u32_t val;
343 
344 	val = ATL2_READ_U32(ATL2_MAC_REG);
345 	val &= ~(ATL2_MAC_PROMISC_EN | ATL2_MAC_MCAST_EN | ATL2_MAC_BCAST_EN);
346 
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;
353 
354 	ATL2_WRITE_U32(ATL2_MAC_REG, val);
355 }
356 
357 /*===========================================================================*
358  *				atl2_setup				     *
359  *===========================================================================*/
360 static int atl2_setup(void)
361 {
362 	/* Set up the device for normal operation.
363 	 */
364 	u32_t val;
365 
366 	atl2_stop();
367 
368 	if (!atl2_reset())
369 		return FALSE;
370 
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);
374 
375 	/* Enable PHY. */
376 	ATL2_WRITE_U32(ATL2_PHY_ENABLE_REG, ATL2_PHY_ENABLE);
377 	micro_delay(1000);
378 
379 	/* Clear and disable interrupts. */
380 	ATL2_WRITE_U32(ATL2_ISR_REG, 0xffffffff);
381 
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]);
385 
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);
391 
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);
395 
396 	/* A whole lot of other initialization copied from Linux/FreeBSD. */
397 	ATL2_WRITE_U32(ATL2_IFG_REG, ATL2_IFG_DEFAULT);
398 
399 	ATL2_WRITE_U32(ATL2_HDPX_REG, ATL2_HDPX_DEFAULT);
400 
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);
404 
405 	ATL2_WRITE_U16(ATL2_ICT_REG, ATL2_ICT_DEFAULT);
406 
407 	ATL2_WRITE_U32(ATL2_CUT_THRESH_REG, ATL2_CUT_THRESH_DEFAULT);
408 
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);
411 
412 	/* Set MTU. */
413 	ATL2_WRITE_U16(ATL2_MTU_REG, ATL2_MTU_DEFAULT);
414 
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);
421 
422 	ATL2_WRITE_U8(ATL2_DMAREAD_REG, ATL2_DMAREAD_EN);
423 	ATL2_WRITE_U8(ATL2_DMAWRITE_REG, ATL2_DMAWRITE_EN);
424 
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;
430 	}
431 
432 	/* Clear interrupt status. */
433 	ATL2_WRITE_U32(ATL2_ISR_REG, 0x3fffffff);
434 	ATL2_WRITE_U32(ATL2_ISR_REG, 0);
435 
436 	/* Enable interrupts. */
437 	ATL2_WRITE_U32(ATL2_IMR_REG, ATL2_IMR_DEFAULT);
438 
439 	/* Configure MAC. */
440 	ATL2_WRITE_U32(ATL2_MAC_REG, ATL2_MAC_DEFAULT);
441 
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.
444 	 */
445 	ATL2_WRITE_U32(ATL2_MHT0_REG, 0xffffffff);
446 	ATL2_WRITE_U32(ATL2_MHT1_REG, 0xffffffff);
447 
448 	atl2_set_mode();
449 
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);
453 
454 	return TRUE;
455 }
456 
457 /*===========================================================================*
458  *				atl2_probe				     *
459  *===========================================================================*/
460 static int atl2_probe(int skip)
461 {
462 	/* Find a matching PCI device.
463 	 */
464 	u16_t vid, did;
465 #if VERBOSE
466 	char *dname;
467 #endif
468 	int r, devind;
469 
470 	pci_init();
471 
472 	r = pci_first_dev(&devind, &vid, &did);
473 	if (r <= 0)
474 		return -1;
475 
476 	while (skip--) {
477 		r = pci_next_dev(&devind, &vid, &did);
478 		if (r <= 0)
479 			return -1;
480 	}
481 
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
488 
489 	pci_reserve(devind);
490 
491 	return devind;
492 }
493 
494 /*===========================================================================*
495  *				atl2_init				     *
496  *===========================================================================*/
497 static void atl2_init(int devind)
498 {
499 	/* Initialize the device.
500 	 */
501 	u32_t bar;
502 	int r, flag;
503 
504 	/* Initialize global state. */
505 	state.devind = devind;
506 	state.mode = DL_NOMODE;
507 	state.flags = 0;
508 	state.recv_count = 0;
509 
510 	memset(&state.stat, 0, sizeof(state.stat));
511 
512 	if ((r = pci_get_bar(devind, PCI_BAR, &bar, &state.size, &flag)) != OK)
513 		panic("unable to retrieve bar: %d", r);
514 
515 	if (state.size < ATL2_MIN_MMAP_SIZE || flag)
516 		panic("invalid register bar");
517 
518 	state.base = vm_map_phys(SELF, (void *) bar, state.size);
519 	if (state.base == MAP_FAILED)
520 		panic("unable to map in registers");
521 
522 	if ((r = atl2_alloc_dma()) != OK)
523 		panic("unable to allocate DMA buffers: %d", r);
524 
525 	state.irq = pci_attr_r8(devind, PCI_ILR);
526 	state.hook_id = 0;
527 
528 	if ((r = sys_irqsetpolicy(state.irq, 0, &state.hook_id)) != OK)
529 		panic("unable to register IRQ: %d", r);
530 
531 	if (!atl2_reset())
532 		panic("unable to reset hardware");
533 
534 	if ((r = sys_irqenable(&state.hook_id)) != OK)
535 		panic("unable to enable IRQ: %d", r);
536 
537 	atl2_get_hwaddr();
538 
539 	atl2_setup();
540 }
541 
542 /*===========================================================================*
543  *				atl2_tx_stat				     *
544  *===========================================================================*/
545 static void atl2_tx_stat(u32_t stat)
546 {
547 	/* Update statistics for packet transmission.
548 	 */
549 
550 	if (stat & ATL2_TXS_SUCCESS)
551 		state.stat.ets_packetT++;
552 	else
553 		state.stat.ets_recvErr++;
554 
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++;
567 }
568 
569 /*===========================================================================*
570  *				atl2_rx_stat				     *
571  *===========================================================================*/
572 static void atl2_rx_stat(u32_t stat)
573 {
574 	/* Update statistics for packet receipt.
575 	 */
576 
577 	if (stat & ATL2_RXD_SUCCESS)
578 		state.stat.ets_packetR++;
579 	else
580 		state.stat.ets_recvErr++;
581 
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++;
590 }
591 
592 /*===========================================================================*
593  *				atl2_tx_advance				     *
594  *===========================================================================*/
595 static int atl2_tx_advance(void)
596 {
597 	/* Advance the TxD/TxS tails by as many sent packets as found.
598 	 */
599 	u32_t stat, size, dsize;
600 	int advanced;
601 
602 	advanced = FALSE;
603 
604 	while (state.txs_num > 0) {
605 		/* Has the tail packet been processed by the driver? */
606 		stat = state.txs_base[state.txs_tail];
607 
608 		if (!(stat & ATL2_TXS_UPDATE))
609 			break;
610 
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..
613 		 */
614 		size = stat & ATL2_TXS_SIZE_MASK;
615 
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);
622 
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;
628 
629 		state.txs_tail = (state.txs_tail + 1) % ATL2_TXS_COUNT;
630 		state.txs_num--;
631 
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"));
636 		}
637 
638 		/* Update statistics. */
639 		atl2_tx_stat(stat);
640 
641 		advanced = TRUE;
642 	}
643 
644 	return advanced;
645 }
646 
647 /*===========================================================================*
648  *				atl2_rx_advance				     *
649  *===========================================================================*/
650 static void atl2_rx_advance(int next)
651 {
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.
655 	 */
656 	int update_tail;
657 	rxd_t *rxd;
658 	u32_t hdr, size;
659 
660 	update_tail = FALSE;
661 
662 	if (next) {
663 		state.rxd_tail = (state.rxd_tail + 1) % ATL2_RXD_COUNT;
664 		update_tail = TRUE;
665 
666 		ATL2_DEBUG(("ATL2: successfully received packet\n"));
667 
668 		state.flags &= ~ATL2_FLAG_RX_AVAIL;
669 	}
670 
671 	assert(!(state.flags & ATL2_FLAG_RX_AVAIL));
672 
673 	for (;;) {
674 		/* Check the RxD tail for updates. */
675 		rxd = &state.rxd_base[state.rxd_tail];
676 
677 		hdr = rxd->hdr;
678 
679 		if (!(hdr & ATL2_RXD_UPDATE))
680 			break;
681 
682 		rxd->hdr = hdr & ~(ATL2_RXD_UPDATE);
683 
684 		/* Update statistics. */
685 		atl2_rx_stat(hdr);
686 
687 		/* Stop at the first successful receipt. The packet will be
688 		 * picked up by Inet later.
689 		 */
690 		size = hdr & ATL2_RXD_SIZE_MASK;
691 
692 		if ((hdr & ATL2_RXD_SUCCESS) && size >= ETH_MIN_PACK_SIZE) {
693 			ATL2_DEBUG(("ATL2: packet available, size %ld\n",
694 				size));
695 
696 			state.flags |= ATL2_FLAG_RX_AVAIL;
697 			break;
698 		}
699 
700 		ATL2_DEBUG(("ATL2: packet receipt failed\n"));
701 
702 		/* Advance tail. */
703 		state.rxd_tail = (state.rxd_tail + 1) % ATL2_RXD_COUNT;
704 		update_tail = TRUE;
705 	}
706 
707 	/* If new RxD descriptors are now up for reuse, tell the device. */
708 	if (update_tail) {
709 		__insn_barrier();
710 
711 		ATL2_WRITE_U32(ATL2_RXD_IDX_REG, state.rxd_tail);
712 	}
713 }
714 
715 /*===========================================================================*
716  *				atl2_reply				     *
717  *===========================================================================*/
718 static void atl2_reply(void)
719 {
720 	/* Send a task reply to Inet.
721 	 */
722 	message m;
723 	int r, flags;
724 
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;
730 
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;
734 
735 	ATL2_DEBUG(("ATL2: sending reply, flags %x count %d\n", flags,
736 		m.m_netdrv_net_dl_task.count));
737 
738 	if ((r = ipc_send(state.task_endpt, &m)) != OK)
739 		panic("unable to reply: %d", r);
740 
741 	state.flags &= ~(ATL2_FLAG_PACK_SENT | ATL2_FLAG_PACK_RCVD);
742 	state.recv_count = 0;
743 }
744 
745 /*===========================================================================*
746  *				atl2_readv				     *
747  *===========================================================================*/
748 static void atl2_readv(const message *m, int from_int)
749 {
750 	/* Read packet data.
751 	 */
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;
757 
758 	/* We can deal with only one read request from Inet at a time. */
759 	assert(from_int || !(state.flags & ATL2_FLAG_READ_PEND));
760 
761 	state.task_endpt = m->m_source;
762 
763 	/* Are there any packets available at all? */
764 	if (!(state.flags & ATL2_FLAG_RX_AVAIL))
765 		goto suspend;
766 
767 	/* Get the first available packet's size. Cut off the CRC. */
768 	rxd = &state.rxd_base[state.rxd_tail];
769 
770 	count = rxd->hdr & ATL2_RXD_SIZE_MASK;
771 	count -= ETH_CRC_SIZE;
772 
773 	ATL2_DEBUG(("ATL2: readv: found packet with length %d\n", count));
774 
775 	/* Copy out the packet. */
776 	off = 0;
777 	left = count;
778 	pos = rxd->data;
779 
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);
783 
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);
789 
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);
793 
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);
798 
799 			pos += size;
800 			left -= size;
801 		}
802 
803 		off += batch * sizeof(iovec[0]);
804 	}
805 
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;
811 	}
812 
813 	/* We are done with this packet. Move on to the next. */
814 	atl2_rx_advance(TRUE /*next*/);
815 
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;
820 
821 	/* If called from the interrupt handler, the caller will reply. */
822 	if (!from_int)
823 		atl2_reply();
824 
825 	return;
826 
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.
831 	 */
832 	if (from_int)
833 		return;
834 
835 	state.flags |= ATL2_FLAG_READ_PEND;
836 	state.read_msg = *m;
837 
838 	atl2_reply();
839 }
840 
841 /*===========================================================================*
842  *				atl2_writev				     *
843  *===========================================================================*/
844 static void atl2_writev(const message *m, int from_int)
845 {
846 	/* Write packet data.
847 	 */
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;
853 
854 	/* We can deal with only one write request from Inet at a time. */
855 	assert(from_int || !(state.flags & ATL2_FLAG_WRITE_PEND));
856 
857 	state.task_endpt = m->m_source;
858 
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.
862 	 */
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;
868 
869 	/* Optimistically try to copy in the data; suspend if it turns out
870 	 * that it does not fit.
871 	 */
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;
877 
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);
881 
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);
887 
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;
893 
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;
904 			}
905 
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);
911 
912 			pos = (pos + size - skip) % ATL2_TXD_BUFSIZE;
913 			left -= size;
914 			count += size;
915 		}
916 
917 		off += batch * sizeof(iovec[0]);
918 	}
919 
920 	assert(count <= ETH_MAX_PACK_SIZE_TAGGED);
921 
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;
926 
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);
932 
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++;
936 
937 	/* Tell the device about our new position. */
938 	__insn_barrier();
939 
940 	ATL2_WRITE_U32(ATL2_TXD_IDX_REG, pos / sizeof(u32_t));
941 
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;
945 
946 	/* If called from the interrupt handler, the caller will reply. */
947 	if (!from_int)
948 		atl2_reply();
949 
950 	return;
951 
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.
956 	 */
957 	if (from_int)
958 		return;
959 
960 	state.flags |= ATL2_FLAG_WRITE_PEND;
961 	state.write_msg = *m;
962 
963 	atl2_reply();
964 }
965 
966 /*===========================================================================*
967  *				atl2_intr				     *
968  *===========================================================================*/
969 static void atl2_intr(const message *UNUSED(m))
970 {
971 	/* Interrupt received.
972 	 */
973 	u32_t val;
974 	int r, try_write, try_read;
975 
976 	/* Clear and disable interrupts. */
977 	val = ATL2_READ_U32(ATL2_ISR_REG);
978 
979 	ATL2_WRITE_U32(ATL2_ISR_REG, val | ATL2_ISR_DISABLE);
980 
981 	ATL2_DEBUG(("ATL2: interrupt (0x%08lx)\n", val));
982 
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();
987 	}
988 
989 	try_write = try_read = FALSE;
990 
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);
995 	}
996 
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*/);
1001 
1002 			try_read = (state.flags & ATL2_FLAG_READ_PEND);
1003 		}
1004 	}
1005 
1006 	/* Reenable interrupts. */
1007 	ATL2_WRITE_U32(ATL2_ISR_REG, 0);
1008 
1009 	if ((r = sys_irqenable(&state.hook_id)) != OK)
1010 		panic("unable to enable IRQ: %d", r);
1011 
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();
1019 }
1020 
1021 /*===========================================================================*
1022  *				atl2_conf				     *
1023  *===========================================================================*/
1024 static void atl2_conf(message *m)
1025 {
1026 	/* Configure the mode of the card.
1027 	 */
1028 	ether_addr_t addr;
1029 	int r;
1030 
1031 	state.mode = m->m_net_netdrv_dl_conf.mode;
1032 
1033 	atl2_set_mode();
1034 
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;
1041 
1042 	memcpy(m->m_netdrv_net_dl_conf.hw_addr, &addr,
1043 		sizeof(m->m_netdrv_net_dl_conf.hw_addr));
1044 
1045 	m->m_type = DL_CONF_REPLY;
1046 	m->m_netdrv_net_dl_conf.stat = OK;
1047 
1048 	if ((r = ipc_send(m->m_source, m)) != OK)
1049 		printf("ATL2: unable to send reply (%d)\n", r);
1050 }
1051 
1052 /*===========================================================================*
1053  *				atl2_getstat				     *
1054  *===========================================================================*/
1055 static void atl2_getstat(message *m)
1056 {
1057 	/* Copy out statistics.
1058 	 */
1059 	int r;
1060 
1061 	sys_safecopyto(m->m_source, m->m_net_netdrv_dl_getstat_s.grant, 0,
1062 		(vir_bytes) &state.stat, sizeof(state.stat));
1063 
1064 	m->m_type = DL_STAT_REPLY;
1065 
1066 	if ((r = ipc_send(m->m_source, m)) != OK)
1067 		printf("ATL2: unable to send reply (%d)\n", r);
1068 }
1069 
1070 /*===========================================================================*
1071  *				atl2_dump_link				     *
1072  *===========================================================================*/
1073 static void atl2_dump_link(void)
1074 {
1075 	/* Dump link status.
1076 	 */
1077 	u16_t val;
1078 	int link_up;
1079 
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;
1083 
1084 	link_up = val & ATL2_MII_BMSR_LSTATUS;
1085 	printf("link status:     %4s\t", link_up ? "up" : "down");
1086 
1087 	if (!link_up) return;
1088 
1089 	if (!atl2_read_mdio(ATL2_MII_PSSR, &val)) return;
1090 
1091 	if (!(val & ATL2_MII_PSSR_RESOLVED)) {
1092 		printf("(not resolved)\n");
1093 
1094 		return;
1095 	}
1096 
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, ");
1102 	}
1103 
1104 	printf("%s duplex)", (val & ATL2_MII_PSSR_DUPLEX) ? "full" : "half");
1105 }
1106 
1107 /*===========================================================================*
1108  *				atl2_dump				     *
1109  *===========================================================================*/
1110 static void atl2_dump(void)
1111 {
1112 	/* Dump statistics.
1113 	 */
1114 
1115 	printf("\n");
1116 	printf("Attansic L2 statistics:\n");
1117 
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);
1121 
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);
1125 
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);
1129 
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);
1133 
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);
1137 
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);
1141 
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);
1145 
1146 	printf("flags:         0x%04x\t", state.flags);
1147 	atl2_dump_link();
1148 	printf("\n");
1149 }
1150 
1151 /*===========================================================================*
1152  *		            sef_cb_init_fresh                                *
1153  *===========================================================================*/
1154 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
1155 {
1156 	/* Initialize the atl2 driver.
1157 	 */
1158 	int r, devind;
1159 	long v;
1160 #if ATL2_FKEY
1161 	int fkeys, sfkeys;
1162 #endif
1163 
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;
1168 
1169 	/* Try to find a recognized device. */
1170 	devind = atl2_probe(instance);
1171 
1172 	if (devind < 0)
1173 		panic("no matching device found");
1174 
1175 	/* Initialize the device. */
1176 	atl2_init(devind);
1177 
1178 	/* Announce we are up! */
1179 	netdriver_announce();
1180 
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
1188 
1189 	return(OK);
1190 }
1191 
1192 /*===========================================================================*
1193  *			    sef_cb_signal_handler			     *
1194  *===========================================================================*/
1195 static void sef_cb_signal_handler(int signo)
1196 {
1197 	/* In case of a termination signal, shut down this driver.
1198 	 * Stop the device, and deallocate resources as proof of concept.
1199 	 */
1200 	int r;
1201 
1202 	/* Only check for termination signal, ignore anything else. */
1203 	if (signo != SIGTERM) return;
1204 
1205 	atl2_stop();
1206 
1207 	if ((r = sys_irqrmpolicy(&state.hook_id)) != OK)
1208 		panic("unable to deregister IRQ: %d", r);
1209 
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);
1214 
1215 	vm_unmap_phys(SELF, (void *) state.base, state.size);
1216 
1217 	/* We cannot free the PCI device at this time. */
1218 
1219 	exit(0);
1220 }
1221 
1222 /*===========================================================================*
1223  *				sef_local_startup			     *
1224  *===========================================================================*/
1225 static void sef_local_startup(void)
1226 {
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);
1231 
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);
1235 
1236 	/* Register signal callbacks. */
1237 	sef_setcb_signal_handler(sef_cb_signal_handler);
1238 
1239 	/* Let SEF perform startup. */
1240 	sef_startup();
1241 }
1242 
1243 /*===========================================================================*
1244  *				main					     *
1245  *===========================================================================*/
1246 int main(int argc, char **argv)
1247 {
1248 	/* Driver task.
1249 	 */
1250 	message m;
1251 	int ipc_status;
1252 	int r;
1253 
1254 	/* Initialize SEF. */
1255 	env_setargs(argc, argv);
1256 	sef_local_startup();
1257 
1258 	while (TRUE) {
1259 		if ((r = netdriver_receive(ANY, &m, &ipc_status)) != OK)
1260 			panic("netdriver_receive failed: %d", r);
1261 
1262 		if (is_ipc_notify(ipc_status)) {
1263 			switch (m.m_source) {
1264 			case HARDWARE:		/* interrupt */
1265 				atl2_intr(&m);
1266 
1267 				break;
1268 
1269 			case TTY_PROC_NR:	/* function key */
1270 				atl2_dump();
1271 
1272 				break;
1273 
1274 			default:
1275 				printf("ATL2: illegal notify from %d\n",
1276 					m.m_source);
1277 			}
1278 
1279 			continue;
1280 		}
1281 
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);
1291 		}
1292 	}
1293 }
1294