Improve the process for GNU tools
[minix3.git] / minix / drivers / net / rtl8169 / rtl8169.c
blob47c7bcab9f1a907ab9028982d701a5c5aad5a76e
1 /*
2 * rtl8169.c
4 * This file contains a ethernet device driver for Realtek rtl8169 based
5 * ethernet cards.
7 */
9 #include <minix/drivers.h>
10 #include <minix/netdriver.h>
12 #include <machine/pci.h>
13 #include <assert.h>
15 #include "rtl8169.h"
17 #define VERBOSE 0 /* display message during init */
19 #define RE_DTCC_VALUE 600 /* DTCC Update once every 10 minutes */
21 #define RX_CONFIG_MASK 0xff7e1880 /* Clears the bits supported by chip */
23 #define RE_INTR_MASK (RL_IMR_TDU | RL_IMR_FOVW | RL_IMR_PUN | RL_IMR_RDU | \
24 RL_IMR_TER | RL_IMR_TOK | RL_IMR_RER | RL_IMR_ROK)
26 #define RL_ENVVAR "RTLETH" /* Configuration */
28 typedef struct re_desc
30 u32_t status; /* command/status */
31 u32_t vlan; /* VLAN */
32 u32_t addr_low; /* low 32-bits of physical buffer address */
33 u32_t addr_high; /* high 32-bits of physical buffer address */
34 } re_desc;
36 typedef struct re_dtcc
38 u32_t TxOk_low; /* low 32-bits of Tx Ok packets */
39 u32_t TxOk_high; /* high 32-bits of Tx Ok packets */
40 u32_t RxOk_low; /* low 32-bits of Rx Ok packets */
41 u32_t RxOk_high; /* high 32-bits of Rx Ok packets */
42 u32_t TxEr_low; /* low 32-bits of Tx errors */
43 u32_t TxEr_high; /* high 32-bits of Tx errors */
44 u32_t RxEr; /* Rx errors */
45 u16_t MissPkt; /* Missed packets */
46 u16_t FAE; /* Frame Alignment Error packets (MII only) */
47 u32_t Tx1Col; /* Tx Ok packets with 1 collision before Tx */
48 u32_t TxMCol; /* Tx Ok packets with 2..15 collisions */
49 u32_t RxOkPhy_low; /* low 32-bits of Rx Ok packets for us */
50 u32_t RxOkPhy_high; /* high 32-bits of Rx Ok packets for us */
51 u32_t RxOkBrd_low; /* low 32-bits of Rx Ok broadcast packets */
52 u32_t RxOkBrd_high; /* high 32-bits of Rx Ok broadcast packets */
53 u32_t RxOkMul; /* Rx Ok multicast packets */
54 u16_t TxAbt; /* Tx abort packets */
55 u16_t TxUndrn; /* Tx underrun packets */
56 } re_dtcc;
58 typedef struct re {
59 port_t re_base_port;
60 int re_irq;
61 int re_mode;
62 int re_link_up;
63 int re_got_int;
64 int re_send_int;
65 int re_report_link;
66 int re_need_reset;
67 int re_tx_alive;
68 u32_t re_mac;
69 const char *re_model;
71 /* Rx */
72 int re_rx_head;
73 struct {
74 phys_bytes ret_buf;
75 char *v_ret_buf;
76 } re_rx[N_RX_DESC];
78 re_desc *re_rx_desc; /* Rx descriptor buffer */
79 phys_bytes p_rx_desc; /* Rx descriptor buffer physical */
81 /* Tx */
82 int re_tx_head;
83 struct {
84 int ret_busy;
85 phys_bytes ret_buf;
86 char *v_ret_buf;
87 } re_tx[N_TX_DESC];
88 re_desc *re_tx_desc; /* Tx descriptor buffer */
89 phys_bytes p_tx_desc; /* Tx descriptor buffer physical */
90 int re_tx_busy; /* how many Tx descriptors are busy? */
92 int re_hook_id; /* IRQ hook id at kernel */
93 eth_stat_t re_stat;
94 phys_bytes dtcc_buf; /* Dump Tally Counter buffer physical */
95 re_dtcc *v_dtcc_buf; /* Dump Tally Counter buffer */
96 u32_t dtcc_counter; /* DTCC update counter */
97 char re_name[sizeof("rtl8169#n")];
98 u32_t interrupts;
99 } re_t;
101 static re_t re_state;
103 static int re_instance;
105 static unsigned my_inb(u16_t port)
107 u32_t value;
108 int s;
109 if ((s = sys_inb(port, &value)) != OK)
110 printf("RTL8169: warning, sys_inb failed: %d\n", s);
111 return value;
113 static unsigned my_inw(u16_t port)
115 u32_t value;
116 int s;
117 if ((s = sys_inw(port, &value)) != OK)
118 printf("RTL8169: warning, sys_inw failed: %d\n", s);
119 return value;
121 static unsigned my_inl(u16_t port)
123 u32_t value;
124 int s;
125 if ((s = sys_inl(port, &value)) != OK)
126 printf("RTL8169: warning, sys_inl failed: %d\n", s);
127 return value;
129 #define rl_inb(port, offset) (my_inb((port) + (offset)))
130 #define rl_inw(port, offset) (my_inw((port) + (offset)))
131 #define rl_inl(port, offset) (my_inl((port) + (offset)))
133 static void my_outb(u16_t port, u8_t value)
135 int s;
137 if ((s = sys_outb(port, value)) != OK)
138 printf("RTL8169: warning, sys_outb failed: %d\n", s);
140 static void my_outw(u16_t port, u16_t value)
142 int s;
144 if ((s = sys_outw(port, value)) != OK)
145 printf("RTL8169: warning, sys_outw failed: %d\n", s);
147 static void my_outl(u16_t port, u32_t value)
149 int s;
151 if ((s = sys_outl(port, value)) != OK)
152 printf("RTL8169: warning, sys_outl failed: %d\n", s);
154 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value)))
155 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
156 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
158 static int rl_init(unsigned int instance, ether_addr_t *addr);
159 static int rl_probe(re_t *rep, unsigned int skip);
160 static void rl_init_buf(re_t *rep);
161 static void rl_init_hw(re_t *rep, ether_addr_t *addr);
162 static void rl_reset_hw(re_t *rep);
163 static void rl_confaddr(re_t *rep, ether_addr_t *addr);
164 static void rl_stop(void);
165 static void rl_rec_mode(re_t *rep);
166 static void rl_mode(unsigned int mode);
167 static ssize_t rl_recv(struct netdriver_data *data, size_t max);
168 static int rl_send(struct netdriver_data *data, size_t size);
169 static void rl_intr(unsigned int mask);
170 static void rl_check_ints(re_t *rep);
171 static void rl_do_reset(re_t *rep);
172 static void rl_stat(eth_stat_t *stat);
173 #if VERBOSE
174 static void rl_report_link(re_t *rep);
175 static void dump_phy(const re_t *rep);
176 #endif
177 static void rl_handler(re_t *rep);
178 static void rl_alarm(clock_t stamp);
180 static const struct netdriver rl_table = {
181 .ndr_init = rl_init,
182 .ndr_stop = rl_stop,
183 .ndr_mode = rl_mode,
184 .ndr_recv = rl_recv,
185 .ndr_send = rl_send,
186 .ndr_stat = rl_stat,
187 .ndr_intr = rl_intr,
188 .ndr_alarm = rl_alarm
191 /*===========================================================================*
192 * main *
193 *===========================================================================*/
194 int main(int argc, char *argv[])
196 env_setargs(argc, argv);
198 netdriver_task(&rl_table);
200 return 0;
203 /*===========================================================================*
204 * rl_init *
205 *===========================================================================*/
206 static int rl_init(unsigned int instance, ether_addr_t *addr)
208 /* Initialize the rtl8169 driver. */
209 re_t *rep;
211 /* Initialize driver state. */
212 rep = &re_state;
213 memset(rep, 0, sizeof(*rep));
215 strlcpy(rep->re_name, "rtl8169#0", sizeof(rep->re_name));
216 rep->re_name[8] += re_instance;
218 re_instance = instance;
220 /* Try to find a matching device. */
221 if (!rl_probe(rep, instance))
222 return ENXIO;
224 /* Claim buffer memory now. */
225 rl_init_buf(&re_state);
227 /* Initialize the device we found. */
228 rl_init_hw(rep, addr);
230 /* Use a synchronous alarm instead of a watchdog timer. */
231 sys_setalarm(sys_hz(), 0);
233 return OK;
236 /*===========================================================================*
237 * rl_stop *
238 *===========================================================================*/
239 static void rl_stop(void)
241 re_t *rep;
243 rep = &re_state;
245 rl_outb(rep->re_base_port, RL_CR, RL_CR_RST);
248 static void mdio_write(u16_t port, int regaddr, int value)
250 int i;
252 rl_outl(port, RL_PHYAR,
253 0x80000000 | (regaddr & 0x1F) << 16 | (value & 0xFFFF));
255 for (i = 20; i > 0; i--) {
257 * Check if the RTL8169 has completed writing to the specified
258 * MII register
260 if (!(rl_inl(port, RL_PHYAR) & 0x80000000))
261 break;
262 else
263 micro_delay(50);
267 static int mdio_read(u16_t port, int regaddr)
269 int i, value = -1;
271 rl_outl(port, RL_PHYAR, (regaddr & 0x1F) << 16);
273 for (i = 20; i > 0; i--) {
275 * Check if the RTL8169 has completed retrieving data from
276 * the specified MII register
278 if (rl_inl(port, RL_PHYAR) & 0x80000000) {
279 value = (int)(rl_inl(port, RL_PHYAR) & 0xFFFF);
280 break;
281 } else
282 micro_delay(50);
284 return value;
287 static void rtl8169_update_stat(re_t *rep)
289 port_t port;
290 int i;
292 port = rep->re_base_port;
294 /* Fetch Missed Packets */
295 rep->re_stat.ets_missedP += rl_inw(port, RL_MPC);
296 rl_outw(port, RL_MPC, 0x00);
298 /* Dump Tally Counter Command */
299 rl_outl(port, RL_DTCCR_HI, 0); /* 64 bits */
300 rl_outl(port, RL_DTCCR_LO, rep->dtcc_buf | RL_DTCCR_CMD);
301 for (i = 0; i < 1000; i++) {
302 if (!(rl_inl(port, RL_DTCCR_LO) & RL_DTCCR_CMD))
303 break;
304 micro_delay(10);
307 /* Update counters */
308 rep->re_stat.ets_frameAll = rep->v_dtcc_buf->FAE;
309 rep->re_stat.ets_transDef = rep->v_dtcc_buf->TxUndrn;
310 rep->re_stat.ets_transAb = rep->v_dtcc_buf->TxAbt;
311 rep->re_stat.ets_collision =
312 rep->v_dtcc_buf->Tx1Col + rep->v_dtcc_buf->TxMCol;
315 #if 0
316 /*===========================================================================*
317 * rtl8169_dump *
318 *===========================================================================*/
319 static void rtl8169_dump(void)
321 re_dtcc *dtcc;
322 re_t *rep;
324 rep = &re_state;
326 printf("\n");
328 rtl8169_update_stat(rep);
330 printf("Realtek RTL 8169 statistics of instance %d:\n", re_instance);
332 printf("recvErr :%8ld\t", rep->re_stat.ets_recvErr);
333 printf("sendErr :%8ld\t", rep->re_stat.ets_sendErr);
334 printf("OVW :%8ld\n", rep->re_stat.ets_OVW);
336 printf("CRCerr :%8ld\t", rep->re_stat.ets_CRCerr);
337 printf("frameAll :%8ld\t", rep->re_stat.ets_frameAll);
338 printf("missedP :%8ld\n", rep->re_stat.ets_missedP);
340 printf("packetR :%8ld\t", rep->re_stat.ets_packetR);
341 printf("packetT :%8ld\t", rep->re_stat.ets_packetT);
342 printf("transDef :%8ld\n", rep->re_stat.ets_transDef);
344 printf("collision :%8ld\t", rep->re_stat.ets_collision);
345 printf("transAb :%8ld\t", rep->re_stat.ets_transAb);
346 printf("carrSense :%8ld\n", rep->re_stat.ets_carrSense);
348 printf("fifoUnder :%8ld\t", rep->re_stat.ets_fifoUnder);
349 printf("fifoOver :%8ld\t", rep->re_stat.ets_fifoOver);
350 printf("OWC :%8ld\n", rep->re_stat.ets_OWC);
351 printf("interrupts :%8u\n", rep->interrupts);
353 printf("\nRealtek RTL 8169 Tally Counters:\n");
355 dtcc = rep->v_dtcc_buf;
357 if (dtcc->TxOk_high)
358 printf("TxOk :%8u%08u\t",
359 dtcc->TxOk_high, dtcc->TxOk_low);
360 else
361 printf("TxOk :%16u\t", dtcc->TxOk_low);
363 if (dtcc->RxOk_high)
364 printf("RxOk :%8u%08u\n",
365 dtcc->RxOk_high, dtcc->RxOk_low);
366 else
367 printf("RxOk :%16u\n", dtcc->RxOk_low);
369 if (dtcc->TxEr_high)
370 printf("TxEr :%8u%08u\t",
371 dtcc->TxEr_high, dtcc->TxEr_low);
372 else
373 printf("TxEr :%16u\t", dtcc->TxEr_low);
375 printf("RxEr :%16u\n", dtcc->RxEr);
377 printf("Tx1Col :%16u\t", dtcc->Tx1Col);
378 printf("TxMCol :%16u\n", dtcc->TxMCol);
380 if (dtcc->RxOkPhy_high)
381 printf("RxOkPhy :%8u%08u\t",
382 dtcc->RxOkPhy_high, dtcc->RxOkPhy_low);
383 else
384 printf("RxOkPhy :%16u\t", dtcc->RxOkPhy_low);
386 if (dtcc->RxOkBrd_high)
387 printf("RxOkBrd :%8u%08u\n",
388 dtcc->RxOkBrd_high, dtcc->RxOkBrd_low);
389 else
390 printf("RxOkBrd :%16u\n", dtcc->RxOkBrd_low);
392 printf("RxOkMul :%16u\t", dtcc->RxOkMul);
393 printf("MissPkt :%16d\n", dtcc->MissPkt);
395 printf("\nRealtek RTL 8169 Miscellaneous Info:\n");
397 printf("tx_head :%8d busy %d\t",
398 rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
400 #endif
402 /*===========================================================================*
403 * rl_mode *
404 *===========================================================================*/
405 static void rl_mode(unsigned int mode)
407 re_t *rep;
409 rep = &re_state;
411 rep->re_mode = mode;
413 rl_rec_mode(rep);
416 /*===========================================================================*
417 * rl_probe *
418 *===========================================================================*/
419 static int rl_probe(re_t *rep, unsigned int skip)
421 int r, devind;
422 u16_t vid, did;
423 u32_t bar;
424 u8_t ilr;
425 #if VERBOSE
426 char *dname;
427 #endif
429 pci_init();
431 r = pci_first_dev(&devind, &vid, &did);
432 if (r == 0)
433 return 0;
435 while (skip--) {
436 r = pci_next_dev(&devind, &vid, &did);
437 if (!r)
438 return 0;
441 #if VERBOSE
442 dname = pci_dev_name(vid, did);
443 if (!dname)
444 dname = "unknown device";
445 printf("%s: ", rep->re_name);
446 printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
447 #endif
449 pci_reserve(devind);
450 bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
451 if (bar < 0x400) {
452 panic("base address is not properly configured");
454 rep->re_base_port = bar;
456 ilr = pci_attr_r8(devind, PCI_ILR);
457 rep->re_irq = ilr;
458 #if VERBOSE
459 printf("%s: using I/O address 0x%lx, IRQ %d\n",
460 rep->re_name, (unsigned long)bar, ilr);
461 #endif
463 return TRUE;
466 /*===========================================================================*
467 * rl_init_buf *
468 *===========================================================================*/
469 static void rl_init_buf(re_t *rep)
471 size_t rx_bufsize, tx_bufsize, rx_descsize, tx_descsize, tot_bufsize;
472 struct re_desc *desc;
473 phys_bytes buf;
474 char *mallocbuf;
475 int d;
477 /* Allocate receive and transmit descriptors */
478 rx_descsize = (N_RX_DESC * sizeof(struct re_desc));
479 tx_descsize = (N_TX_DESC * sizeof(struct re_desc));
481 /* Allocate receive and transmit buffers */
482 tx_bufsize = ETH_MAX_PACK_SIZE_TAGGED;
483 if (tx_bufsize % 4)
484 tx_bufsize += 4-(tx_bufsize % 4); /* Align */
485 rx_bufsize = RX_BUFSIZE;
486 tot_bufsize = rx_descsize + tx_descsize;
487 tot_bufsize += (N_TX_DESC * tx_bufsize) + (N_RX_DESC * rx_bufsize);
488 tot_bufsize += sizeof(struct re_dtcc);
490 if (tot_bufsize % 4096)
491 tot_bufsize += 4096 - (tot_bufsize % 4096);
493 if (!(mallocbuf = alloc_contig(tot_bufsize, AC_ALIGN64K, &buf)))
494 panic("Couldn't allocate kernel buffer");
496 /* Rx Descriptor */
497 rep->re_rx_desc = (re_desc *)mallocbuf;
498 rep->p_rx_desc = buf;
499 memset(mallocbuf, 0x00, rx_descsize);
500 buf += rx_descsize;
501 mallocbuf += rx_descsize;
503 /* Tx Descriptor */
504 rep->re_tx_desc = (re_desc *)mallocbuf;
505 rep->p_tx_desc = buf;
506 memset(mallocbuf, 0x00, tx_descsize);
507 buf += tx_descsize;
508 mallocbuf += tx_descsize;
510 desc = rep->re_rx_desc;
511 for (d = 0; d < N_RX_DESC; d++) {
512 /* Setting Rx buffer */
513 rep->re_rx[d].ret_buf = buf;
514 rep->re_rx[d].v_ret_buf = mallocbuf;
515 buf += rx_bufsize;
516 mallocbuf += rx_bufsize;
518 /* Setting Rx descriptor */
519 if (d == (N_RX_DESC - 1)) /* Last descriptor: set EOR bit */
520 desc->status = DESC_EOR | DESC_OWN |
521 (RX_BUFSIZE & DESC_RX_LENMASK);
522 else
523 desc->status = DESC_OWN |
524 (RX_BUFSIZE & DESC_RX_LENMASK);
526 desc->addr_low = rep->re_rx[d].ret_buf;
527 desc++;
529 desc = rep->re_tx_desc;
530 for (d = 0; d < N_TX_DESC; d++) {
531 rep->re_tx[d].ret_busy = FALSE;
532 rep->re_tx[d].ret_buf = buf;
533 rep->re_tx[d].v_ret_buf = mallocbuf;
534 buf += tx_bufsize;
535 mallocbuf += tx_bufsize;
537 /* Setting Tx descriptor */
538 desc->addr_low = rep->re_tx[d].ret_buf;
539 desc++;
541 rep->re_tx_busy = 0;
543 /* Dump Tally Counter buffer */
544 rep->dtcc_buf = buf;
545 rep->v_dtcc_buf = (re_dtcc *)mallocbuf;
548 /*===========================================================================*
549 * rl_init_hw *
550 *===========================================================================*/
551 static void rl_init_hw(re_t *rep, ether_addr_t *addr)
553 int s;
554 #if VERBOSE
555 int i;
556 #endif
559 * Set the interrupt handler. The policy is to only send HARD_INT
560 * notifications. Don't reenable interrupts automatically. The id
561 * that is passed back is the interrupt line number.
563 rep->re_hook_id = rep->re_irq;
564 if ((s = sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
565 printf("RTL8169: error, couldn't set IRQ policy: %d\n", s);
567 rl_reset_hw(rep);
569 if ((s = sys_irqenable(&rep->re_hook_id)) != OK)
570 printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
572 #if VERBOSE
573 printf("%s: model: %s mac: 0x%08x\n",
574 rep->re_name, rep->re_model, rep->re_mac);
575 #endif
577 rl_confaddr(rep, addr);
579 #if VERBOSE
580 printf("%s: Ethernet address ", rep->re_name);
581 for (i = 0; i < 6; i++) {
582 printf("%x%c", addr->ea_addr[i],
583 i < 5 ? ':' : '\n');
585 #endif
588 static void rtl8169s_phy_config(port_t port)
590 mdio_write(port, 0x1f, 0x0001);
591 mdio_write(port, 0x06, 0x006e);
592 mdio_write(port, 0x08, 0x0708);
593 mdio_write(port, 0x15, 0x4000);
594 mdio_write(port, 0x18, 0x65c7);
596 mdio_write(port, 0x1f, 0x0001);
597 mdio_write(port, 0x03, 0x00a1);
598 mdio_write(port, 0x02, 0x0008);
599 mdio_write(port, 0x01, 0x0120);
600 mdio_write(port, 0x00, 0x1000);
601 mdio_write(port, 0x04, 0x0800);
602 mdio_write(port, 0x04, 0x0000);
604 mdio_write(port, 0x03, 0xff41);
605 mdio_write(port, 0x02, 0xdf60);
606 mdio_write(port, 0x01, 0x0140);
607 mdio_write(port, 0x00, 0x0077);
608 mdio_write(port, 0x04, 0x7800);
609 mdio_write(port, 0x04, 0x7000);
611 mdio_write(port, 0x03, 0x802f);
612 mdio_write(port, 0x02, 0x4f02);
613 mdio_write(port, 0x01, 0x0409);
614 mdio_write(port, 0x00, 0xf0f9);
615 mdio_write(port, 0x04, 0x9800);
616 mdio_write(port, 0x04, 0x9000);
618 mdio_write(port, 0x03, 0xdf01);
619 mdio_write(port, 0x02, 0xdf20);
620 mdio_write(port, 0x01, 0xff95);
621 mdio_write(port, 0x00, 0xba00);
622 mdio_write(port, 0x04, 0xa800);
623 mdio_write(port, 0x04, 0xa000);
625 mdio_write(port, 0x03, 0xff41);
626 mdio_write(port, 0x02, 0xdf20);
627 mdio_write(port, 0x01, 0x0140);
628 mdio_write(port, 0x00, 0x00bb);
629 mdio_write(port, 0x04, 0xb800);
630 mdio_write(port, 0x04, 0xb000);
632 mdio_write(port, 0x03, 0xdf41);
633 mdio_write(port, 0x02, 0xdc60);
634 mdio_write(port, 0x01, 0x6340);
635 mdio_write(port, 0x00, 0x007d);
636 mdio_write(port, 0x04, 0xd800);
637 mdio_write(port, 0x04, 0xd000);
639 mdio_write(port, 0x03, 0xdf01);
640 mdio_write(port, 0x02, 0xdf20);
641 mdio_write(port, 0x01, 0x100a);
642 mdio_write(port, 0x00, 0xa0ff);
643 mdio_write(port, 0x04, 0xf800);
644 mdio_write(port, 0x04, 0xf000);
646 mdio_write(port, 0x1f, 0x0000);
647 mdio_write(port, 0x0b, 0x0000);
648 mdio_write(port, 0x00, 0x9200);
651 static void rtl8169scd_phy_config(port_t port)
653 mdio_write(port, 0x1f, 0x0001);
654 mdio_write(port, 0x04, 0x0000);
655 mdio_write(port, 0x03, 0x00a1);
656 mdio_write(port, 0x02, 0x0008);
657 mdio_write(port, 0x01, 0x0120);
658 mdio_write(port, 0x00, 0x1000);
659 mdio_write(port, 0x04, 0x0800);
660 mdio_write(port, 0x04, 0x9000);
661 mdio_write(port, 0x03, 0x802f);
662 mdio_write(port, 0x02, 0x4f02);
663 mdio_write(port, 0x01, 0x0409);
664 mdio_write(port, 0x00, 0xf099);
665 mdio_write(port, 0x04, 0x9800);
666 mdio_write(port, 0x04, 0xa000);
667 mdio_write(port, 0x03, 0xdf01);
668 mdio_write(port, 0x02, 0xdf20);
669 mdio_write(port, 0x01, 0xff95);
670 mdio_write(port, 0x00, 0xba00);
671 mdio_write(port, 0x04, 0xa800);
672 mdio_write(port, 0x04, 0xf000);
673 mdio_write(port, 0x03, 0xdf01);
674 mdio_write(port, 0x02, 0xdf20);
675 mdio_write(port, 0x01, 0x101a);
676 mdio_write(port, 0x00, 0xa0ff);
677 mdio_write(port, 0x04, 0xf800);
678 mdio_write(port, 0x04, 0x0000);
679 mdio_write(port, 0x1f, 0x0000);
681 mdio_write(port, 0x1f, 0x0001);
682 mdio_write(port, 0x10, 0xf41b);
683 mdio_write(port, 0x14, 0xfb54);
684 mdio_write(port, 0x18, 0xf5c7);
685 mdio_write(port, 0x1f, 0x0000);
687 mdio_write(port, 0x1f, 0x0001);
688 mdio_write(port, 0x17, 0x0cc0);
689 mdio_write(port, 0x1f, 0x0000);
692 /*===========================================================================*
693 * rl_reset_hw *
694 *===========================================================================*/
695 static void rl_reset_hw(re_t *rep)
697 port_t port;
698 u32_t t;
699 int i;
701 port = rep->re_base_port;
703 rl_outw(port, RL_IMR, 0x0000);
705 /* Reset the device */
706 rl_outb(port, RL_CR, RL_CR_RST);
707 SPIN_UNTIL(!(rl_inb(port, RL_CR) & RL_CR_RST), 1000000);
708 if (rl_inb(port, RL_CR) & RL_CR_RST)
709 printf("rtl8169: reset failed to complete");
710 rl_outw(port, RL_ISR, 0xFFFF);
712 /* Get Model and MAC info */
713 t = rl_inl(port, RL_TCR);
714 rep->re_mac = (t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
715 switch (rep->re_mac) {
716 case RL_TCR_HWVER_RTL8169:
717 rep->re_model = "RTL8169";
719 rl_outw(port, RL_CCR_UNDOC, 0x01);
720 break;
721 case RL_TCR_HWVER_RTL8169S:
722 rep->re_model = "RTL8169S";
724 rtl8169s_phy_config(port);
726 rl_outw(port, RL_CCR_UNDOC, 0x01);
727 mdio_write(port, 0x0b, 0x0000); /* w 0x0b 15 0 0 */
728 break;
729 case RL_TCR_HWVER_RTL8110S:
730 rep->re_model = "RTL8110S";
732 rtl8169s_phy_config(port);
734 rl_outw(port, RL_CCR_UNDOC, 0x01);
735 break;
736 case RL_TCR_HWVER_RTL8169SB:
737 rep->re_model = "RTL8169SB";
739 mdio_write(port, 0x1f, 0x02);
740 mdio_write(port, 0x01, 0x90d0);
741 mdio_write(port, 0x1f, 0x00);
743 rl_outw(port, RL_CCR_UNDOC, 0x01);
744 break;
745 case RL_TCR_HWVER_RTL8110SCd:
746 rep->re_model = "RTL8110SCd";
748 rtl8169scd_phy_config(port);
750 rl_outw(port, RL_CCR_UNDOC, 0x01);
751 break;
752 case RL_TCR_HWVER_RTL8105E:
753 rep->re_model = "RTL8105E";
754 break;
755 default:
756 rep->re_model = "Unknown";
757 rep->re_mac = t;
758 break;
761 mdio_write(port, MII_CTRL, MII_CTRL_RST);
762 for (i = 0; i < 1000; i++) {
763 t = mdio_read(port, MII_CTRL);
764 if (!(t & MII_CTRL_RST))
765 break;
766 else
767 micro_delay(100);
770 t = mdio_read(port, MII_CTRL);
771 t |= MII_CTRL_ANE | MII_CTRL_DM | MII_CTRL_SP_1000;
772 mdio_write(port, MII_CTRL, t);
774 t = mdio_read(port, MII_ANA);
775 t |= MII_ANA_10THD | MII_ANA_10TFD | MII_ANA_100TXHD | MII_ANA_100TXFD;
776 t |= MII_ANA_PAUSE_SYM | MII_ANA_PAUSE_ASYM;
777 mdio_write(port, MII_ANA, t);
779 t = mdio_read(port, MII_1000_CTRL) | 0x300;
780 mdio_write(port, MII_1000_CTRL, t);
782 /* Restart Auto-Negotiation Process */
783 t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_RAN;
784 mdio_write(port, MII_CTRL, t);
786 rl_outw(port, RL_9346CR, RL_9346CR_EEM_CONFIG); /* Unlock */
788 switch (rep->re_mac) {
789 case RL_TCR_HWVER_RTL8169S:
790 case RL_TCR_HWVER_RTL8110S:
791 /* Bit-3 and bit-14 of the C+CR register MUST be 1. */
792 t = rl_inw(port, RL_CPLUSCMD);
793 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW | (1 << 14));
794 break;
795 case RL_TCR_HWVER_RTL8169:
796 case RL_TCR_HWVER_RTL8169SB:
797 case RL_TCR_HWVER_RTL8110SCd:
798 t = rl_inw(port, RL_CPLUSCMD);
799 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW);
800 break;
803 rl_outw(port, RL_INTRMITIGATE, 0x00);
805 t = rl_inb(port, RL_CR);
806 rl_outb(port, RL_CR, t | RL_CR_RE | RL_CR_TE);
808 /* Initialize Rx */
809 rl_outw(port, RL_RMS, RX_BUFSIZE); /* Maximum rx packet size */
810 t = rl_inl(port, RL_RCR) & RX_CONFIG_MASK;
811 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | t);
812 rl_outl(port, RL_RDSAR_LO, rep->p_rx_desc);
813 rl_outl(port, RL_RDSAR_HI, 0x00); /* For 64 bit */
815 /* Initialize Tx */
816 rl_outw(port, RL_ETTHR, 0x3f); /* No early transmit */
817 rl_outl(port, RL_TCR, RL_TCR_MXDMA_2048 | RL_TCR_IFG_STD);
818 rl_outl(port, RL_TNPDS_LO, rep->p_tx_desc);
819 rl_outl(port, RL_TNPDS_HI, 0x00); /* For 64 bit */
821 rl_outw(port, RL_9346CR, RL_9346CR_EEM_NORMAL); /* Lock */
823 rl_outw(port, RL_MPC, 0x00);
824 rl_outw(port, RL_MULINT, rl_inw(port, RL_MULINT) & 0xF000);
825 rl_outw(port, RL_IMR, RE_INTR_MASK);
828 /*===========================================================================*
829 * rl_confaddr *
830 *===========================================================================*/
831 static void rl_confaddr(re_t *rep, ether_addr_t *addr)
833 static char eakey[] = RL_ENVVAR "#_EA";
834 static char eafmt[] = "x:x:x:x:x:x";
835 int i;
836 port_t port;
837 u32_t w;
838 long v;
840 /* User defined ethernet address? */
841 eakey[sizeof(RL_ENVVAR)-1] = '0' + re_instance;
843 port = rep->re_base_port;
845 for (i = 0; i < 6; i++) {
846 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
847 break;
848 addr->ea_addr[i] = v;
851 if (i != 0 && i != 6)
852 env_panic(eakey); /* It's all or nothing */
854 /* Should update ethernet address in hardware */
855 if (i == 6) {
856 port = rep->re_base_port;
857 rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
858 w = 0;
859 for (i = 0; i < 4; i++)
860 w |= (addr->ea_addr[i] << (i * 8));
861 rl_outl(port, RL_IDR, w);
862 w = 0;
863 for (i = 4; i < 6; i++)
864 w |= (addr->ea_addr[i] << ((i-4) * 8));
865 rl_outl(port, RL_IDR + 4, w);
866 rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
869 /* Get ethernet address */
870 for (i = 0; i < 6; i++)
871 addr->ea_addr[i] = rl_inb(port, RL_IDR+i);
874 /*===========================================================================*
875 * rl_rec_mode *
876 *===========================================================================*/
877 static void rl_rec_mode(re_t *rep)
879 port_t port;
880 u32_t rcr;
881 u32_t mc_filter[2]; /* Multicast hash filter */
883 port = rep->re_base_port;
885 mc_filter[1] = mc_filter[0] = 0xffffffff;
886 rl_outl(port, RL_MAR + 0, mc_filter[0]);
887 rl_outl(port, RL_MAR + 4, mc_filter[1]);
889 rcr = rl_inl(port, RL_RCR);
890 rcr &= ~(RL_RCR_AB | RL_RCR_AM | RL_RCR_APM | RL_RCR_AAP);
891 if (rep->re_mode & NDEV_PROMISC)
892 rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
893 if (rep->re_mode & NDEV_BROAD)
894 rcr |= RL_RCR_AB;
895 if (rep->re_mode & NDEV_MULTI)
896 rcr |= RL_RCR_AM;
897 rcr |= RL_RCR_APM;
898 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | rcr);
901 /*===========================================================================*
902 * rl_recv *
903 *===========================================================================*/
904 static ssize_t rl_recv(struct netdriver_data *data, size_t max)
906 int index;
907 port_t port;
908 unsigned totlen, packlen;
909 re_desc *desc;
910 u32_t rxstat;
911 re_t *rep;
913 rep = &re_state;
915 port = rep->re_base_port;
917 if (rl_inb(port, RL_CR) & RL_CR_BUFE)
918 return SUSPEND; /* Receive buffer is empty, suspend */
920 index = rep->re_rx_head;
921 desc = rep->re_rx_desc;
922 desc += index;
924 for (;;) {
925 rxstat = desc->status;
927 if (rxstat & DESC_OWN)
928 return SUSPEND;
930 if (rxstat & DESC_RX_CRC)
931 rep->re_stat.ets_CRCerr++;
933 if ((rxstat & (DESC_FS | DESC_LS)) == (DESC_FS | DESC_LS))
934 break;
936 #if VERBOSE
937 printf("rl_recv: packet is fragmented\n");
938 #endif
939 /* Fix the fragmented packet */
940 if (index == N_RX_DESC - 1) {
941 desc->status = DESC_EOR | DESC_OWN |
942 (RX_BUFSIZE & DESC_RX_LENMASK);
943 index = 0;
944 desc = rep->re_rx_desc;
945 } else {
946 desc->status = DESC_OWN |
947 (RX_BUFSIZE & DESC_RX_LENMASK);
948 index++;
949 desc++;
951 /* Loop until we get correct packet */
954 totlen = rxstat & DESC_RX_LENMASK;
955 if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
956 /* Someting went wrong */
957 printf("rl_recv: bad length (%u) in status 0x%08x\n",
958 totlen, rxstat);
959 panic(NULL);
962 /* Should subtract the CRC */
963 packlen = totlen - ETH_CRC_SIZE;
964 if (packlen > max)
965 packlen = max;
967 netdriver_copyout(data, 0, rep->re_rx[index].v_ret_buf, packlen);
969 rep->re_stat.ets_packetR++;
971 if (index == N_RX_DESC - 1) {
972 desc->status = DESC_EOR | DESC_OWN |
973 (RX_BUFSIZE & DESC_RX_LENMASK);
974 index = 0;
975 } else {
976 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
977 index++;
979 rep->re_rx_head = index;
980 assert(rep->re_rx_head < N_RX_DESC);
982 return packlen;
985 /*===========================================================================*
986 * rl_send *
987 *===========================================================================*/
988 static int rl_send(struct netdriver_data *data, size_t size)
990 int tx_head;
991 re_t *rep;
992 re_desc *desc;
994 rep = &re_state;
996 tx_head = rep->re_tx_head;
998 desc = rep->re_tx_desc;
999 desc += tx_head;
1001 assert(desc);
1002 assert(rep->re_tx_desc);
1003 assert(rep->re_tx_head >= 0 && rep->re_tx_head < N_TX_DESC);
1005 if (rep->re_tx[tx_head].ret_busy)
1006 return SUSPEND;
1008 netdriver_copyin(data, 0, rep->re_tx[tx_head].v_ret_buf, size);
1010 rep->re_tx[tx_head].ret_busy = TRUE;
1011 rep->re_tx_busy++;
1013 if (tx_head == N_TX_DESC - 1) {
1014 desc->status = DESC_EOR | DESC_OWN | DESC_FS | DESC_LS | size;
1015 tx_head = 0;
1016 } else {
1017 desc->status = DESC_OWN | DESC_FS | DESC_LS | size;
1018 tx_head++;
1021 assert(tx_head < N_TX_DESC);
1022 rep->re_tx_head = tx_head;
1024 rl_outl(rep->re_base_port, RL_TPPOLL, RL_TPPOLL_NPQ);
1026 return OK;
1029 /*===========================================================================*
1030 * rl_check_ints *
1031 *===========================================================================*/
1032 static void rl_check_ints(re_t *rep)
1034 if (!rep->re_got_int)
1035 return;
1036 rep->re_got_int = FALSE;
1038 netdriver_recv();
1040 if (rep->re_need_reset)
1041 rl_do_reset(rep);
1043 if (rep->re_send_int) {
1044 rep->re_send_int = FALSE;
1046 netdriver_send();
1049 if (rep->re_report_link) {
1050 rep->re_report_link = FALSE;
1052 #if VERBOSE
1053 rl_report_link(rep);
1054 #endif
1058 /*===========================================================================*
1059 * rl_report_link *
1060 *===========================================================================*/
1061 #if VERBOSE
1062 static void rl_report_link(re_t *rep)
1064 port_t port;
1065 u8_t mii_status;
1067 port = rep->re_base_port;
1069 mii_status = rl_inb(port, RL_PHYSTAT);
1071 if (mii_status & RL_STAT_LINK) {
1072 rep->re_link_up = 1;
1073 printf("%s: link up at ", rep->re_name);
1074 } else {
1075 rep->re_link_up = 0;
1076 printf("%s: link down\n", rep->re_name);
1077 return;
1080 if (mii_status & RL_STAT_1000)
1081 printf("1000 Mbps");
1082 else if (mii_status & RL_STAT_100)
1083 printf("100 Mbps");
1084 else if (mii_status & RL_STAT_10)
1085 printf("10 Mbps");
1087 if (mii_status & RL_STAT_FULLDUP)
1088 printf(", full duplex");
1089 else
1090 printf(", half duplex");
1091 printf("\n");
1093 dump_phy(rep);
1095 #endif
1097 /*===========================================================================*
1098 * rl_do_reset *
1099 *===========================================================================*/
1100 static void rl_do_reset(re_t *rep)
1102 rep->re_need_reset = FALSE;
1103 rl_reset_hw(rep);
1104 rl_rec_mode(rep);
1106 rep->re_tx_head = 0;
1107 if (rep->re_tx[rep->re_tx_head].ret_busy)
1108 rep->re_tx_busy--;
1109 rep->re_tx[rep->re_tx_head].ret_busy = FALSE;
1110 rep->re_send_int = TRUE;
1113 /*===========================================================================*
1114 * rl_stat *
1115 *===========================================================================*/
1116 static void rl_stat(eth_stat_t *stat)
1118 memcpy(stat, &re_state.re_stat, sizeof(*stat));
1121 #if VERBOSE
1122 static void dump_phy(const re_t *rep)
1124 port_t port;
1125 u32_t t;
1127 port = rep->re_base_port;
1129 t = rl_inb(port, RL_CONFIG0);
1130 printf("CONFIG0\t\t:");
1131 t = t & RL_CFG0_ROM;
1132 if (t == RL_CFG0_ROM128K)
1133 printf(" 128K Boot ROM");
1134 else if (t == RL_CFG0_ROM64K)
1135 printf(" 64K Boot ROM");
1136 else if (t == RL_CFG0_ROM32K)
1137 printf(" 32K Boot ROM");
1138 else if (t == RL_CFG0_ROM16K)
1139 printf(" 16K Boot ROM");
1140 else if (t == RL_CFG0_ROM8K)
1141 printf(" 8K Boot ROM");
1142 else if (t == RL_CFG0_ROMNO)
1143 printf(" No Boot ROM");
1144 printf("\n");
1146 t = rl_inb(port, RL_CONFIG1);
1147 printf("CONFIG1\t\t:");
1148 if (t & RL_CFG1_LEDS1)
1149 printf(" LED1");
1150 if (t & RL_CFG1_LEDS0)
1151 printf(" LED0");
1152 if (t & RL_CFG1_DVRLOAD)
1153 printf(" Driver");
1154 if (t & RL_CFG1_LWACT)
1155 printf(" LWAKE");
1156 if (t & RL_CFG1_IOMAP)
1157 printf(" IOMAP");
1158 if (t & RL_CFG1_MEMMAP)
1159 printf(" MEMMAP");
1160 if (t & RL_CFG1_VPD)
1161 printf(" VPD");
1162 if (t & RL_CFG1_PME)
1163 printf(" PME");
1164 printf("\n");
1166 t = rl_inb(port, RL_CONFIG2);
1167 printf("CONFIG2\t\t:");
1168 if (t & RL_CFG2_AUX)
1169 printf(" AUX");
1170 if (t & RL_CFG2_PCIBW)
1171 printf(" PCI-64-Bit");
1172 else
1173 printf(" PCI-32-Bit");
1174 t = t & RL_CFG2_PCICLK;
1175 if (t == RL_CFG2_66MHZ)
1176 printf(" 66 MHz");
1177 else if (t == RL_CFG2_33MHZ)
1178 printf(" 33 MHz");
1179 printf("\n");
1181 t = mdio_read(port, MII_CTRL);
1182 printf("MII_CTRL\t:");
1183 if (t & MII_CTRL_RST)
1184 printf(" Reset");
1185 if (t & MII_CTRL_LB)
1186 printf(" Loopback");
1187 if (t & MII_CTRL_ANE)
1188 printf(" ANE");
1189 if (t & MII_CTRL_PD)
1190 printf(" Power-down");
1191 if (t & MII_CTRL_ISO)
1192 printf(" Isolate");
1193 if (t & MII_CTRL_RAN)
1194 printf(" RAN");
1195 if (t & MII_CTRL_DM)
1196 printf(" Full-duplex");
1197 if (t & MII_CTRL_CT)
1198 printf(" COL-signal");
1199 t = t & (MII_CTRL_SP_LSB | MII_CTRL_SP_MSB);
1200 if (t == MII_CTRL_SP_10)
1201 printf(" 10 Mb/s");
1202 else if (t == MII_CTRL_SP_100)
1203 printf(" 100 Mb/s");
1204 else if (t == MII_CTRL_SP_1000)
1205 printf(" 1000 Mb/s");
1206 printf("\n");
1208 t = mdio_read(port, MII_STATUS);
1209 printf("MII_STATUS\t:");
1210 if (t & MII_STATUS_100T4)
1211 printf(" 100Base-T4");
1212 if (t & MII_STATUS_100XFD)
1213 printf(" 100BaseX-FD");
1214 if (t & MII_STATUS_100XHD)
1215 printf(" 100BaseX-HD");
1216 if (t & MII_STATUS_10FD)
1217 printf(" 10Mbps-FD");
1218 if (t & MII_STATUS_10HD)
1219 printf(" 10Mbps-HD");
1220 if (t & MII_STATUS_100T2FD)
1221 printf(" 100Base-T2-FD");
1222 if (t & MII_STATUS_100T2HD)
1223 printf(" 100Base-T2-HD");
1224 if (t & MII_STATUS_EXT_STAT)
1225 printf(" Ext-stat");
1226 if (t & MII_STATUS_RES)
1227 printf(" res-0x%x", t & MII_STATUS_RES);
1228 if (t & MII_STATUS_MFPS)
1229 printf(" MFPS");
1230 if (t & MII_STATUS_ANC)
1231 printf(" ANC");
1232 if (t & MII_STATUS_RF)
1233 printf(" remote-fault");
1234 if (t & MII_STATUS_ANA)
1235 printf(" ANA");
1236 if (t & MII_STATUS_LS)
1237 printf(" Link");
1238 if (t & MII_STATUS_JD)
1239 printf(" Jabber");
1240 if (t & MII_STATUS_EC)
1241 printf(" Extended-capability");
1242 printf("\n");
1244 t = mdio_read(port, MII_ANA);
1245 printf("MII_ANA\t\t: 0x%04x\n", t);
1247 t = mdio_read(port, MII_ANLPA);
1248 printf("MII_ANLPA\t: 0x%04x\n", t);
1250 t = mdio_read(port, MII_ANE);
1251 printf("MII_ANE\t\t:");
1252 if (t & MII_ANE_RES)
1253 printf(" res-0x%x", t & MII_ANE_RES);
1254 if (t & MII_ANE_PDF)
1255 printf(" Par-Detect-Fault");
1256 if (t & MII_ANE_LPNPA)
1257 printf(" LP-Next-Page-Able");
1258 if (t & MII_ANE_NPA)
1259 printf(" Loc-Next-Page-Able");
1260 if (t & MII_ANE_PR)
1261 printf(" Page-Received");
1262 if (t & MII_ANE_LPANA)
1263 printf(" LP-Auto-Neg-Able");
1264 printf("\n");
1266 t = mdio_read(port, MII_1000_CTRL);
1267 printf("MII_1000_CTRL\t:");
1268 if (t & MII_1000C_FULL)
1269 printf(" 1000BaseT-FD");
1270 if (t & MII_1000C_HALF)
1271 printf(" 1000BaseT-HD");
1272 printf("\n");
1274 t = mdio_read(port, MII_1000_STATUS);
1275 if (t) {
1276 printf("MII_1000_STATUS\t:");
1277 if (t & MII_1000S_LRXOK)
1278 printf(" Local-Receiver");
1279 if (t & MII_1000S_RRXOK)
1280 printf(" Remote-Receiver");
1281 if (t & MII_1000S_HALF)
1282 printf(" 1000BaseT-HD");
1283 if (t & MII_1000S_FULL)
1284 printf(" 1000BaseT-FD");
1285 printf("\n");
1287 t = mdio_read(port, MII_EXT_STATUS);
1288 printf("MII_EXT_STATUS\t:");
1289 if (t & MII_ESTAT_1000XFD)
1290 printf(" 1000BaseX-FD");
1291 if (t & MII_ESTAT_1000XHD)
1292 printf(" 1000BaseX-HD");
1293 if (t & MII_ESTAT_1000TFD)
1294 printf(" 1000BaseT-FD");
1295 if (t & MII_ESTAT_1000THD)
1296 printf(" 1000BaseT-HD");
1297 printf("\n");
1300 #endif
1302 /*===========================================================================*
1303 * rl_intr *
1304 *===========================================================================*/
1305 static void rl_intr(unsigned int __unused mask)
1307 re_t *rep;
1308 int s;
1310 rep = &re_state;
1312 /* Run interrupt handler at driver level. */
1313 rl_handler(rep);
1315 /* Reenable interrupts for this hook. */
1316 if ((s = sys_irqenable(&rep->re_hook_id)) != OK)
1317 printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
1319 /* Perform tasks based on the flagged conditions. */
1320 rl_check_ints(rep);
1323 /*===========================================================================*
1324 * rl_handler *
1325 *===========================================================================*/
1326 static void rl_handler(re_t *rep)
1328 int i, port, tx_head, tx_tail, link_up;
1329 u16_t isr;
1330 re_desc *desc;
1332 port = rep->re_base_port;
1334 /* Ack interrupt */
1335 isr = rl_inw(port, RL_ISR);
1336 if(!isr)
1337 return;
1338 rl_outw(port, RL_ISR, isr);
1339 rep->interrupts++;
1341 if (isr & RL_IMR_FOVW) {
1342 isr &= ~RL_IMR_FOVW;
1343 /* Should do anything? */
1345 rep->re_stat.ets_fifoOver++;
1347 if (isr & RL_IMR_PUN) {
1348 isr &= ~RL_IMR_PUN;
1351 * Either the link status changed or there was a TX fifo
1352 * underrun.
1354 link_up = !(!(rl_inb(port, RL_PHYSTAT) & RL_STAT_LINK));
1355 if (link_up != rep->re_link_up) {
1356 rep->re_report_link = TRUE;
1357 rep->re_got_int = TRUE;
1361 if (isr & (RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK)) {
1362 if (isr & RL_ISR_RER)
1363 rep->re_stat.ets_recvErr++;
1364 isr &= ~(RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK);
1366 rep->re_got_int = TRUE;
1369 if ((isr & (RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK)) || 1) {
1370 if (isr & RL_ISR_TER)
1371 rep->re_stat.ets_sendErr++;
1372 isr &= ~(RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK);
1374 /* Transmit completed */
1375 tx_head = rep->re_tx_head;
1376 tx_tail = tx_head+1;
1377 if (tx_tail >= N_TX_DESC)
1378 tx_tail = 0;
1379 for (i = 0; i < 2 * N_TX_DESC; i++) {
1380 if (!rep->re_tx[tx_tail].ret_busy) {
1381 /* Strange, this buffer is not in-use.
1382 * Increment tx_tail until tx_head is
1383 * reached (or until we find a buffer that
1384 * is in-use.
1386 if (tx_tail == tx_head)
1387 break;
1388 if (++tx_tail >= N_TX_DESC)
1389 tx_tail = 0;
1390 assert(tx_tail < N_TX_DESC);
1391 continue;
1393 desc = rep->re_tx_desc;
1394 desc += tx_tail;
1395 if (desc->status & DESC_OWN) {
1396 /* Buffer is not yet ready */
1397 break;
1400 rep->re_stat.ets_packetT++;
1401 rep->re_tx[tx_tail].ret_busy = FALSE;
1402 rep->re_tx_busy--;
1404 if (++tx_tail >= N_TX_DESC)
1405 tx_tail = 0;
1406 assert(tx_tail < N_TX_DESC);
1408 rep->re_send_int = TRUE;
1409 rep->re_got_int = TRUE;
1410 rep->re_tx_alive = TRUE;
1412 assert(i < 2 * N_TX_DESC);
1415 /* Ignore Reserved Interrupt */
1416 if (isr & RL_ISR_RES)
1417 isr &= ~RL_ISR_RES;
1419 if (isr)
1420 printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr);
1423 /*===========================================================================*
1424 * rl_alarm *
1425 *===========================================================================*/
1426 static void rl_alarm(clock_t __unused stamp)
1428 re_t *rep;
1430 /* Use a synchronous alarm instead of a watchdog timer. */
1431 sys_setalarm(sys_hz(), 0);
1433 rep = &re_state;
1435 /* Should collect statistics */
1436 if (!(++rep->dtcc_counter % RE_DTCC_VALUE))
1437 rtl8169_update_stat(rep);
1439 assert(rep->re_tx_busy >= 0 && rep->re_tx_busy <= N_TX_DESC);
1440 if (rep->re_tx_busy == 0) {
1441 /* Assume that an idle system is alive */
1442 rep->re_tx_alive = TRUE;
1443 return;
1445 if (rep->re_tx_alive) {
1446 rep->re_tx_alive = FALSE;
1447 return;
1449 printf("rl_alarm: resetting instance %d\n", re_instance);
1450 printf("tx_head :%8d busy %d\t",
1451 rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
1452 rep->re_need_reset = TRUE;
1453 rep->re_got_int = TRUE;
1455 rl_check_ints(rep);