xref: /minix/minix/drivers/net/rtl8169/rtl8169.c (revision 7f5f010b)
1 /*
2  * rtl8169.c
3  *
4  * This file contains a ethernet device driver for Realtek rtl8169 based
5  * ethernet cards.
6  *
7  */
8 
9 #include <minix/drivers.h>
10 #include <minix/netdriver.h>
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <minix/com.h>
16 #include <minix/ds.h>
17 #include <minix/syslib.h>
18 #include <minix/type.h>
19 #include <minix/sysutil.h>
20 #include <minix/endpoint.h>
21 #include <minix/timers.h>
22 #include <net/hton.h>
23 #include <net/gen/ether.h>
24 #include <net/gen/eth_io.h>
25 #include <machine/pci.h>
26 
27 #include <sys/types.h>
28 #include <assert.h>
29 #include <unistd.h>
30 #include "kernel/const.h"
31 #include "kernel/config.h"
32 #include "kernel/type.h"
33 
34 #define VERBOSE		0		/* display message during init */
35 
36 #include "rtl8169.h"
37 
38 #define IOVEC_NR	16		/* I/O vectors are handled IOVEC_NR entries at a time. */
39 
40 #define RE_DTCC_VALUE	600		/* DTCC Update after every 10 minutes */
41 
42 #define RX_CONFIG_MASK	0xff7e1880	/* Clears the bits supported by chip */
43 
44 #define RE_INTR_MASK	(RL_IMR_TDU | RL_IMR_FOVW | RL_IMR_PUN | RL_IMR_RDU | RL_IMR_TER | RL_IMR_TOK | RL_IMR_RER | RL_IMR_ROK)
45 
46 #define RL_ENVVAR	"RTLETH"	/* Configuration */
47 
48 typedef struct re_desc
49 {
50 	u32_t status;		/* command/status */
51 	u32_t vlan;		/* VLAN */
52 	u32_t addr_low;		/* low 32-bits of physical buffer address */
53 	u32_t addr_high;	/* high 32-bits of physical buffer address */
54 } re_desc;
55 
56 typedef struct re_dtcc
57 {
58 	u32_t	TxOk_low;	/* low 32-bits of Tx Ok packets */
59 	u32_t	TxOk_high;	/* high 32-bits of Tx Ok packets */
60 	u32_t	RxOk_low;	/* low 32-bits of Rx Ok packets */
61 	u32_t	RxOk_high;	/* high 32-bits of Rx Ok packets */
62 	u32_t	TxEr_low;	/* low 32-bits of Tx errors */
63 	u32_t	TxEr_high;	/* high 32-bits of Tx errors */
64 	u32_t	RxEr;		/* Rx errors */
65 	u16_t	MissPkt;	/* Missed packets */
66 	u16_t	FAE;		/* Frame Aignment Error packets (MII mode only) */
67 	u32_t	Tx1Col;		/* Tx Ok packets with only 1 collision happened before Tx Ok */
68 	u32_t	TxMCol;		/* Tx Ok packets with > 1 and < 16 collisions happened before Tx Ok */
69 	u32_t	RxOkPhy_low;	/* low 32-bits of Rx Ok packets with physical addr destination ID */
70 	u32_t	RxOkPhy_high;	/* high 32-bits of Rx Ok packets with physical addr destination ID */
71 	u32_t	RxOkBrd_low;	/* low 32-bits of Rx Ok packets with broadcast destination ID */
72 	u32_t	RxOkBrd_high;	/* high 32-bits of Rx Ok packets with broadcast destination ID */
73 	u32_t	RxOkMul;	/* Rx Ok Packets with multicast destination ID */
74 	u16_t	TxAbt;		/* Tx abort packets */
75 	u16_t	TxUndrn;	/* Tx underrun packets */
76 } re_dtcc;
77 
78 typedef struct re {
79 	port_t re_base_port;
80 	int re_irq;
81 	int re_mode;
82 	int re_flags;
83 	endpoint_t re_client;
84 	int re_link_up;
85 	int re_got_int;
86 	int re_send_int;
87 	int re_report_link;
88 	int re_need_reset;
89 	int re_tx_alive;
90 	int setup;
91 	u32_t re_mac;
92 	char *re_model;
93 
94 	/* Rx */
95 	int re_rx_head;
96 	struct {
97 		int ret_busy;
98 		phys_bytes ret_buf;
99 		char *v_ret_buf;
100 	} re_rx[N_RX_DESC];
101 
102 	vir_bytes re_read_s;
103 	re_desc *re_rx_desc;	/* Rx descriptor buffer */
104 	phys_bytes p_rx_desc;	/* Rx descriptor buffer physical */
105 
106 	/* Tx */
107 	int re_tx_head;
108 	struct {
109 		int ret_busy;
110 		phys_bytes ret_buf;
111 		char *v_ret_buf;
112 	} re_tx[N_TX_DESC];
113 	re_desc *re_tx_desc;	/* Tx descriptor buffer */
114 	phys_bytes p_tx_desc;	/* Tx descriptor buffer physical */
115 
116 	/* PCI related */
117 	int re_seen;		/* TRUE iff device available */
118 
119 	/* 'large' items */
120 	int re_hook_id;		/* IRQ hook id at kernel */
121 	eth_stat_t re_stat;
122 	phys_bytes dtcc_buf;	/* Dump Tally Counter buffer physical */
123 	re_dtcc *v_dtcc_buf;	/* Dump Tally Counter buffer */
124 	u32_t dtcc_counter;	/* DTCC update counter */
125 	ether_addr_t re_address;
126 	message re_rx_mess;
127 	message re_tx_mess;
128 	char re_name[sizeof("rtl8169#n")];
129 	iovec_t re_iovec[IOVEC_NR];
130 	iovec_s_t re_iovec_s[IOVEC_NR];
131 	u32_t interrupts;
132 }
133 re_t;
134 
135 #define REM_DISABLED	0x0
136 #define REM_ENABLED	0x1
137 
138 #define REF_PACK_SENT	0x001
139 #define REF_PACK_RECV	0x002
140 #define REF_SEND_AVAIL	0x004
141 #define REF_READING	0x010
142 #define REF_EMPTY	0x000
143 #define REF_PROMISC	0x040
144 #define REF_MULTI	0x080
145 #define REF_BROAD	0x100
146 #define REF_ENABLED	0x200
147 
148 static re_t re_state;
149 
150 static int re_instance;
151 
152 static unsigned my_inb(u16_t port)
153 {
154 	u32_t value;
155 	int s;
156 	if ((s = sys_inb(port, &value)) != OK)
157 		printf("RTL8169: warning, sys_inb failed: %d\n", s);
158 	return value;
159 }
160 static unsigned my_inw(u16_t port)
161 {
162 	u32_t value;
163 	int s;
164 	if ((s = sys_inw(port, &value)) != OK)
165 		printf("RTL8169: warning, sys_inw failed: %d\n", s);
166 	return value;
167 }
168 static unsigned my_inl(u16_t port)
169 {
170 	u32_t value;
171 	int s;
172 	if ((s = sys_inl(port, &value)) != OK)
173 		printf("RTL8169: warning, sys_inl failed: %d\n", s);
174 	return value;
175 }
176 #define rl_inb(port, offset)	(my_inb((port) + (offset)))
177 #define rl_inw(port, offset)	(my_inw((port) + (offset)))
178 #define rl_inl(port, offset)	(my_inl((port) + (offset)))
179 
180 static void my_outb(u16_t port, u8_t value)
181 {
182 	int s;
183 
184 	if ((s = sys_outb(port, value)) != OK)
185 		printf("RTL8169: warning, sys_outb failed: %d\n", s);
186 }
187 static void my_outw(u16_t port, u16_t value)
188 {
189 	int s;
190 
191 	if ((s = sys_outw(port, value)) != OK)
192 		printf("RTL8169: warning, sys_outw failed: %d\n", s);
193 }
194 static void my_outl(u16_t port, u32_t value)
195 {
196 	int s;
197 
198 	if ((s = sys_outl(port, value)) != OK)
199 		printf("RTL8169: warning, sys_outl failed: %d\n", s);
200 }
201 #define rl_outb(port, offset, value)	(my_outb((port) + (offset), (value)))
202 #define rl_outw(port, offset, value)	(my_outw((port) + (offset), (value)))
203 #define rl_outl(port, offset, value)	(my_outl((port) + (offset), (value)))
204 
205 static void rl_init(message *mp);
206 static void rl_pci_conf(void);
207 static int rl_probe(re_t *rep, int skip);
208 static void rl_conf_hw(re_t *rep);
209 static void rl_init_buf(re_t *rep);
210 static void rl_init_hw(re_t *rep);
211 static void rl_reset_hw(re_t *rep);
212 static void rl_confaddr(re_t *rep);
213 static void rl_rec_mode(re_t *rep);
214 static void rl_readv_s(const message *mp, int from_int);
215 static void rl_writev_s(const message *mp, int from_int);
216 static void rl_check_ints(re_t *rep);
217 static void rl_report_link(re_t *rep);
218 static void rl_do_reset(re_t *rep);
219 static void rl_getstat_s(message *mp);
220 static void reply(re_t *rep);
221 static void mess_reply(message *req, message *reply);
222 static void check_int_events(void);
223 static void do_hard_int(void);
224 static void dump_phy(const re_t *rep);
225 static void rl_handler(re_t *rep);
226 static void rl_watchdog_f(minix_timer_t *tp);
227 
228 /*
229  * The message used in the main loop is made global, so that rl_watchdog_f()
230  * can change its message type to fake an interrupt message.
231  */
232 static message m;
233 static int int_event_check;		/* set to TRUE if events arrived */
234 
235 u32_t system_hz;
236 
237 /* SEF functions and variables. */
238 static void sef_local_startup(void);
239 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
240 static void sef_cb_signal_handler(int signo);
241 
242 /*===========================================================================*
243  *				main					     *
244  *===========================================================================*/
245 int main(int argc, char *argv[])
246 {
247 	int r;
248 	int ipc_status;
249 
250 	/* SEF local startup. */
251 	env_setargs(argc, argv);
252 	sef_local_startup();
253 
254 	while (TRUE) {
255 		if ((r = netdriver_receive(ANY, &m, &ipc_status)) != OK)
256 			panic("netdriver_receive failed: %d", r);
257 
258 		if (is_ipc_notify(ipc_status)) {
259 			switch (_ENDPOINT_P(m.m_source)) {
260 			case CLOCK:
261 				/*
262 				 * Under MINIX, synchronous alarms are used
263 				 * instead of watchdog functions.
264 				 * The approach is very different: MINIX VMD
265 				 * timeouts are handled within the kernel
266 				 * (the watchdog is executed by CLOCK), and
267 				 * notify() the driver in some cases. MINIX
268 				 * timeouts result in a SYN_ALARM message to
269 				 * the driver and thus are handled where they
270 				 * should be handled. Locally, watchdog
271 				 * functions are used again.
272 				 */
273 				rl_watchdog_f(NULL);
274 				break;
275 			case HARDWARE:
276 				do_hard_int();
277 				if (int_event_check) {
278 					check_int_events();
279 				}
280 				break ;
281 			default:
282 				panic("illegal notify from: %d",	m.m_type);
283 			}
284 
285 			/* done, get nwe message */
286 			continue;
287 		}
288 
289 		switch (m.m_type) {
290 		case DL_WRITEV_S:	rl_writev_s(&m, FALSE);	 break;
291 		case DL_READV_S:	rl_readv_s(&m, FALSE);	 break;
292 		case DL_CONF:		rl_init(&m);		 break;
293 		case DL_GETSTAT_S:	rl_getstat_s(&m);	 break;
294 		default:
295 			panic("illegal message: %d", m.m_type);
296 		}
297 	}
298 }
299 
300 /*===========================================================================*
301  *			       sef_local_startup			     *
302  *===========================================================================*/
303 static void sef_local_startup()
304 {
305   /* Register init callbacks. */
306   sef_setcb_init_fresh(sef_cb_init_fresh);
307   sef_setcb_init_lu(sef_cb_init_fresh);
308   sef_setcb_init_restart(sef_cb_init_fresh);
309 
310   /* Register live update callbacks. */
311   sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
312   sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
313 
314   /* Register signal callbacks. */
315   sef_setcb_signal_handler(sef_cb_signal_handler);
316 
317   /* Let SEF perform startup. */
318   sef_startup();
319 }
320 
321 /*===========================================================================*
322  *		            sef_cb_init_fresh                                *
323  *===========================================================================*/
324 static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
325 {
326 /* Initialize the rtl8169 driver. */
327 	long v;
328 
329 	system_hz = sys_hz();
330 
331 	v = 0;
332 	(void) env_parse("instance", "d", 0, &v, 0, 255);
333 	re_instance = (int) v;
334 
335 	/* Claim buffer memory now. */
336 	rl_init_buf(&re_state);
337 
338 	/* Announce we are up! */
339 	netdriver_announce();
340 
341 	return(OK);
342 }
343 
344 /*===========================================================================*
345  *		           sef_cb_signal_handler                             *
346  *===========================================================================*/
347 static void sef_cb_signal_handler(int signo)
348 {
349 	re_t *rep;
350 
351 	/* Only check for termination signal, ignore anything else. */
352 	if (signo != SIGTERM) return;
353 
354 	rep = &re_state;
355 	if (rep->re_mode == REM_ENABLED)
356 		rl_outb(rep->re_base_port, RL_CR, RL_CR_RST);
357 
358 	exit(0);
359 }
360 
361 static void mdio_write(u16_t port, int regaddr, int value)
362 {
363 	int i;
364 
365 	rl_outl(port,  RL_PHYAR, 0x80000000 | (regaddr & 0x1F) << 16 | (value & 0xFFFF));
366 
367 	for (i = 20; i > 0; i--) {
368 		/*
369 		 * Check if the RTL8169 has completed writing to the specified
370 		 * MII register
371 		 */
372 		if (!(rl_inl(port, RL_PHYAR) & 0x80000000))
373 			break;
374 		else
375 			micro_delay(50);
376 	}
377 }
378 
379 static int mdio_read(u16_t port, int regaddr)
380 {
381 	int i, value = -1;
382 
383 	rl_outl(port, RL_PHYAR, (regaddr & 0x1F) << 16);
384 
385 	for (i = 20; i > 0; i--) {
386 		/*
387 		 * Check if the RTL8169 has completed retrieving data from
388 		 * the specified MII register
389 		 */
390 		if (rl_inl(port, RL_PHYAR) & 0x80000000) {
391 			value = (int)(rl_inl(port, RL_PHYAR) & 0xFFFF);
392 			break;
393 		} else
394 			micro_delay(50);
395 	}
396 	return value;
397 }
398 
399 /*===========================================================================*
400  *				check_int_events			     *
401  *===========================================================================*/
402 static void check_int_events(void)
403 {
404 	re_t *rep;
405 
406 	rep = &re_state;
407 
408 	if (rep->re_mode != REM_ENABLED)
409 		return;
410 	if (!rep->re_got_int)
411 		return;
412 	rep->re_got_int = 0;
413 	assert(rep->re_flags & REF_ENABLED);
414 	rl_check_ints(rep);
415 }
416 
417 static void rtl8169_update_stat(re_t *rep)
418 {
419 	port_t port;
420 	int i;
421 
422 	port = rep->re_base_port;
423 
424 	/* Fetch Missed Packets */
425 	rep->re_stat.ets_missedP += rl_inw(port, RL_MPC);
426 	rl_outw(port, RL_MPC, 0x00);
427 
428 	/* Dump Tally Counter Command */
429 	rl_outl(port, RL_DTCCR_HI, 0);		/* 64 bits */
430 	rl_outl(port, RL_DTCCR_LO, rep->dtcc_buf | RL_DTCCR_CMD);
431 	for (i = 0; i < 1000; i++) {
432 		if (!(rl_inl(port, RL_DTCCR_LO) & RL_DTCCR_CMD))
433 			break;
434 		micro_delay(10);
435 	}
436 
437 	/* Update counters */
438 	rep->re_stat.ets_frameAll = rep->v_dtcc_buf->FAE;
439 	rep->re_stat.ets_transDef = rep->v_dtcc_buf->TxUndrn;
440 	rep->re_stat.ets_transAb = rep->v_dtcc_buf->TxAbt;
441 	rep->re_stat.ets_collision =
442 		rep->v_dtcc_buf->Tx1Col + rep->v_dtcc_buf->TxMCol;
443 }
444 
445 #if 0
446 /*===========================================================================*
447  *				rtl8169_dump				     *
448  *===========================================================================*/
449 static void rtl8169_dump(void)
450 {
451 	re_dtcc *dtcc;
452 	re_t *rep;
453 
454 	rep = &re_state;
455 
456 	printf("\n");
457 	if (rep->re_mode == REM_DISABLED)
458 		printf("Realtek RTL 8169 instance %d is disabled\n",
459 			re_instance);
460 
461 	if (rep->re_mode != REM_ENABLED)
462 		return;
463 
464 	rtl8169_update_stat(rep);
465 
466 	printf("Realtek RTL 8169 statistics of instance %d:\n", re_instance);
467 
468 	printf("recvErr    :%8ld\t", rep->re_stat.ets_recvErr);
469 	printf("sendErr    :%8ld\t", rep->re_stat.ets_sendErr);
470 	printf("OVW        :%8ld\n", rep->re_stat.ets_OVW);
471 
472 	printf("CRCerr     :%8ld\t", rep->re_stat.ets_CRCerr);
473 	printf("frameAll   :%8ld\t", rep->re_stat.ets_frameAll);
474 	printf("missedP    :%8ld\n", rep->re_stat.ets_missedP);
475 
476 	printf("packetR    :%8ld\t", rep->re_stat.ets_packetR);
477 	printf("packetT    :%8ld\t", rep->re_stat.ets_packetT);
478 	printf("transDef   :%8ld\n", rep->re_stat.ets_transDef);
479 
480 	printf("collision  :%8ld\t", rep->re_stat.ets_collision);
481 	printf("transAb    :%8ld\t", rep->re_stat.ets_transAb);
482 	printf("carrSense  :%8ld\n", rep->re_stat.ets_carrSense);
483 
484 	printf("fifoUnder  :%8ld\t", rep->re_stat.ets_fifoUnder);
485 	printf("fifoOver   :%8ld\t", rep->re_stat.ets_fifoOver);
486 	printf("OWC        :%8ld\n", rep->re_stat.ets_OWC);
487 	printf("interrupts :%8lu\n", rep->interrupts);
488 
489 	printf("\nRealtek RTL 8169 Tally Counters:\n");
490 
491 	dtcc = rep->v_dtcc_buf;
492 
493 	if (dtcc->TxOk_high)
494 		printf("TxOk       :%8ld%08ld\t", dtcc->TxOk_high, dtcc->TxOk_low);
495 	else
496 		printf("TxOk       :%16lu\t", dtcc->TxOk_low);
497 
498 	if (dtcc->RxOk_high)
499 		printf("RxOk       :%8ld%08ld\n", dtcc->RxOk_high, dtcc->RxOk_low);
500 	else
501 		printf("RxOk       :%16lu\n", dtcc->RxOk_low);
502 
503 	if (dtcc->TxEr_high)
504 		printf("TxEr       :%8ld%08ld\t", dtcc->TxEr_high, dtcc->TxEr_low);
505 	else
506 		printf("TxEr       :%16ld\t", dtcc->TxEr_low);
507 
508 	printf("RxEr       :%16ld\n", dtcc->RxEr);
509 
510 	printf("Tx1Col     :%16ld\t", dtcc->Tx1Col);
511 	printf("TxMCol     :%16ld\n", dtcc->TxMCol);
512 
513 	if (dtcc->RxOkPhy_high)
514 		printf("RxOkPhy    :%8ld%08ld\t", dtcc->RxOkPhy_high, dtcc->RxOkPhy_low);
515 	else
516 		printf("RxOkPhy    :%16ld\t", dtcc->RxOkPhy_low);
517 
518 	if (dtcc->RxOkBrd_high)
519 		printf("RxOkBrd    :%8ld%08ld\n", dtcc->RxOkBrd_high, dtcc->RxOkBrd_low);
520 	else
521 		printf("RxOkBrd    :%16ld\n", dtcc->RxOkBrd_low);
522 
523 	printf("RxOkMul    :%16ld\t", dtcc->RxOkMul);
524 	printf("MissPkt    :%16d\n", dtcc->MissPkt);
525 
526 	printf("\nRealtek RTL 8169 Miscellaneous Info:\n");
527 
528 	printf("re_flags   :      0x%08x\n", rep->re_flags);
529 	printf("tx_head    :%8d  busy %d\t",
530 		rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
531 }
532 #endif
533 
534 /*===========================================================================*
535  *				do_init					     *
536  *===========================================================================*/
537 static void rl_init(mp)
538 message *mp;
539 {
540 	static int first_time = 1;
541 
542 	re_t *rep;
543 	message reply_mess;
544 
545 	if (first_time) {
546 		first_time = 0;
547 		rl_pci_conf();	/* Configure PCI devices. */
548 
549 		/* Use a synchronous alarm instead of a watchdog timer. */
550 		sys_setalarm(system_hz, 0);
551 	}
552 
553 	rep = &re_state;
554 	if (rep->re_mode == REM_DISABLED) {
555 		/* This is the default, try to (re)locate the device. */
556 		rl_conf_hw(rep);
557 		if (rep->re_mode == REM_DISABLED) {
558 			/* Probe failed, or the device is configured off. */
559 			reply_mess.m_type = DL_CONF_REPLY;
560 			reply_mess.m_netdrv_net_dl_conf.stat = ENXIO;
561 			mess_reply(mp, &reply_mess);
562 			return;
563 		}
564 		if (rep->re_mode == REM_ENABLED)
565 			rl_init_hw(rep);
566 	}
567 
568 	assert(rep->re_mode == REM_ENABLED);
569 	assert(rep->re_flags & REF_ENABLED);
570 
571 	rep->re_flags &= ~(REF_PROMISC | REF_MULTI | REF_BROAD);
572 
573 	if (mp->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ)
574 		rep->re_flags |= REF_PROMISC;
575 	if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ)
576 		rep->re_flags |= REF_MULTI;
577 	if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ)
578 		rep->re_flags |= REF_BROAD;
579 
580 	rl_rec_mode(rep);
581 
582 	reply_mess.m_type = DL_CONF_REPLY;
583 	reply_mess.m_netdrv_net_dl_conf.stat = OK;
584 	memcpy(reply_mess.m_netdrv_net_dl_conf.hw_addr,
585 		rep->re_address.ea_addr,
586 		sizeof(reply_mess.m_netdrv_net_dl_conf.hw_addr));
587 
588 	mess_reply(mp, &reply_mess);
589 }
590 
591 /*===========================================================================*
592  *				rl_pci_conf				     *
593  *===========================================================================*/
594 static void rl_pci_conf()
595 {
596 	re_t *rep;
597 
598 	rep = &re_state;
599 
600 	strlcpy(rep->re_name, "rtl8169#0", sizeof(rep->re_name));
601 	rep->re_name[8] += re_instance;
602 	rep->re_seen = FALSE;
603 
604 	pci_init();
605 
606 	if (rl_probe(rep, re_instance))
607 		rep->re_seen = TRUE;
608 }
609 
610 /*===========================================================================*
611  *				rl_probe				     *
612  *===========================================================================*/
613 static int rl_probe(rep, skip)
614 re_t *rep;
615 int skip;
616 {
617 	int r, devind;
618 	u16_t vid, did;
619 	u32_t bar;
620 	u8_t ilr;
621 #if VERBOSE
622 	char *dname;
623 #endif
624 
625 	r = pci_first_dev(&devind, &vid, &did);
626 	if (r == 0)
627 		return 0;
628 
629 	while (skip--) {
630 		r = pci_next_dev(&devind, &vid, &did);
631 		if (!r)
632 			return 0;
633 	}
634 
635 #if VERBOSE
636 	dname = pci_dev_name(vid, did);
637 	if (!dname)
638 		dname = "unknown device";
639 	printf("%s: ", rep->re_name);
640 	printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
641 #endif
642 
643 	pci_reserve(devind);
644 	bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
645 	if (bar < 0x400) {
646 		panic("base address is not properly configured");
647 	}
648 	rep->re_base_port = bar;
649 
650 	ilr = pci_attr_r8(devind, PCI_ILR);
651 	rep->re_irq = ilr;
652 #if VERBOSE
653 	printf("%s: using I/O address 0x%lx, IRQ %d\n",
654 		rep->re_name, (unsigned long)bar, ilr);
655 #endif
656 
657 	return TRUE;
658 }
659 
660 /*===========================================================================*
661  *				rl_conf_hw				     *
662  *===========================================================================*/
663 static void rl_conf_hw(rep)
664 re_t *rep;
665 {
666 	static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */ };
667 
668 	rep->re_mode = REM_DISABLED;		/* Superfluous */
669 
670 	if (rep->re_seen)
671 		rep->re_mode = REM_ENABLED;	/* PCI device is present */
672 	if (rep->re_mode != REM_ENABLED)
673 		return;
674 
675 	rep->re_flags = REF_EMPTY;
676 	rep->re_link_up = 0;
677 	rep->re_got_int = 0;
678 	rep->re_send_int = 0;
679 	rep->re_report_link = 0;
680 	rep->re_need_reset = 0;
681 	rep->re_tx_alive = 0;
682 	rep->re_rx_head = 0;
683 	rep->re_read_s = 0;
684 	rep->re_tx_head = 0;
685 	rep->re_stat = empty_stat;
686 	rep->dtcc_counter = 0;
687 }
688 
689 /*===========================================================================*
690  *				rl_init_buf				     *
691  *===========================================================================*/
692 static void rl_init_buf(rep)
693 re_t *rep;
694 {
695 	size_t rx_bufsize, tx_bufsize, rx_descsize, tx_descsize, tot_bufsize;
696 	struct re_desc *desc;
697 	phys_bytes buf;
698 	char *mallocbuf;
699 	int d;
700 
701 	assert(!rep->setup);
702 
703 	/* Allocate receive and transmit descriptors */
704 	rx_descsize = (N_RX_DESC * sizeof(struct re_desc));
705 	tx_descsize = (N_TX_DESC * sizeof(struct re_desc));
706 
707 	/* Allocate receive and transmit buffers */
708 	tx_bufsize = ETH_MAX_PACK_SIZE_TAGGED;
709 	if (tx_bufsize % 4)
710 		tx_bufsize += 4-(tx_bufsize % 4);	/* Align */
711 	rx_bufsize = RX_BUFSIZE;
712 	tot_bufsize = rx_descsize + tx_descsize;
713 	tot_bufsize += (N_TX_DESC * tx_bufsize) + (N_RX_DESC * rx_bufsize);
714 	tot_bufsize += sizeof(struct re_dtcc);
715 
716 	if (tot_bufsize % 4096)
717 		tot_bufsize += 4096 - (tot_bufsize % 4096);
718 
719 	if (!(mallocbuf = alloc_contig(tot_bufsize, AC_ALIGN64K, &buf)))
720 		panic("Couldn't allocate kernel buffer");
721 
722 	/* Rx Descriptor */
723 	rep->re_rx_desc = (re_desc *)mallocbuf;
724 	rep->p_rx_desc = buf;
725 	memset(mallocbuf, 0x00, rx_descsize);
726 	buf += rx_descsize;
727 	mallocbuf += rx_descsize;
728 
729 	/* Tx Descriptor */
730 	rep->re_tx_desc = (re_desc *)mallocbuf;
731 	rep->p_tx_desc = buf;
732 	memset(mallocbuf, 0x00, tx_descsize);
733 	buf += tx_descsize;
734 	mallocbuf += tx_descsize;
735 
736 	desc = rep->re_rx_desc;
737 	for (d = 0; d < N_RX_DESC; d++) {
738 		/* Setting Rx buffer */
739 		rep->re_rx[d].ret_buf = buf;
740 		rep->re_rx[d].v_ret_buf = mallocbuf;
741 		buf += rx_bufsize;
742 		mallocbuf += rx_bufsize;
743 
744 		/* Setting Rx descriptor */
745 		if (d == (N_RX_DESC - 1)) /* Last descriptor? if so, set the EOR bit */
746 			desc->status =  DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
747 		else
748 			desc->status =  DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
749 
750 		desc->addr_low =  rep->re_rx[d].ret_buf;
751 		desc++;
752 	}
753 	desc = rep->re_tx_desc;
754 	for (d = 0; d < N_TX_DESC; d++) {
755 		rep->re_tx[d].ret_busy = FALSE;
756 		rep->re_tx[d].ret_buf = buf;
757 		rep->re_tx[d].v_ret_buf = mallocbuf;
758 		buf += tx_bufsize;
759 		mallocbuf += tx_bufsize;
760 
761 		/* Setting Tx descriptor */
762 		desc->addr_low =  rep->re_tx[d].ret_buf;
763 		desc++;
764 	}
765 
766 	/* Dump Tally Counter buffer */
767 	rep->dtcc_buf = buf;
768 	rep->v_dtcc_buf = (re_dtcc *)mallocbuf;
769 
770 	rep->setup = 1;
771 }
772 
773 /*===========================================================================*
774  *				rl_init_hw				     *
775  *===========================================================================*/
776 static void rl_init_hw(rep)
777 re_t *rep;
778 {
779 	int s;
780 #if VERBOSE
781 	int i;
782 #endif
783 
784 	rep->re_flags = REF_EMPTY;
785 	rep->re_flags |= REF_ENABLED;
786 
787 	/*
788 	 * Set the interrupt handler. The policy is to only send HARD_INT
789 	 * notifications. Don't reenable interrupts automatically. The id
790 	 * that is passed back is the interrupt line number.
791 	 */
792 	rep->re_hook_id = rep->re_irq;
793 	if ((s = sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
794 		printf("RTL8169: error, couldn't set IRQ policy: %d\n", s);
795 
796 	rl_reset_hw(rep);
797 
798 	if ((s = sys_irqenable(&rep->re_hook_id)) != OK)
799 		printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
800 
801 #if VERBOSE
802 	printf("%s: model: %s mac: 0x%08x\n",
803 		rep->re_name, rep->re_model, rep->re_mac);
804 #endif
805 
806 	rl_confaddr(rep);
807 #if VERBOSE
808 	printf("%s: Ethernet address ", rep->re_name);
809 	for (i = 0; i < 6; i++) {
810 		printf("%x%c", rep->re_address.ea_addr[i],
811 			i < 5 ? ':' : '\n');
812 	}
813 #endif
814 }
815 
816 static void rtl8169s_phy_config(port_t port)
817 {
818 	mdio_write(port, 0x1f, 0x0001);
819 	mdio_write(port, 0x06, 0x006e);
820 	mdio_write(port, 0x08, 0x0708);
821 	mdio_write(port, 0x15, 0x4000);
822 	mdio_write(port, 0x18, 0x65c7);
823 
824 	mdio_write(port, 0x1f, 0x0001);
825 	mdio_write(port, 0x03, 0x00a1);
826 	mdio_write(port, 0x02, 0x0008);
827 	mdio_write(port, 0x01, 0x0120);
828 	mdio_write(port, 0x00, 0x1000);
829 	mdio_write(port, 0x04, 0x0800);
830 	mdio_write(port, 0x04, 0x0000);
831 
832 	mdio_write(port, 0x03, 0xff41);
833 	mdio_write(port, 0x02, 0xdf60);
834 	mdio_write(port, 0x01, 0x0140);
835 	mdio_write(port, 0x00, 0x0077);
836 	mdio_write(port, 0x04, 0x7800);
837 	mdio_write(port, 0x04, 0x7000);
838 
839 	mdio_write(port, 0x03, 0x802f);
840 	mdio_write(port, 0x02, 0x4f02);
841 	mdio_write(port, 0x01, 0x0409);
842 	mdio_write(port, 0x00, 0xf0f9);
843 	mdio_write(port, 0x04, 0x9800);
844 	mdio_write(port, 0x04, 0x9000);
845 
846 	mdio_write(port, 0x03, 0xdf01);
847 	mdio_write(port, 0x02, 0xdf20);
848 	mdio_write(port, 0x01, 0xff95);
849 	mdio_write(port, 0x00, 0xba00);
850 	mdio_write(port, 0x04, 0xa800);
851 	mdio_write(port, 0x04, 0xa000);
852 
853 	mdio_write(port, 0x03, 0xff41);
854 	mdio_write(port, 0x02, 0xdf20);
855 	mdio_write(port, 0x01, 0x0140);
856 	mdio_write(port, 0x00, 0x00bb);
857 	mdio_write(port, 0x04, 0xb800);
858 	mdio_write(port, 0x04, 0xb000);
859 
860 	mdio_write(port, 0x03, 0xdf41);
861 	mdio_write(port, 0x02, 0xdc60);
862 	mdio_write(port, 0x01, 0x6340);
863 	mdio_write(port, 0x00, 0x007d);
864 	mdio_write(port, 0x04, 0xd800);
865 	mdio_write(port, 0x04, 0xd000);
866 
867 	mdio_write(port, 0x03, 0xdf01);
868 	mdio_write(port, 0x02, 0xdf20);
869 	mdio_write(port, 0x01, 0x100a);
870 	mdio_write(port, 0x00, 0xa0ff);
871 	mdio_write(port, 0x04, 0xf800);
872 	mdio_write(port, 0x04, 0xf000);
873 
874 	mdio_write(port, 0x1f, 0x0000);
875 	mdio_write(port, 0x0b, 0x0000);
876 	mdio_write(port, 0x00, 0x9200);
877 }
878 
879 static void rtl8169scd_phy_config(port_t port)
880 {
881 	mdio_write(port, 0x1f, 0x0001);
882 	mdio_write(port, 0x04, 0x0000);
883 	mdio_write(port, 0x03, 0x00a1);
884 	mdio_write(port, 0x02, 0x0008);
885 	mdio_write(port, 0x01, 0x0120);
886 	mdio_write(port, 0x00, 0x1000);
887 	mdio_write(port, 0x04, 0x0800);
888 	mdio_write(port, 0x04, 0x9000);
889 	mdio_write(port, 0x03, 0x802f);
890 	mdio_write(port, 0x02, 0x4f02);
891 	mdio_write(port, 0x01, 0x0409);
892 	mdio_write(port, 0x00, 0xf099);
893 	mdio_write(port, 0x04, 0x9800);
894 	mdio_write(port, 0x04, 0xa000);
895 	mdio_write(port, 0x03, 0xdf01);
896 	mdio_write(port, 0x02, 0xdf20);
897 	mdio_write(port, 0x01, 0xff95);
898 	mdio_write(port, 0x00, 0xba00);
899 	mdio_write(port, 0x04, 0xa800);
900 	mdio_write(port, 0x04, 0xf000);
901 	mdio_write(port, 0x03, 0xdf01);
902 	mdio_write(port, 0x02, 0xdf20);
903 	mdio_write(port, 0x01, 0x101a);
904 	mdio_write(port, 0x00, 0xa0ff);
905 	mdio_write(port, 0x04, 0xf800);
906 	mdio_write(port, 0x04, 0x0000);
907 	mdio_write(port, 0x1f, 0x0000);
908 
909 	mdio_write(port, 0x1f, 0x0001);
910 	mdio_write(port, 0x10, 0xf41b);
911 	mdio_write(port, 0x14, 0xfb54);
912 	mdio_write(port, 0x18, 0xf5c7);
913 	mdio_write(port, 0x1f, 0x0000);
914 
915 	mdio_write(port, 0x1f, 0x0001);
916 	mdio_write(port, 0x17, 0x0cc0);
917 	mdio_write(port, 0x1f, 0x0000);
918 }
919 
920 /*===========================================================================*
921  *				rl_reset_hw				     *
922  *===========================================================================*/
923 static void rl_reset_hw(rep)
924 re_t *rep;
925 {
926 	port_t port;
927 	u32_t t;
928 	int i;
929 
930 	port = rep->re_base_port;
931 
932 	rl_outw(port, RL_IMR, 0x0000);
933 
934 	/* Reset the device */
935 	rl_outb(port, RL_CR, RL_CR_RST);
936 	SPIN_UNTIL(!(rl_inb(port, RL_CR) & RL_CR_RST), 1000000);
937 	if (rl_inb(port, RL_CR) & RL_CR_RST)
938 		printf("rtl8169: reset failed to complete");
939 	rl_outw(port, RL_ISR, 0xFFFF);
940 
941 	/* Get Model and MAC info */
942 	t = rl_inl(port, RL_TCR);
943 	rep->re_mac = (t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
944 	switch (rep->re_mac) {
945 	case RL_TCR_HWVER_RTL8169:
946 		rep->re_model = "RTL8169";
947 
948 		rl_outw(port, RL_CCR_UNDOC, 0x01);
949 		break;
950 	case RL_TCR_HWVER_RTL8169S:
951 		rep->re_model = "RTL8169S";
952 
953 		rtl8169s_phy_config(port);
954 
955 		rl_outw(port, RL_CCR_UNDOC, 0x01);
956 		mdio_write(port, 0x0b, 0x0000);		/* w 0x0b 15 0 0 */
957 		break;
958 	case RL_TCR_HWVER_RTL8110S:
959 		rep->re_model = "RTL8110S";
960 
961 		rtl8169s_phy_config(port);
962 
963 		rl_outw(port, RL_CCR_UNDOC, 0x01);
964 		break;
965 	case RL_TCR_HWVER_RTL8169SB:
966 		rep->re_model = "RTL8169SB";
967 
968 		mdio_write(port, 0x1f, 0x02);
969 		mdio_write(port, 0x01, 0x90d0);
970 		mdio_write(port, 0x1f, 0x00);
971 
972 		rl_outw(port, RL_CCR_UNDOC, 0x01);
973 		break;
974 	case RL_TCR_HWVER_RTL8110SCd:
975 		rep->re_model = "RTL8110SCd";
976 
977 		rtl8169scd_phy_config(port);
978 
979 		rl_outw(port, RL_CCR_UNDOC, 0x01);
980 		break;
981 	case RL_TCR_HWVER_RTL8105E:
982 		rep->re_model = "RTL8105E";
983 		break;
984 	default:
985 		rep->re_model = "Unknown";
986 		rep->re_mac = t;
987 		break;
988 	}
989 
990 	mdio_write(port, MII_CTRL, MII_CTRL_RST);
991 	for (i = 0; i < 1000; i++) {
992 		t = mdio_read(port, MII_CTRL);
993 		if (!(t & MII_CTRL_RST))
994 			break;
995 		else
996 			micro_delay(100);
997 	}
998 
999 	t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_DM | MII_CTRL_SP_1000;
1000 	mdio_write(port, MII_CTRL, t);
1001 
1002 	t = mdio_read(port, MII_ANA);
1003 	t |= MII_ANA_10THD | MII_ANA_10TFD | MII_ANA_100TXHD | MII_ANA_100TXFD;
1004 	t |= MII_ANA_PAUSE_SYM | MII_ANA_PAUSE_ASYM;
1005 	mdio_write(port, MII_ANA, t);
1006 
1007 	t = mdio_read(port, MII_1000_CTRL) | 0x300;
1008 	mdio_write(port, MII_1000_CTRL, t);
1009 
1010 	/* Restart Auto-Negotiation Process */
1011 	t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_RAN;
1012 	mdio_write(port, MII_CTRL, t);
1013 
1014 	rl_outw(port, RL_9346CR, RL_9346CR_EEM_CONFIG);	/* Unlock */
1015 
1016 	switch (rep->re_mac) {
1017 	case RL_TCR_HWVER_RTL8169S:
1018 	case RL_TCR_HWVER_RTL8110S:
1019 		/* Bit-3 and bit-14 of the C+CR register MUST be 1. */
1020 		t = rl_inw(port, RL_CPLUSCMD);
1021 		rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW | (1 << 14));
1022 		break;
1023 	case RL_TCR_HWVER_RTL8169:
1024 	case RL_TCR_HWVER_RTL8169SB:
1025 	case RL_TCR_HWVER_RTL8110SCd:
1026 		t = rl_inw(port, RL_CPLUSCMD);
1027 		rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW);
1028 		break;
1029 	}
1030 
1031 	rl_outw(port, RL_INTRMITIGATE, 0x00);
1032 
1033 	t = rl_inb(port, RL_CR);
1034 	rl_outb(port, RL_CR, t | RL_CR_RE | RL_CR_TE);
1035 
1036 	/* Initialize Rx */
1037 	rl_outw(port, RL_RMS, RX_BUFSIZE);	/* Maximum rx packet size */
1038 	t = rl_inl(port, RL_RCR) & RX_CONFIG_MASK;
1039 	rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | t);
1040 	rl_outl(port, RL_RDSAR_LO, rep->p_rx_desc);
1041 	rl_outl(port, RL_RDSAR_HI, 0x00);	/* For 64 bit */
1042 
1043 	/* Initialize Tx */
1044 	rl_outw(port, RL_ETTHR, 0x3f);		/* No early transmit */
1045 	rl_outl(port, RL_TCR, RL_TCR_MXDMA_2048 | RL_TCR_IFG_STD);
1046 	rl_outl(port, RL_TNPDS_LO, rep->p_tx_desc);
1047 	rl_outl(port, RL_TNPDS_HI, 0x00);	/* For 64 bit */
1048 
1049 	rl_outw(port, RL_9346CR, RL_9346CR_EEM_NORMAL);	/* Lock */
1050 
1051 	rl_outw(port, RL_MPC, 0x00);
1052 	rl_outw(port, RL_MULINT, rl_inw(port, RL_MULINT) & 0xF000);
1053 	rl_outw(port, RL_IMR, RE_INTR_MASK);
1054 }
1055 
1056 /*===========================================================================*
1057  *				rl_confaddr				     *
1058  *===========================================================================*/
1059 static void rl_confaddr(rep)
1060 re_t *rep;
1061 {
1062 	static char eakey[] = RL_ENVVAR "#_EA";
1063 	static char eafmt[] = "x:x:x:x:x:x";
1064 
1065 	int i;
1066 	port_t port;
1067 	u32_t w;
1068 	long v;
1069 
1070 	/* User defined ethernet address? */
1071 	eakey[sizeof(RL_ENVVAR)-1] = '0' + re_instance;
1072 
1073 	port = rep->re_base_port;
1074 
1075 	for (i = 0; i < 6; i++) {
1076 		if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
1077 			break;
1078 		rep->re_address.ea_addr[i] = v;
1079 	}
1080 
1081 	if (i != 0 && i != 6)
1082 		env_panic(eakey);	/* It's all or nothing */
1083 
1084 	/* Should update ethernet address in hardware */
1085 	if (i == 6) {
1086 		port = rep->re_base_port;
1087 		rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
1088 		w = 0;
1089 		for (i = 0; i < 4; i++)
1090 			w |= (rep->re_address.ea_addr[i] << (i * 8));
1091 		rl_outl(port, RL_IDR, w);
1092 		w = 0;
1093 		for (i = 4; i < 6; i++)
1094 			w |= (rep->re_address.ea_addr[i] << ((i-4) * 8));
1095 		rl_outl(port, RL_IDR + 4, w);
1096 		rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
1097 	}
1098 
1099 	/* Get ethernet address */
1100 	for (i = 0; i < 6; i++)
1101 		rep->re_address.ea_addr[i] = rl_inb(port, RL_IDR+i);
1102 }
1103 
1104 /*===========================================================================*
1105  *				rl_rec_mode				     *
1106  *===========================================================================*/
1107 static void rl_rec_mode(rep)
1108 re_t *rep;
1109 {
1110 	port_t port;
1111 	u32_t rcr;
1112 	u32_t mc_filter[2];		/* Multicast hash filter */
1113 
1114 	port = rep->re_base_port;
1115 
1116 	mc_filter[1] = mc_filter[0] = 0xffffffff;
1117 	rl_outl(port, RL_MAR + 0, mc_filter[0]);
1118 	rl_outl(port, RL_MAR + 4, mc_filter[1]);
1119 
1120 	rcr = rl_inl(port, RL_RCR);
1121 	rcr &= ~(RL_RCR_AB | RL_RCR_AM | RL_RCR_APM | RL_RCR_AAP);
1122 	if (rep->re_flags & REF_PROMISC)
1123 		rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
1124 	if (rep->re_flags & REF_BROAD)
1125 		rcr |= RL_RCR_AB;
1126 	if (rep->re_flags & REF_MULTI)
1127 		rcr |= RL_RCR_AM;
1128 	rcr |= RL_RCR_APM;
1129 	rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | rcr);
1130 }
1131 
1132 void transmittest(re_t *rep)
1133 {
1134 	int tx_head;
1135 	int ipc_status;
1136 
1137 	tx_head = rep->re_tx_head;
1138 
1139 	if(rep->re_tx[tx_head].ret_busy) {
1140 		do {
1141 			message m;
1142 			int r;
1143 			if ((r = netdriver_receive(ANY, &m, &ipc_status)) != OK)
1144 				panic("netdriver_receive failed: %d", r);
1145 		} while(m.m_source != HARDWARE);
1146 		assert(!(rep->re_flags & REF_SEND_AVAIL));
1147 		rep->re_flags |= REF_SEND_AVAIL;
1148 	}
1149 
1150 	return;
1151 }
1152 
1153 /*===========================================================================*
1154  *				rl_readv_s				     *
1155  *===========================================================================*/
1156 static void rl_readv_s(const message *mp, int from_int)
1157 {
1158 	int i, j, n, s, count, size, index;
1159 	port_t port;
1160 	unsigned totlen, packlen;
1161 	re_desc *desc;
1162 	u32_t rxstat = 0x12345678;
1163 	re_t *rep;
1164 	iovec_s_t *iovp;
1165 	int cps;
1166 	int iov_offset = 0;
1167 
1168 	rep = &re_state;
1169 
1170 	rep->re_client = mp->m_source;
1171 	count = mp->m_net_netdrv_dl_readv_s.count;
1172 
1173 	assert(rep->re_mode == REM_ENABLED);
1174 	assert(rep->re_flags & REF_ENABLED);
1175 
1176 	port = rep->re_base_port;
1177 
1178 	/*
1179 	 * Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1180 	 */
1181 	if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
1182 		goto suspend;		/* Receive buffer is empty, suspend */
1183 
1184 	index = rep->re_rx_head;
1185 	desc = rep->re_rx_desc;
1186 	desc += index;
1187 readvs_loop:
1188 	rxstat = desc->status;
1189 
1190 	if (rxstat & DESC_OWN)
1191 		goto suspend;
1192 
1193 	if (rxstat & DESC_RX_CRC)
1194 		rep->re_stat.ets_CRCerr++;
1195 
1196 	if ((rxstat & (DESC_FS | DESC_LS)) != (DESC_FS | DESC_LS)) {
1197 #if VERBOSE
1198 		printf("rl_readv_s: packet is fragmented\n");
1199 #endif
1200 		/* Fix the fragmented packet */
1201 		if (index == N_RX_DESC - 1) {
1202 			desc->status =  DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1203 			index = 0;
1204 			desc = rep->re_rx_desc;
1205 		} else {
1206 			desc->status =  DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1207 			index++;
1208 			desc++;
1209 		}
1210 		goto readvs_loop;	/* Loop until we get correct packet */
1211 	}
1212 
1213 	totlen = rxstat & DESC_RX_LENMASK;
1214 	if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
1215 		/* Someting went wrong */
1216 		printf("rl_readv_s: bad length (%u) in status 0x%08x\n",
1217 			totlen, rxstat);
1218 		panic(NULL);
1219 	}
1220 
1221 	/* Should subtract the CRC */
1222 	packlen = totlen - ETH_CRC_SIZE;
1223 
1224 	size = 0;
1225 	for (i = 0; i < count; i += IOVEC_NR,
1226 		iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
1227 	{
1228 		n = IOVEC_NR;
1229 		if (i + n > count)
1230 			n = count-i;
1231 		cps = sys_safecopyfrom(mp->m_source,
1232 			mp->m_net_netdrv_dl_readv_s.grant, iov_offset,
1233 			(vir_bytes) rep->re_iovec_s,
1234 			n * sizeof(rep->re_iovec_s[0]));
1235 		if (cps != OK) {
1236 			panic("rl_readv_s: sys_safecopyfrom failed: %d", 				cps);
1237 		}
1238 
1239 		for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
1240 			s = iovp->iov_size;
1241 			if (size + s > packlen) {
1242 				assert(packlen > size);
1243 				s = packlen-size;
1244 			}
1245 
1246 			cps = sys_safecopyto(mp->m_source, iovp->iov_grant, 0,
1247 				(vir_bytes) rep->re_rx[index].v_ret_buf + size, s);
1248 			if (cps != OK)
1249 				panic("rl_readv_s: sys_safecopyto failed: %d", cps);
1250 
1251 			size += s;
1252 			if (size == packlen)
1253 				break;
1254 		}
1255 		if (size == packlen)
1256 			break;
1257 	}
1258 	if (size < packlen)
1259 		assert(0);
1260 
1261 	rep->re_stat.ets_packetR++;
1262 	rep->re_read_s = packlen;
1263 	if (index == N_RX_DESC - 1) {
1264 		desc->status =  DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1265 		index = 0;
1266 	} else {
1267 		desc->status =  DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1268 		index++;
1269 	}
1270 	rep->re_rx_head = index;
1271 	assert(rep->re_rx_head < N_RX_DESC);
1272 	rep->re_flags = (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
1273 
1274 	if (!from_int)
1275 		reply(rep);
1276 
1277 	return;
1278 
1279 suspend:
1280 	if (from_int) {
1281 		assert(rep->re_flags & REF_READING);
1282 
1283 		/* No need to store any state */
1284 		return;
1285 	}
1286 
1287 	rep->re_rx_mess = *mp;
1288 	assert(!(rep->re_flags & REF_READING));
1289 	rep->re_flags |= REF_READING;
1290 
1291 	reply(rep);
1292 }
1293 
1294 /*===========================================================================*
1295  *				rl_writev_s				     *
1296  *===========================================================================*/
1297 static void rl_writev_s(const message *mp, int from_int)
1298 {
1299 	int i, j, n, s, count, size;
1300 	int tx_head;
1301 	re_t *rep;
1302 	iovec_s_t *iovp;
1303 	re_desc *desc;
1304 	char *ret;
1305 	int cps;
1306 	int iov_offset = 0;
1307 
1308 	rep = &re_state;
1309 
1310 	rep->re_client = mp->m_source;
1311 	count = mp->m_net_netdrv_dl_writev_s.count;
1312 	assert(rep->setup);
1313 
1314 	assert(rep->re_mode == REM_ENABLED);
1315 	assert(rep->re_flags & REF_ENABLED);
1316 
1317 	if (from_int) {
1318 		assert(rep->re_flags & REF_SEND_AVAIL);
1319 		rep->re_flags &= ~REF_SEND_AVAIL;
1320 		rep->re_send_int = FALSE;
1321 		rep->re_tx_alive = TRUE;
1322 	}
1323 
1324 	tx_head = rep->re_tx_head;
1325 
1326 	desc = rep->re_tx_desc;
1327 	desc += tx_head;
1328 
1329 	if(!desc || !rep->re_tx_desc) {
1330 		printf("desc %p, re_tx_desc %p, tx_head %d, setup %d\n",
1331 			desc, rep->re_tx_desc, tx_head, rep->setup);
1332 	}
1333 
1334 	assert(rep->re_tx_desc);
1335 	assert(rep->re_tx_head >= 0 && rep->re_tx_head < N_TX_DESC);
1336 
1337 	assert(desc);
1338 
1339 	if (rep->re_tx[tx_head].ret_busy) {
1340 		assert(!(rep->re_flags & REF_SEND_AVAIL));
1341 		rep->re_flags |= REF_SEND_AVAIL;
1342 		if (rep->re_tx[tx_head].ret_busy)
1343 			goto suspend;
1344 
1345 		/*
1346 		 * Race condition, the interrupt handler may clear re_busy
1347 		 * before we got a chance to set REF_SEND_AVAIL. Checking
1348 		 * ret_busy twice should be sufficient.
1349 		 */
1350 #if VERBOSE
1351 		printf("rl_writev_s: race detected\n");
1352 #endif
1353 		rep->re_flags &= ~REF_SEND_AVAIL;
1354 		rep->re_send_int = FALSE;
1355 	}
1356 
1357 	assert(!(rep->re_flags & REF_SEND_AVAIL));
1358 	assert(!(rep->re_flags & REF_PACK_SENT));
1359 
1360 	size = 0;
1361 	ret = rep->re_tx[tx_head].v_ret_buf;
1362 	for (i = 0; i < count; i += IOVEC_NR,
1363 		iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
1364 	{
1365 		n = IOVEC_NR;
1366 		if (i + n > count)
1367 			n = count - i;
1368 		cps = sys_safecopyfrom(mp->m_source,
1369 			mp->m_net_netdrv_dl_writev_s.grant, iov_offset,
1370 			(vir_bytes) rep->re_iovec_s,
1371 			n * sizeof(rep->re_iovec_s[0]));
1372 		if (cps != OK) {
1373 			panic("rl_writev_s: sys_safecopyfrom failed: %d", 				cps);
1374 		}
1375 
1376 		for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
1377 			s = iovp->iov_size;
1378 			if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
1379 				panic("invalid packet size");
1380 
1381 			cps = sys_safecopyfrom(mp->m_source, iovp->iov_grant,
1382 				0, (vir_bytes) ret, s);
1383 			if (cps != OK) {
1384 				panic("rl_writev_s: sys_safecopyfrom failed: %d", cps);
1385 			}
1386 			size += s;
1387 			ret += s;
1388 		}
1389 	}
1390 	assert(desc);
1391 	if (size < ETH_MIN_PACK_SIZE)
1392 		panic("invalid packet size: %d", size);
1393 
1394 	rep->re_tx[tx_head].ret_busy = TRUE;
1395 
1396 	if (tx_head == N_TX_DESC - 1) {
1397 		desc->status =  DESC_EOR | DESC_OWN | DESC_FS | DESC_LS | size;
1398 		tx_head = 0;
1399 	} else {
1400 		desc->status =  DESC_OWN | DESC_FS | DESC_LS | size;
1401 		tx_head++;
1402 	}
1403 
1404 	assert(tx_head < N_TX_DESC);
1405 	rep->re_tx_head = tx_head;
1406 
1407 	rl_outl(rep->re_base_port, RL_TPPOLL, RL_TPPOLL_NPQ);
1408 	rep->re_flags |= REF_PACK_SENT;
1409 
1410 	/*
1411 	 * If the interrupt handler called, don't send a reply. The reply
1412 	 * will be sent after all interrupts are handled.
1413 	 */
1414 	if (from_int)
1415 		return;
1416 	reply(rep);
1417 	return;
1418 
1419 suspend:
1420 	if (from_int)
1421 		panic("should not be sending");
1422 
1423 	rep->re_tx_mess = *mp;
1424 	reply(rep);
1425 }
1426 
1427 /*===========================================================================*
1428  *				rl_check_ints				     *
1429  *===========================================================================*/
1430 static void rl_check_ints(rep)
1431 re_t *rep;
1432 {
1433 	int re_flags;
1434 
1435 	re_flags = rep->re_flags;
1436 
1437 	if ((re_flags & REF_READING) &&
1438 		!(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE))
1439 	{
1440 		assert(rep->re_rx_mess.m_type == DL_READV_S);
1441 		rl_readv_s(&rep->re_rx_mess, TRUE /* from int */);
1442 	}
1443 
1444 	if (rep->re_need_reset)
1445 		rl_do_reset(rep);
1446 
1447 	if (rep->re_send_int) {
1448 		assert(rep->re_tx_mess.m_type == DL_WRITEV_S);
1449 		rl_writev_s(&rep->re_tx_mess, TRUE /* from int */);
1450 	}
1451 
1452 	if (rep->re_report_link) {
1453 		rep->re_report_link = FALSE;
1454 
1455 		rl_report_link(rep);
1456 	}
1457 
1458 	if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV))
1459 		reply(rep);
1460 }
1461 
1462 /*===========================================================================*
1463  *				rl_report_link				     *
1464  *===========================================================================*/
1465 static void rl_report_link(rep)
1466 re_t *rep;
1467 {
1468 #if VERBOSE
1469 	port_t port;
1470 	u8_t mii_status;
1471 
1472 	port = rep->re_base_port;
1473 
1474 	mii_status = rl_inb(port, RL_PHYSTAT);
1475 
1476 	if (mii_status & RL_STAT_LINK) {
1477 		rep->re_link_up = 1;
1478 		printf("%s: link up at ", rep->re_name);
1479 	} else {
1480 		rep->re_link_up = 0;
1481 		printf("%s: link down\n", rep->re_name);
1482 		return;
1483 	}
1484 
1485 	if (mii_status & RL_STAT_1000)
1486 		printf("1000 Mbps");
1487 	else if (mii_status & RL_STAT_100)
1488 		printf("100 Mbps");
1489 	else if (mii_status & RL_STAT_10)
1490 		printf("10 Mbps");
1491 
1492 	if (mii_status & RL_STAT_FULLDUP)
1493 		printf(", full duplex");
1494 	else
1495 		printf(", half duplex");
1496 	printf("\n");
1497 #endif
1498 
1499 	dump_phy(rep);
1500 }
1501 
1502 /*===========================================================================*
1503  *				rl_do_reset				     *
1504  *===========================================================================*/
1505 static void rl_do_reset(rep)
1506 re_t *rep;
1507 {
1508 	rep->re_need_reset = FALSE;
1509 	rl_reset_hw(rep);
1510 	rl_rec_mode(rep);
1511 
1512 	rep->re_tx_head = 0;
1513 	if (rep->re_flags & REF_SEND_AVAIL) {
1514 		rep->re_tx[rep->re_tx_head].ret_busy = FALSE;
1515 		rep->re_send_int = TRUE;
1516 	}
1517 }
1518 
1519 /*===========================================================================*
1520  *				rl_getstat_s				     *
1521  *===========================================================================*/
1522 static void rl_getstat_s(mp)
1523 message *mp;
1524 {
1525 	int r;
1526 	eth_stat_t stats;
1527 	re_t *rep;
1528 
1529 	rep = &re_state;
1530 
1531 	assert(rep->re_mode == REM_ENABLED);
1532 	assert(rep->re_flags & REF_ENABLED);
1533 
1534 	stats = rep->re_stat;
1535 
1536 	r = sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant,
1537 		0, (vir_bytes) &stats, sizeof(stats));
1538 	if (r != OK)
1539 		panic("rl_getstat_s: sys_safecopyto failed: %d", r);
1540 
1541 	mp->m_type = DL_STAT_REPLY;
1542 	r = ipc_send(mp->m_source, mp);
1543 	if (r != OK)
1544 		panic("rl_getstat_s: ipc_send failed: %d", r);
1545 }
1546 
1547 /*===========================================================================*
1548  *				reply					     *
1549  *===========================================================================*/
1550 static void reply(rep)
1551 re_t *rep;
1552 {
1553 	message reply;
1554 	int flags;
1555 	int r;
1556 
1557 	flags = DL_NOFLAGS;
1558 	if (rep->re_flags & REF_PACK_SENT)
1559 		flags |= DL_PACK_SEND;
1560 	if (rep->re_flags & REF_PACK_RECV)
1561 		flags |= DL_PACK_RECV;
1562 
1563 	reply.m_type = DL_TASK_REPLY;
1564 	reply.m_netdrv_net_dl_task.flags = flags;
1565 	reply.m_netdrv_net_dl_task.count = rep->re_read_s;
1566 
1567 	r = ipc_send(rep->re_client, &reply);
1568 
1569 	if (r < 0) {
1570 		printf("RTL8169 tried sending to %d, type %d\n",
1571 			rep->re_client, reply.m_type);
1572 		panic("ipc_send failed: %d", r);
1573 	}
1574 
1575 	rep->re_read_s = 0;
1576 	rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
1577 }
1578 
1579 /*===========================================================================*
1580  *				mess_reply				     *
1581  *===========================================================================*/
1582 static void mess_reply(req, reply_mess)
1583 message *req;
1584 message *reply_mess;
1585 {
1586 	if (ipc_send(req->m_source, reply_mess) != OK)
1587 		panic("unable to mess_reply");
1588 }
1589 
1590 static void dump_phy(const re_t *rep)
1591 {
1592 #if VERBOSE
1593 	port_t port;
1594 	u32_t t;
1595 
1596 	port = rep->re_base_port;
1597 
1598 	t = rl_inb(port, RL_CONFIG0);
1599 	printf("CONFIG0\t\t:");
1600 	t = t & RL_CFG0_ROM;
1601 	if (t == RL_CFG0_ROM128K)
1602 		printf(" 128K Boot ROM");
1603 	else if (t == RL_CFG0_ROM64K)
1604 		printf(" 64K Boot ROM");
1605 	else if (t == RL_CFG0_ROM32K)
1606 		printf(" 32K Boot ROM");
1607 	else if (t == RL_CFG0_ROM16K)
1608 		printf(" 16K Boot ROM");
1609 	else if (t == RL_CFG0_ROM8K)
1610 		printf(" 8K Boot ROM");
1611 	else if (t == RL_CFG0_ROMNO)
1612 		printf(" No Boot ROM");
1613 	printf("\n");
1614 
1615 	t = rl_inb(port, RL_CONFIG1);
1616 	printf("CONFIG1\t\t:");
1617 	if (t & RL_CFG1_LEDS1)
1618 		printf(" LED1");
1619 	if (t & RL_CFG1_LEDS0)
1620 		printf(" LED0");
1621 	if (t & RL_CFG1_DVRLOAD)
1622 		printf(" Driver");
1623 	if (t & RL_CFG1_LWACT)
1624 		printf(" LWAKE");
1625 	if (t & RL_CFG1_IOMAP)
1626 		printf(" IOMAP");
1627 	if (t & RL_CFG1_MEMMAP)
1628 		printf(" MEMMAP");
1629 	if (t & RL_CFG1_VPD)
1630 		printf(" VPD");
1631 	if (t & RL_CFG1_PME)
1632 		printf(" PME");
1633 	printf("\n");
1634 
1635 	t = rl_inb(port, RL_CONFIG2);
1636 	printf("CONFIG2\t\t:");
1637 	if (t & RL_CFG2_AUX)
1638 		printf(" AUX");
1639 	if (t & RL_CFG2_PCIBW)
1640 		printf(" PCI-64-Bit");
1641 	else
1642 		printf(" PCI-32-Bit");
1643 	t = t & RL_CFG2_PCICLK;
1644 	if (t == RL_CFG2_66MHZ)
1645 		printf(" 66 MHz");
1646 	else if (t == RL_CFG2_33MHZ)
1647 		printf(" 33 MHz");
1648 	printf("\n");
1649 
1650 	t = mdio_read(port, MII_CTRL);
1651 	printf("MII_CTRL\t:");
1652 	if (t & MII_CTRL_RST)
1653 		printf(" Reset");
1654 	if (t & MII_CTRL_LB)
1655 		printf(" Loopback");
1656 	if (t & MII_CTRL_ANE)
1657 		printf(" ANE");
1658 	if (t & MII_CTRL_PD)
1659 		printf(" Power-down");
1660 	if (t & MII_CTRL_ISO)
1661 		printf(" Isolate");
1662 	if (t & MII_CTRL_RAN)
1663 		printf(" RAN");
1664 	if (t & MII_CTRL_DM)
1665 		printf(" Full-duplex");
1666 	if (t & MII_CTRL_CT)
1667 		printf(" COL-signal");
1668 	t = t & (MII_CTRL_SP_LSB | MII_CTRL_SP_MSB);
1669 	if (t == MII_CTRL_SP_10)
1670 		printf(" 10 Mb/s");
1671 	else if (t == MII_CTRL_SP_100)
1672 		printf(" 100 Mb/s");
1673 	else if (t == MII_CTRL_SP_1000)
1674 		printf(" 1000 Mb/s");
1675 	printf("\n");
1676 
1677 	t = mdio_read(port, MII_STATUS);
1678 	printf("MII_STATUS\t:");
1679 	if (t & MII_STATUS_100T4)
1680 		printf(" 100Base-T4");
1681 	if (t & MII_STATUS_100XFD)
1682 		printf(" 100BaseX-FD");
1683 	if (t & MII_STATUS_100XHD)
1684 		printf(" 100BaseX-HD");
1685 	if (t & MII_STATUS_10FD)
1686 		printf(" 10Mbps-FD");
1687 	if (t & MII_STATUS_10HD)
1688 		printf(" 10Mbps-HD");
1689 	if (t & MII_STATUS_100T2FD)
1690 		printf(" 100Base-T2-FD");
1691 	if (t & MII_STATUS_100T2HD)
1692 		printf(" 100Base-T2-HD");
1693 	if (t & MII_STATUS_EXT_STAT)
1694 		printf(" Ext-stat");
1695 	if (t & MII_STATUS_RES)
1696 		printf(" res-0x%x", t & MII_STATUS_RES);
1697 	if (t & MII_STATUS_MFPS)
1698 		printf(" MFPS");
1699 	if (t & MII_STATUS_ANC)
1700 		printf(" ANC");
1701 	if (t & MII_STATUS_RF)
1702 		printf(" remote-fault");
1703 	if (t & MII_STATUS_ANA)
1704 		printf(" ANA");
1705 	if (t & MII_STATUS_LS)
1706 		printf(" Link");
1707 	if (t & MII_STATUS_JD)
1708 		printf(" Jabber");
1709 	if (t & MII_STATUS_EC)
1710 		printf(" Extended-capability");
1711 	printf("\n");
1712 
1713 	t = mdio_read(port, MII_ANA);
1714 	printf("MII_ANA\t\t: 0x%04x\n", t);
1715 
1716 	t = mdio_read(port, MII_ANLPA);
1717 	printf("MII_ANLPA\t: 0x%04x\n", t);
1718 
1719 	t = mdio_read(port, MII_ANE);
1720 	printf("MII_ANE\t\t:");
1721 	if (t & MII_ANE_RES)
1722 		printf(" res-0x%x", t & MII_ANE_RES);
1723 	if (t & MII_ANE_PDF)
1724 		printf(" Par-Detect-Fault");
1725 	if (t & MII_ANE_LPNPA)
1726 		printf(" LP-Next-Page-Able");
1727 	if (t & MII_ANE_NPA)
1728 		printf(" Loc-Next-Page-Able");
1729 	if (t & MII_ANE_PR)
1730 		printf(" Page-Received");
1731 	if (t & MII_ANE_LPANA)
1732 		printf(" LP-Auto-Neg-Able");
1733 	printf("\n");
1734 
1735 	t = mdio_read(port, MII_1000_CTRL);
1736 	printf("MII_1000_CTRL\t:");
1737 	if (t & MII_1000C_FULL)
1738 		printf(" 1000BaseT-FD");
1739 	if (t & MII_1000C_HALF)
1740 		printf(" 1000BaseT-HD");
1741 	printf("\n");
1742 
1743 	t = mdio_read(port, MII_1000_STATUS);
1744 	if (t) {
1745 		printf("MII_1000_STATUS\t:");
1746 		if (t & MII_1000S_LRXOK)
1747 			printf(" Local-Receiver");
1748 		if (t & MII_1000S_RRXOK)
1749 			printf(" Remote-Receiver");
1750 		if (t & MII_1000S_HALF)
1751 			printf(" 1000BaseT-HD");
1752 		if (t & MII_1000S_FULL)
1753 			printf(" 1000BaseT-FD");
1754 		printf("\n");
1755 
1756 		t = mdio_read(port, MII_EXT_STATUS);
1757 		printf("MII_EXT_STATUS\t:");
1758 		if (t & MII_ESTAT_1000XFD)
1759 			printf(" 1000BaseX-FD");
1760 		if (t & MII_ESTAT_1000XHD)
1761 			printf(" 1000BaseX-HD");
1762 		if (t & MII_ESTAT_1000TFD)
1763 			printf(" 1000BaseT-FD");
1764 		if (t & MII_ESTAT_1000THD)
1765 			printf(" 1000BaseT-HD");
1766 		printf("\n");
1767 	}
1768 #endif
1769 }
1770 
1771 static void do_hard_int(void)
1772 {
1773 	int s;
1774 
1775 	/* Run interrupt handler at driver level. */
1776 	rl_handler(&re_state);
1777 
1778 	/* Reenable interrupts for this hook. */
1779 	if ((s = sys_irqenable(&re_state.re_hook_id)) != OK)
1780 		printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
1781 }
1782 
1783 /*===========================================================================*
1784  *				rl_handler				     *
1785  *===========================================================================*/
1786 static void rl_handler(re_t *rep)
1787 {
1788 	int i, port, tx_head, tx_tail, link_up;
1789 	u16_t isr;
1790 	re_desc *desc;
1791 	int_event_check = FALSE;	/* disable check by default */
1792 
1793 	port = rep->re_base_port;
1794 
1795 	/* Ack interrupt */
1796 	isr = rl_inw(port, RL_ISR);
1797 	if(!isr)
1798 		return;
1799 	rl_outw(port, RL_ISR, isr);
1800 	rep->interrupts++;
1801 
1802 	if (isr & RL_IMR_FOVW) {
1803 		isr &= ~RL_IMR_FOVW;
1804 		/* Should do anything? */
1805 
1806 		rep->re_stat.ets_fifoOver++;
1807 	}
1808 	if (isr & RL_IMR_PUN) {
1809 		isr &= ~RL_IMR_PUN;
1810 
1811 		/*
1812 		 * Either the link status changed or there was a TX fifo
1813 		 * underrun.
1814 		 */
1815 		link_up = !(!(rl_inb(port, RL_PHYSTAT) & RL_STAT_LINK));
1816 		if (link_up != rep->re_link_up) {
1817 			rep->re_report_link = TRUE;
1818 			rep->re_got_int = TRUE;
1819 			int_event_check = TRUE;
1820 		}
1821 	}
1822 
1823 	if (isr & (RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK)) {
1824 		if (isr & RL_ISR_RER)
1825 			rep->re_stat.ets_recvErr++;
1826 		isr &= ~(RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK);
1827 
1828 		if (!rep->re_got_int && (rep->re_flags & REF_READING)) {
1829 			rep->re_got_int = TRUE;
1830 			int_event_check = TRUE;
1831 		}
1832 	}
1833 
1834 	if ((isr & (RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK)) || 1) {
1835 		if (isr & RL_ISR_TER)
1836 			rep->re_stat.ets_sendErr++;
1837 		isr &= ~(RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK);
1838 
1839 		/* Transmit completed */
1840 		tx_head = rep->re_tx_head;
1841 		tx_tail = tx_head+1;
1842 		if (tx_tail >= N_TX_DESC)
1843 			tx_tail = 0;
1844 		for (i = 0; i < 2 * N_TX_DESC; i++) {
1845 			if (!rep->re_tx[tx_tail].ret_busy) {
1846 				/* Strange, this buffer is not in-use.
1847 				 * Increment tx_tail until tx_head is
1848 				 * reached (or until we find a buffer that
1849 				 * is in-use.
1850 				 */
1851 				if (tx_tail == tx_head)
1852 					break;
1853 				if (++tx_tail >= N_TX_DESC)
1854 					tx_tail = 0;
1855 				assert(tx_tail < N_TX_DESC);
1856 				continue;
1857 			}
1858 			desc = rep->re_tx_desc;
1859 			desc += tx_tail;
1860 			if (desc->status & DESC_OWN) {
1861 				/* Buffer is not yet ready */
1862 				break;
1863 			}
1864 
1865 			rep->re_stat.ets_packetT++;
1866 			rep->re_tx[tx_tail].ret_busy = FALSE;
1867 
1868 			if (++tx_tail >= N_TX_DESC)
1869 				tx_tail = 0;
1870 			assert(tx_tail < N_TX_DESC);
1871 
1872 			if (rep->re_flags & REF_SEND_AVAIL) {
1873 				rep->re_send_int = TRUE;
1874 				if (!rep->re_got_int) {
1875 					rep->re_got_int = TRUE;
1876 					int_event_check = TRUE;
1877 				}
1878 			}
1879 		}
1880 		assert(i < 2 * N_TX_DESC);
1881 	}
1882 
1883 	/* Ignore Reserved Interrupt */
1884 	if (isr & RL_ISR_RES)
1885 		isr &= ~RL_ISR_RES;
1886 
1887 	if (isr)
1888 		printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr);
1889 }
1890 
1891 /*===========================================================================*
1892  *				rl_watchdog_f				     *
1893  *===========================================================================*/
1894 static void rl_watchdog_f(tp)
1895 minix_timer_t *tp;
1896 {
1897 	re_t *rep;
1898 	/* Use a synchronous alarm instead of a watchdog timer. */
1899 	sys_setalarm(system_hz, 0);
1900 
1901 	rep = &re_state;
1902 
1903 	if (rep->re_mode != REM_ENABLED)
1904 		return;
1905 
1906 	/* Should collect statistics */
1907 	if (!(++rep->dtcc_counter % RE_DTCC_VALUE))
1908 		rtl8169_update_stat(rep);
1909 
1910 	if (!(rep->re_flags & REF_SEND_AVAIL)) {
1911 	/* Assume that an idle system is alive */
1912 	rep->re_tx_alive = TRUE;
1913 		return;
1914 	}
1915 	if (rep->re_tx_alive) {
1916 		rep->re_tx_alive = FALSE;
1917 		return;
1918 	}
1919 	printf("rl_watchdog_f: resetting instance %d mode 0x%x flags 0x%x\n",
1920 		re_instance, rep->re_mode, rep->re_flags);
1921 	printf("tx_head    :%8d  busy %d\t",
1922 		rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
1923 	rep->re_need_reset = TRUE;
1924 	rep->re_got_int = TRUE;
1925 
1926 	check_int_events();
1927 }
1928 
1929