rtl8169: reduce verbosity
[minix.git] / drivers / rtl8169 / rtl8169.c
blob94f758034aa268467b169e5eebc140497b6ac8b0
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 <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 <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>
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"
34 #define VERBOSE 0 /* display message during init */
36 #include "rtl8169.h"
38 #define IOVEC_NR 16 /* I/O vectors are handled IOVEC_NR entries at a time. */
40 #define RE_DTCC_VALUE 600 /* DTCC Update after every 10 minutes */
42 #define RX_CONFIG_MASK 0xff7e1880 /* Clears the bits supported by chip */
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)
46 #define RL_ENVVAR "RTLETH" /* Configuration */
48 typedef struct re_desc
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;
56 typedef struct re_dtcc
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;
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;
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];
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 */
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 */
116 /* PCI related */
117 int re_seen; /* TRUE iff device available */
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;
133 re_t;
135 #define REM_DISABLED 0x0
136 #define REM_ENABLED 0x1
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
148 static re_t re_state;
150 static int re_instance;
152 static unsigned my_inb(u16_t port)
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;
160 static unsigned my_inw(u16_t port)
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;
168 static unsigned my_inl(u16_t port)
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;
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)))
180 static void my_outb(u16_t port, u8_t value)
182 int s;
184 if ((s = sys_outb(port, value)) != OK)
185 printf("RTL8169: warning, sys_outb failed: %d\n", s);
187 static void my_outw(u16_t port, u16_t value)
189 int s;
191 if ((s = sys_outw(port, value)) != OK)
192 printf("RTL8169: warning, sys_outw failed: %d\n", s);
194 static void my_outl(u16_t port, u32_t value)
196 int s;
198 if ((s = sys_outl(port, value)) != OK)
199 printf("RTL8169: warning, sys_outl failed: %d\n", s);
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)))
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(timer_t *tp);
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.
232 static message m;
233 static int int_event_check; /* set to TRUE if events arrived */
235 u32_t system_hz;
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);
242 /*===========================================================================*
243 * main *
244 *===========================================================================*/
245 int main(int argc, char *argv[])
247 int r;
248 int ipc_status;
250 /* SEF local startup. */
251 env_setargs(argc, argv);
252 sef_local_startup();
254 while (TRUE) {
255 if ((r = netdriver_receive(ANY, &m, &ipc_status)) != OK)
256 panic("netdriver_receive failed: %d", r);
258 if (is_ipc_notify(ipc_status)) {
259 switch (_ENDPOINT_P(m.m_source)) {
260 case CLOCK:
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.
273 rl_watchdog_f(NULL);
274 break;
275 case HARDWARE:
276 do_hard_int();
277 if (int_event_check) {
278 check_int_events();
280 break ;
281 default:
282 panic("illegal notify from: %d", m.m_type);
285 /* done, get nwe message */
286 continue;
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);
300 /*===========================================================================*
301 * sef_local_startup *
302 *===========================================================================*/
303 static void sef_local_startup()
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);
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);
314 /* Register signal callbacks. */
315 sef_setcb_signal_handler(sef_cb_signal_handler);
317 /* Let SEF perform startup. */
318 sef_startup();
321 /*===========================================================================*
322 * sef_cb_init_fresh *
323 *===========================================================================*/
324 static int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
326 /* Initialize the rtl8169 driver. */
327 long v;
329 system_hz = sys_hz();
331 v = 0;
332 (void) env_parse("instance", "d", 0, &v, 0, 255);
333 re_instance = (int) v;
335 /* Claim buffer memory now. */
336 rl_init_buf(&re_state);
338 /* Announce we are up! */
339 netdriver_announce();
341 return(OK);
344 /*===========================================================================*
345 * sef_cb_signal_handler *
346 *===========================================================================*/
347 static void sef_cb_signal_handler(int signo)
349 re_t *rep;
351 /* Only check for termination signal, ignore anything else. */
352 if (signo != SIGTERM) return;
354 rep = &re_state;
355 if (rep->re_mode == REM_ENABLED)
356 rl_outb(rep->re_base_port, RL_CR, RL_CR_RST);
358 exit(0);
361 static void mdio_write(u16_t port, int regaddr, int value)
363 int i;
365 rl_outl(port, RL_PHYAR, 0x80000000 | (regaddr & 0x1F) << 16 | (value & 0xFFFF));
367 for (i = 20; i > 0; i--) {
369 * Check if the RTL8169 has completed writing to the specified
370 * MII register
372 if (!(rl_inl(port, RL_PHYAR) & 0x80000000))
373 break;
374 else
375 micro_delay(50);
379 static int mdio_read(u16_t port, int regaddr)
381 int i, value = -1;
383 rl_outl(port, RL_PHYAR, (regaddr & 0x1F) << 16);
385 for (i = 20; i > 0; i--) {
387 * Check if the RTL8169 has completed retrieving data from
388 * the specified MII register
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);
396 return value;
399 /*===========================================================================*
400 * check_int_events *
401 *===========================================================================*/
402 static void check_int_events(void)
404 re_t *rep;
406 rep = &re_state;
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);
417 static void rtl8169_update_stat(re_t *rep)
419 port_t port;
420 int i;
422 port = rep->re_base_port;
424 /* Fetch Missed Packets */
425 rep->re_stat.ets_missedP += rl_inw(port, RL_MPC);
426 rl_outw(port, RL_MPC, 0x00);
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);
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;
445 #if 0
446 /*===========================================================================*
447 * rtl8169_dump *
448 *===========================================================================*/
449 static void rtl8169_dump(void)
451 re_dtcc *dtcc;
452 re_t *rep;
454 rep = &re_state;
456 printf("\n");
457 if (rep->re_mode == REM_DISABLED)
458 printf("Realtek RTL 8169 instance %d is disabled\n",
459 re_instance);
461 if (rep->re_mode != REM_ENABLED)
462 return;
464 rtl8169_update_stat(rep);
466 printf("Realtek RTL 8169 statistics of instance %d:\n", re_instance);
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);
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);
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);
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);
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);
489 printf("\nRealtek RTL 8169 Tally Counters:\n");
491 dtcc = rep->v_dtcc_buf;
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);
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);
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);
508 printf("RxEr :%16ld\n", dtcc->RxEr);
510 printf("Tx1Col :%16ld\t", dtcc->Tx1Col);
511 printf("TxMCol :%16ld\n", dtcc->TxMCol);
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);
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);
523 printf("RxOkMul :%16ld\t", dtcc->RxOkMul);
524 printf("MissPkt :%16d\n", dtcc->MissPkt);
526 printf("\nRealtek RTL 8169 Miscellaneous Info:\n");
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);
532 #endif
534 /*===========================================================================*
535 * do_init *
536 *===========================================================================*/
537 static void rl_init(mp)
538 message *mp;
540 static int first_time = 1;
542 re_t *rep;
543 message reply_mess;
545 if (first_time) {
546 first_time = 0;
547 rl_pci_conf(); /* Configure PCI devices. */
549 /* Use a synchronous alarm instead of a watchdog timer. */
550 sys_setalarm(system_hz, 0);
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.DL_STAT = ENXIO;
561 mess_reply(mp, &reply_mess);
562 return;
564 if (rep->re_mode == REM_ENABLED)
565 rl_init_hw(rep);
568 assert(rep->re_mode == REM_ENABLED);
569 assert(rep->re_flags & REF_ENABLED);
571 rep->re_flags &= ~(REF_PROMISC | REF_MULTI | REF_BROAD);
573 if (mp->DL_MODE & DL_PROMISC_REQ)
574 rep->re_flags |= REF_PROMISC;
575 if (mp->DL_MODE & DL_MULTI_REQ)
576 rep->re_flags |= REF_MULTI;
577 if (mp->DL_MODE & DL_BROAD_REQ)
578 rep->re_flags |= REF_BROAD;
580 rl_rec_mode(rep);
582 reply_mess.m_type = DL_CONF_REPLY;
583 reply_mess.DL_STAT = OK;
584 *(ether_addr_t *) reply_mess.DL_HWADDR = rep->re_address;
586 mess_reply(mp, &reply_mess);
589 /*===========================================================================*
590 * rl_pci_conf *
591 *===========================================================================*/
592 static void rl_pci_conf()
594 re_t *rep;
596 rep = &re_state;
598 strlcpy(rep->re_name, "rtl8169#0", sizeof(rep->re_name));
599 rep->re_name[8] += re_instance;
600 rep->re_seen = FALSE;
602 pci_init();
604 if (rl_probe(rep, re_instance))
605 rep->re_seen = TRUE;
608 /*===========================================================================*
609 * rl_probe *
610 *===========================================================================*/
611 static int rl_probe(rep, skip)
612 re_t *rep;
613 int skip;
615 int r, devind;
616 u16_t vid, did;
617 u32_t bar;
618 u8_t ilr;
619 #if VERBOSE
620 char *dname;
621 #endif
623 r = pci_first_dev(&devind, &vid, &did);
624 if (r == 0)
625 return 0;
627 while (skip--) {
628 r = pci_next_dev(&devind, &vid, &did);
629 if (!r)
630 return 0;
633 #if VERBOSE
634 dname = pci_dev_name(vid, did);
635 if (!dname)
636 dname = "unknown device";
637 printf("%s: ", rep->re_name);
638 printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
639 #endif
641 pci_reserve(devind);
642 bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
643 if (bar < 0x400) {
644 panic("base address is not properly configured");
646 rep->re_base_port = bar;
648 ilr = pci_attr_r8(devind, PCI_ILR);
649 rep->re_irq = ilr;
650 #if VERBOSE
651 printf("%s: using I/O address 0x%lx, IRQ %d\n",
652 rep->re_name, (unsigned long)bar, ilr);
653 #endif
655 return TRUE;
658 /*===========================================================================*
659 * rl_conf_hw *
660 *===========================================================================*/
661 static void rl_conf_hw(rep)
662 re_t *rep;
664 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
666 rep->re_mode = REM_DISABLED; /* Superfluous */
668 if (rep->re_seen)
669 rep->re_mode = REM_ENABLED; /* PCI device is present */
670 if (rep->re_mode != REM_ENABLED)
671 return;
673 rep->re_flags = REF_EMPTY;
674 rep->re_link_up = 0;
675 rep->re_got_int = 0;
676 rep->re_send_int = 0;
677 rep->re_report_link = 0;
678 rep->re_need_reset = 0;
679 rep->re_tx_alive = 0;
680 rep->re_rx_head = 0;
681 rep->re_read_s = 0;
682 rep->re_tx_head = 0;
683 rep->re_stat = empty_stat;
684 rep->dtcc_counter = 0;
687 /*===========================================================================*
688 * rl_init_buf *
689 *===========================================================================*/
690 static void rl_init_buf(rep)
691 re_t *rep;
693 size_t rx_bufsize, tx_bufsize, rx_descsize, tx_descsize, tot_bufsize;
694 struct re_desc *desc;
695 phys_bytes buf;
696 char *mallocbuf;
697 int d;
699 assert(!rep->setup);
701 /* Allocate receive and transmit descriptors */
702 rx_descsize = (N_RX_DESC * sizeof(struct re_desc));
703 tx_descsize = (N_TX_DESC * sizeof(struct re_desc));
705 /* Allocate receive and transmit buffers */
706 tx_bufsize = ETH_MAX_PACK_SIZE_TAGGED;
707 if (tx_bufsize % 4)
708 tx_bufsize += 4-(tx_bufsize % 4); /* Align */
709 rx_bufsize = RX_BUFSIZE;
710 tot_bufsize = rx_descsize + tx_descsize;
711 tot_bufsize += (N_TX_DESC * tx_bufsize) + (N_RX_DESC * rx_bufsize);
712 tot_bufsize += sizeof(struct re_dtcc);
714 if (tot_bufsize % 4096)
715 tot_bufsize += 4096 - (tot_bufsize % 4096);
717 if (!(mallocbuf = alloc_contig(tot_bufsize, AC_ALIGN64K, &buf)))
718 panic("Couldn't allocate kernel buffer");
720 /* Rx Descriptor */
721 rep->re_rx_desc = (re_desc *)mallocbuf;
722 rep->p_rx_desc = buf;
723 memset(mallocbuf, 0x00, rx_descsize);
724 buf += rx_descsize;
725 mallocbuf += rx_descsize;
727 /* Tx Descriptor */
728 rep->re_tx_desc = (re_desc *)mallocbuf;
729 rep->p_tx_desc = buf;
730 memset(mallocbuf, 0x00, tx_descsize);
731 buf += tx_descsize;
732 mallocbuf += tx_descsize;
734 desc = rep->re_rx_desc;
735 for (d = 0; d < N_RX_DESC; d++) {
736 /* Setting Rx buffer */
737 rep->re_rx[d].ret_buf = buf;
738 rep->re_rx[d].v_ret_buf = mallocbuf;
739 buf += rx_bufsize;
740 mallocbuf += rx_bufsize;
742 /* Setting Rx descriptor */
743 if (d == (N_RX_DESC - 1)) /* Last descriptor? if so, set the EOR bit */
744 desc->status = DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
745 else
746 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
748 desc->addr_low = rep->re_rx[d].ret_buf;
749 desc++;
751 desc = rep->re_tx_desc;
752 for (d = 0; d < N_TX_DESC; d++) {
753 rep->re_tx[d].ret_busy = FALSE;
754 rep->re_tx[d].ret_buf = buf;
755 rep->re_tx[d].v_ret_buf = mallocbuf;
756 buf += tx_bufsize;
757 mallocbuf += tx_bufsize;
759 /* Setting Tx descriptor */
760 desc->addr_low = rep->re_tx[d].ret_buf;
761 desc++;
764 /* Dump Tally Counter buffer */
765 rep->dtcc_buf = buf;
766 rep->v_dtcc_buf = (re_dtcc *)mallocbuf;
768 rep->setup = 1;
771 /*===========================================================================*
772 * rl_init_hw *
773 *===========================================================================*/
774 static void rl_init_hw(rep)
775 re_t *rep;
777 int s;
778 #if VERBOSE
779 int i;
780 #endif
782 rep->re_flags = REF_EMPTY;
783 rep->re_flags |= REF_ENABLED;
786 * Set the interrupt handler. The policy is to only send HARD_INT
787 * notifications. Don't reenable interrupts automatically. The id
788 * that is passed back is the interrupt line number.
790 rep->re_hook_id = rep->re_irq;
791 if ((s = sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
792 printf("RTL8169: error, couldn't set IRQ policy: %d\n", s);
794 rl_reset_hw(rep);
796 if ((s = sys_irqenable(&rep->re_hook_id)) != OK)
797 printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
799 #if VERBOSE
800 printf("%s: model: %s mac: 0x%08x\n",
801 rep->re_name, rep->re_model, rep->re_mac);
802 #endif
804 rl_confaddr(rep);
805 #if VERBOSE
806 printf("%s: Ethernet address ", rep->re_name);
807 for (i = 0; i < 6; i++) {
808 printf("%x%c", rep->re_address.ea_addr[i],
809 i < 5 ? ':' : '\n');
811 #endif
814 static void rtl8169s_phy_config(port_t port)
816 mdio_write(port, 0x1f, 0x0001);
817 mdio_write(port, 0x06, 0x006e);
818 mdio_write(port, 0x08, 0x0708);
819 mdio_write(port, 0x15, 0x4000);
820 mdio_write(port, 0x18, 0x65c7);
822 mdio_write(port, 0x1f, 0x0001);
823 mdio_write(port, 0x03, 0x00a1);
824 mdio_write(port, 0x02, 0x0008);
825 mdio_write(port, 0x01, 0x0120);
826 mdio_write(port, 0x00, 0x1000);
827 mdio_write(port, 0x04, 0x0800);
828 mdio_write(port, 0x04, 0x0000);
830 mdio_write(port, 0x03, 0xff41);
831 mdio_write(port, 0x02, 0xdf60);
832 mdio_write(port, 0x01, 0x0140);
833 mdio_write(port, 0x00, 0x0077);
834 mdio_write(port, 0x04, 0x7800);
835 mdio_write(port, 0x04, 0x7000);
837 mdio_write(port, 0x03, 0x802f);
838 mdio_write(port, 0x02, 0x4f02);
839 mdio_write(port, 0x01, 0x0409);
840 mdio_write(port, 0x00, 0xf0f9);
841 mdio_write(port, 0x04, 0x9800);
842 mdio_write(port, 0x04, 0x9000);
844 mdio_write(port, 0x03, 0xdf01);
845 mdio_write(port, 0x02, 0xdf20);
846 mdio_write(port, 0x01, 0xff95);
847 mdio_write(port, 0x00, 0xba00);
848 mdio_write(port, 0x04, 0xa800);
849 mdio_write(port, 0x04, 0xa000);
851 mdio_write(port, 0x03, 0xff41);
852 mdio_write(port, 0x02, 0xdf20);
853 mdio_write(port, 0x01, 0x0140);
854 mdio_write(port, 0x00, 0x00bb);
855 mdio_write(port, 0x04, 0xb800);
856 mdio_write(port, 0x04, 0xb000);
858 mdio_write(port, 0x03, 0xdf41);
859 mdio_write(port, 0x02, 0xdc60);
860 mdio_write(port, 0x01, 0x6340);
861 mdio_write(port, 0x00, 0x007d);
862 mdio_write(port, 0x04, 0xd800);
863 mdio_write(port, 0x04, 0xd000);
865 mdio_write(port, 0x03, 0xdf01);
866 mdio_write(port, 0x02, 0xdf20);
867 mdio_write(port, 0x01, 0x100a);
868 mdio_write(port, 0x00, 0xa0ff);
869 mdio_write(port, 0x04, 0xf800);
870 mdio_write(port, 0x04, 0xf000);
872 mdio_write(port, 0x1f, 0x0000);
873 mdio_write(port, 0x0b, 0x0000);
874 mdio_write(port, 0x00, 0x9200);
877 static void rtl8169scd_phy_config(port_t port)
879 mdio_write(port, 0x1f, 0x0001);
880 mdio_write(port, 0x04, 0x0000);
881 mdio_write(port, 0x03, 0x00a1);
882 mdio_write(port, 0x02, 0x0008);
883 mdio_write(port, 0x01, 0x0120);
884 mdio_write(port, 0x00, 0x1000);
885 mdio_write(port, 0x04, 0x0800);
886 mdio_write(port, 0x04, 0x9000);
887 mdio_write(port, 0x03, 0x802f);
888 mdio_write(port, 0x02, 0x4f02);
889 mdio_write(port, 0x01, 0x0409);
890 mdio_write(port, 0x00, 0xf099);
891 mdio_write(port, 0x04, 0x9800);
892 mdio_write(port, 0x04, 0xa000);
893 mdio_write(port, 0x03, 0xdf01);
894 mdio_write(port, 0x02, 0xdf20);
895 mdio_write(port, 0x01, 0xff95);
896 mdio_write(port, 0x00, 0xba00);
897 mdio_write(port, 0x04, 0xa800);
898 mdio_write(port, 0x04, 0xf000);
899 mdio_write(port, 0x03, 0xdf01);
900 mdio_write(port, 0x02, 0xdf20);
901 mdio_write(port, 0x01, 0x101a);
902 mdio_write(port, 0x00, 0xa0ff);
903 mdio_write(port, 0x04, 0xf800);
904 mdio_write(port, 0x04, 0x0000);
905 mdio_write(port, 0x1f, 0x0000);
907 mdio_write(port, 0x1f, 0x0001);
908 mdio_write(port, 0x10, 0xf41b);
909 mdio_write(port, 0x14, 0xfb54);
910 mdio_write(port, 0x18, 0xf5c7);
911 mdio_write(port, 0x1f, 0x0000);
913 mdio_write(port, 0x1f, 0x0001);
914 mdio_write(port, 0x17, 0x0cc0);
915 mdio_write(port, 0x1f, 0x0000);
918 /*===========================================================================*
919 * rl_reset_hw *
920 *===========================================================================*/
921 static void rl_reset_hw(rep)
922 re_t *rep;
924 port_t port;
925 u32_t t;
926 int i;
928 port = rep->re_base_port;
930 rl_outw(port, RL_IMR, 0x0000);
932 /* Reset the device */
933 rl_outb(port, RL_CR, RL_CR_RST);
934 SPIN_UNTIL(!(rl_inb(port, RL_CR) & RL_CR_RST), 1000000);
935 if (rl_inb(port, RL_CR) & RL_CR_RST)
936 printf("rtl8169: reset failed to complete");
937 rl_outw(port, RL_ISR, 0xFFFF);
939 /* Get Model and MAC info */
940 t = rl_inl(port, RL_TCR);
941 rep->re_mac = (t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
942 switch (rep->re_mac) {
943 case RL_TCR_HWVER_RTL8169:
944 rep->re_model = "RTL8169";
946 rl_outw(port, RL_CCR_UNDOC, 0x01);
947 break;
948 case RL_TCR_HWVER_RTL8169S:
949 rep->re_model = "RTL8169S";
951 rtl8169s_phy_config(port);
953 rl_outw(port, RL_CCR_UNDOC, 0x01);
954 mdio_write(port, 0x0b, 0x0000); /* w 0x0b 15 0 0 */
955 break;
956 case RL_TCR_HWVER_RTL8110S:
957 rep->re_model = "RTL8110S";
959 rtl8169s_phy_config(port);
961 rl_outw(port, RL_CCR_UNDOC, 0x01);
962 break;
963 case RL_TCR_HWVER_RTL8169SB:
964 rep->re_model = "RTL8169SB";
966 mdio_write(port, 0x1f, 0x02);
967 mdio_write(port, 0x01, 0x90d0);
968 mdio_write(port, 0x1f, 0x00);
970 rl_outw(port, RL_CCR_UNDOC, 0x01);
971 break;
972 case RL_TCR_HWVER_RTL8110SCd:
973 rep->re_model = "RTL8110SCd";
975 rtl8169scd_phy_config(port);
977 rl_outw(port, RL_CCR_UNDOC, 0x01);
978 break;
979 case RL_TCR_HWVER_RTL8105E:
980 rep->re_model = "RTL8105E";
981 break;
982 default:
983 rep->re_model = "Unknown";
984 rep->re_mac = t;
985 break;
988 mdio_write(port, MII_CTRL, MII_CTRL_RST);
989 for (i = 0; i < 1000; i++) {
990 t = mdio_read(port, MII_CTRL);
991 if (!(t & MII_CTRL_RST))
992 break;
993 else
994 micro_delay(100);
997 t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_DM | MII_CTRL_SP_1000;
998 mdio_write(port, MII_CTRL, t);
1000 t = mdio_read(port, MII_ANA);
1001 t |= MII_ANA_10THD | MII_ANA_10TFD | MII_ANA_100TXHD | MII_ANA_100TXFD;
1002 t |= MII_ANA_PAUSE_SYM | MII_ANA_PAUSE_ASYM;
1003 mdio_write(port, MII_ANA, t);
1005 t = mdio_read(port, MII_1000_CTRL) | 0x300;
1006 mdio_write(port, MII_1000_CTRL, t);
1008 /* Restart Auto-Negotiation Process */
1009 t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_RAN;
1010 mdio_write(port, MII_CTRL, t);
1012 rl_outw(port, RL_9346CR, RL_9346CR_EEM_CONFIG); /* Unlock */
1014 switch (rep->re_mac) {
1015 case RL_TCR_HWVER_RTL8169S:
1016 case RL_TCR_HWVER_RTL8110S:
1017 /* Bit-3 and bit-14 of the C+CR register MUST be 1. */
1018 t = rl_inw(port, RL_CPLUSCMD);
1019 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW | (1 << 14));
1020 break;
1021 case RL_TCR_HWVER_RTL8169:
1022 case RL_TCR_HWVER_RTL8169SB:
1023 case RL_TCR_HWVER_RTL8110SCd:
1024 t = rl_inw(port, RL_CPLUSCMD);
1025 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW);
1026 break;
1029 rl_outw(port, RL_INTRMITIGATE, 0x00);
1031 t = rl_inb(port, RL_CR);
1032 rl_outb(port, RL_CR, t | RL_CR_RE | RL_CR_TE);
1034 /* Initialize Rx */
1035 rl_outw(port, RL_RMS, RX_BUFSIZE); /* Maximum rx packet size */
1036 t = rl_inl(port, RL_RCR) & RX_CONFIG_MASK;
1037 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | t);
1038 rl_outl(port, RL_RDSAR_LO, rep->p_rx_desc);
1039 rl_outl(port, RL_RDSAR_HI, 0x00); /* For 64 bit */
1041 /* Initialize Tx */
1042 rl_outw(port, RL_ETTHR, 0x3f); /* No early transmit */
1043 rl_outl(port, RL_TCR, RL_TCR_MXDMA_2048 | RL_TCR_IFG_STD);
1044 rl_outl(port, RL_TNPDS_LO, rep->p_tx_desc);
1045 rl_outl(port, RL_TNPDS_HI, 0x00); /* For 64 bit */
1047 rl_outw(port, RL_9346CR, RL_9346CR_EEM_NORMAL); /* Lock */
1049 rl_outw(port, RL_MPC, 0x00);
1050 rl_outw(port, RL_MULINT, rl_inw(port, RL_MULINT) & 0xF000);
1051 rl_outw(port, RL_IMR, RE_INTR_MASK);
1054 /*===========================================================================*
1055 * rl_confaddr *
1056 *===========================================================================*/
1057 static void rl_confaddr(rep)
1058 re_t *rep;
1060 static char eakey[] = RL_ENVVAR "#_EA";
1061 static char eafmt[] = "x:x:x:x:x:x";
1063 int i;
1064 port_t port;
1065 u32_t w;
1066 long v;
1068 /* User defined ethernet address? */
1069 eakey[sizeof(RL_ENVVAR)-1] = '0' + re_instance;
1071 port = rep->re_base_port;
1073 for (i = 0; i < 6; i++) {
1074 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
1075 break;
1076 rep->re_address.ea_addr[i] = v;
1079 if (i != 0 && i != 6)
1080 env_panic(eakey); /* It's all or nothing */
1082 /* Should update ethernet address in hardware */
1083 if (i == 6) {
1084 port = rep->re_base_port;
1085 rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
1086 w = 0;
1087 for (i = 0; i < 4; i++)
1088 w |= (rep->re_address.ea_addr[i] << (i * 8));
1089 rl_outl(port, RL_IDR, w);
1090 w = 0;
1091 for (i = 4; i < 6; i++)
1092 w |= (rep->re_address.ea_addr[i] << ((i-4) * 8));
1093 rl_outl(port, RL_IDR + 4, w);
1094 rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
1097 /* Get ethernet address */
1098 for (i = 0; i < 6; i++)
1099 rep->re_address.ea_addr[i] = rl_inb(port, RL_IDR+i);
1102 /*===========================================================================*
1103 * rl_rec_mode *
1104 *===========================================================================*/
1105 static void rl_rec_mode(rep)
1106 re_t *rep;
1108 port_t port;
1109 u32_t rcr;
1110 u32_t mc_filter[2]; /* Multicast hash filter */
1112 port = rep->re_base_port;
1114 mc_filter[1] = mc_filter[0] = 0xffffffff;
1115 rl_outl(port, RL_MAR + 0, mc_filter[0]);
1116 rl_outl(port, RL_MAR + 4, mc_filter[1]);
1118 rcr = rl_inl(port, RL_RCR);
1119 rcr &= ~(RL_RCR_AB | RL_RCR_AM | RL_RCR_APM | RL_RCR_AAP);
1120 if (rep->re_flags & REF_PROMISC)
1121 rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
1122 if (rep->re_flags & REF_BROAD)
1123 rcr |= RL_RCR_AB;
1124 if (rep->re_flags & REF_MULTI)
1125 rcr |= RL_RCR_AM;
1126 rcr |= RL_RCR_APM;
1127 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | rcr);
1130 void transmittest(re_t *rep)
1132 int tx_head;
1133 int ipc_status;
1135 tx_head = rep->re_tx_head;
1137 if(rep->re_tx[tx_head].ret_busy) {
1138 do {
1139 message m;
1140 int r;
1141 if ((r = netdriver_receive(ANY, &m, &ipc_status)) != OK)
1142 panic("netdriver_receive failed: %d", r);
1143 } while(m.m_source != HARDWARE);
1144 assert(!(rep->re_flags & REF_SEND_AVAIL));
1145 rep->re_flags |= REF_SEND_AVAIL;
1148 return;
1151 /*===========================================================================*
1152 * rl_readv_s *
1153 *===========================================================================*/
1154 static void rl_readv_s(const message *mp, int from_int)
1156 int i, j, n, s, count, size, index;
1157 port_t port;
1158 unsigned totlen, packlen;
1159 re_desc *desc;
1160 u32_t rxstat = 0x12345678;
1161 re_t *rep;
1162 iovec_s_t *iovp;
1163 int cps;
1164 int iov_offset = 0;
1166 rep = &re_state;
1168 rep->re_client = mp->m_source;
1169 count = mp->DL_COUNT;
1171 assert(rep->re_mode == REM_ENABLED);
1172 assert(rep->re_flags & REF_ENABLED);
1174 port = rep->re_base_port;
1177 * Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1179 if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
1180 goto suspend; /* Receive buffer is empty, suspend */
1182 index = rep->re_rx_head;
1183 desc = rep->re_rx_desc;
1184 desc += index;
1185 readvs_loop:
1186 rxstat = desc->status;
1188 if (rxstat & DESC_OWN)
1189 goto suspend;
1191 if (rxstat & DESC_RX_CRC)
1192 rep->re_stat.ets_CRCerr++;
1194 if ((rxstat & (DESC_FS | DESC_LS)) != (DESC_FS | DESC_LS)) {
1195 #if VERBOSE
1196 printf("rl_readv_s: packet is fragmented\n");
1197 #endif
1198 /* Fix the fragmented packet */
1199 if (index == N_RX_DESC - 1) {
1200 desc->status = DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1201 index = 0;
1202 desc = rep->re_rx_desc;
1203 } else {
1204 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1205 index++;
1206 desc++;
1208 goto readvs_loop; /* Loop until we get correct packet */
1211 totlen = rxstat & DESC_RX_LENMASK;
1212 if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
1213 /* Someting went wrong */
1214 printf("rl_readv_s: bad length (%u) in status 0x%08x\n",
1215 totlen, rxstat);
1216 panic(NULL);
1219 /* Should subtract the CRC */
1220 packlen = totlen - ETH_CRC_SIZE;
1222 size = 0;
1223 for (i = 0; i < count; i += IOVEC_NR,
1224 iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
1226 n = IOVEC_NR;
1227 if (i + n > count)
1228 n = count-i;
1229 cps = sys_safecopyfrom(mp->m_source, mp->DL_GRANT, iov_offset,
1230 (vir_bytes) rep->re_iovec_s,
1231 n * sizeof(rep->re_iovec_s[0]));
1232 if (cps != OK) {
1233 panic("rl_readv_s: sys_safecopyfrom failed: %d", cps);
1236 for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
1237 s = iovp->iov_size;
1238 if (size + s > packlen) {
1239 assert(packlen > size);
1240 s = packlen-size;
1243 cps = sys_safecopyto(mp->m_source, iovp->iov_grant, 0,
1244 (vir_bytes) rep->re_rx[index].v_ret_buf + size, s);
1245 if (cps != OK)
1246 panic("rl_readv_s: sys_safecopyto failed: %d", cps);
1248 size += s;
1249 if (size == packlen)
1250 break;
1252 if (size == packlen)
1253 break;
1255 if (size < packlen)
1256 assert(0);
1258 rep->re_stat.ets_packetR++;
1259 rep->re_read_s = packlen;
1260 if (index == N_RX_DESC - 1) {
1261 desc->status = DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1262 index = 0;
1263 } else {
1264 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1265 index++;
1267 rep->re_rx_head = index;
1268 assert(rep->re_rx_head < N_RX_DESC);
1269 rep->re_flags = (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
1271 if (!from_int)
1272 reply(rep);
1274 return;
1276 suspend:
1277 if (from_int) {
1278 assert(rep->re_flags & REF_READING);
1280 /* No need to store any state */
1281 return;
1284 rep->re_rx_mess = *mp;
1285 assert(!(rep->re_flags & REF_READING));
1286 rep->re_flags |= REF_READING;
1288 reply(rep);
1291 /*===========================================================================*
1292 * rl_writev_s *
1293 *===========================================================================*/
1294 static void rl_writev_s(const message *mp, int from_int)
1296 int i, j, n, s, count, size;
1297 int tx_head;
1298 re_t *rep;
1299 iovec_s_t *iovp;
1300 re_desc *desc;
1301 char *ret;
1302 int cps;
1303 int iov_offset = 0;
1305 rep = &re_state;
1307 rep->re_client = mp->m_source;
1308 count = mp->DL_COUNT;
1309 assert(rep->setup);
1311 assert(rep->re_mode == REM_ENABLED);
1312 assert(rep->re_flags & REF_ENABLED);
1314 if (from_int) {
1315 assert(rep->re_flags & REF_SEND_AVAIL);
1316 rep->re_flags &= ~REF_SEND_AVAIL;
1317 rep->re_send_int = FALSE;
1318 rep->re_tx_alive = TRUE;
1321 tx_head = rep->re_tx_head;
1323 desc = rep->re_tx_desc;
1324 desc += tx_head;
1326 if(!desc || !rep->re_tx_desc) {
1327 printf("desc %p, re_tx_desc %p, tx_head %d, setup %d\n",
1328 desc, rep->re_tx_desc, tx_head, rep->setup);
1331 assert(rep->re_tx_desc);
1332 assert(rep->re_tx_head >= 0 && rep->re_tx_head < N_TX_DESC);
1334 assert(desc);
1336 if (rep->re_tx[tx_head].ret_busy) {
1337 assert(!(rep->re_flags & REF_SEND_AVAIL));
1338 rep->re_flags |= REF_SEND_AVAIL;
1339 if (rep->re_tx[tx_head].ret_busy)
1340 goto suspend;
1343 * Race condition, the interrupt handler may clear re_busy
1344 * before we got a chance to set REF_SEND_AVAIL. Checking
1345 * ret_busy twice should be sufficient.
1347 #if VERBOSE
1348 printf("rl_writev_s: race detected\n");
1349 #endif
1350 rep->re_flags &= ~REF_SEND_AVAIL;
1351 rep->re_send_int = FALSE;
1354 assert(!(rep->re_flags & REF_SEND_AVAIL));
1355 assert(!(rep->re_flags & REF_PACK_SENT));
1357 size = 0;
1358 ret = rep->re_tx[tx_head].v_ret_buf;
1359 for (i = 0; i < count; i += IOVEC_NR,
1360 iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
1362 n = IOVEC_NR;
1363 if (i + n > count)
1364 n = count - i;
1365 cps = sys_safecopyfrom(mp->m_source, mp->DL_GRANT, iov_offset,
1366 (vir_bytes) rep->re_iovec_s,
1367 n * sizeof(rep->re_iovec_s[0]));
1368 if (cps != OK) {
1369 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps);
1372 for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
1373 s = iovp->iov_size;
1374 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
1375 panic("invalid packet size");
1377 cps = sys_safecopyfrom(mp->m_source, iovp->iov_grant,
1378 0, (vir_bytes) ret, s);
1379 if (cps != OK) {
1380 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps);
1382 size += s;
1383 ret += s;
1386 assert(desc);
1387 if (size < ETH_MIN_PACK_SIZE)
1388 panic("invalid packet size: %d", size);
1390 rep->re_tx[tx_head].ret_busy = TRUE;
1392 if (tx_head == N_TX_DESC - 1) {
1393 desc->status = DESC_EOR | DESC_OWN | DESC_FS | DESC_LS | size;
1394 tx_head = 0;
1395 } else {
1396 desc->status = DESC_OWN | DESC_FS | DESC_LS | size;
1397 tx_head++;
1400 assert(tx_head < N_TX_DESC);
1401 rep->re_tx_head = tx_head;
1403 rl_outl(rep->re_base_port, RL_TPPOLL, RL_TPPOLL_NPQ);
1404 rep->re_flags |= REF_PACK_SENT;
1407 * If the interrupt handler called, don't send a reply. The reply
1408 * will be sent after all interrupts are handled.
1410 if (from_int)
1411 return;
1412 reply(rep);
1413 return;
1415 suspend:
1416 if (from_int)
1417 panic("should not be sending");
1419 rep->re_tx_mess = *mp;
1420 reply(rep);
1423 /*===========================================================================*
1424 * rl_check_ints *
1425 *===========================================================================*/
1426 static void rl_check_ints(rep)
1427 re_t *rep;
1429 int re_flags;
1431 re_flags = rep->re_flags;
1433 if ((re_flags & REF_READING) &&
1434 !(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE))
1436 assert(rep->re_rx_mess.m_type == DL_READV_S);
1437 rl_readv_s(&rep->re_rx_mess, TRUE /* from int */);
1440 if (rep->re_need_reset)
1441 rl_do_reset(rep);
1443 if (rep->re_send_int) {
1444 assert(rep->re_tx_mess.m_type == DL_WRITEV_S);
1445 rl_writev_s(&rep->re_tx_mess, TRUE /* from int */);
1448 if (rep->re_report_link) {
1449 rep->re_report_link = FALSE;
1451 rl_report_link(rep);
1454 if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV))
1455 reply(rep);
1458 /*===========================================================================*
1459 * rl_report_link *
1460 *===========================================================================*/
1461 static void rl_report_link(rep)
1462 re_t *rep;
1464 #if VERBOSE
1465 port_t port;
1466 u8_t mii_status;
1468 port = rep->re_base_port;
1470 mii_status = rl_inb(port, RL_PHYSTAT);
1472 if (mii_status & RL_STAT_LINK) {
1473 rep->re_link_up = 1;
1474 printf("%s: link up at ", rep->re_name);
1475 } else {
1476 rep->re_link_up = 0;
1477 printf("%s: link down\n", rep->re_name);
1478 return;
1481 if (mii_status & RL_STAT_1000)
1482 printf("1000 Mbps");
1483 else if (mii_status & RL_STAT_100)
1484 printf("100 Mbps");
1485 else if (mii_status & RL_STAT_10)
1486 printf("10 Mbps");
1488 if (mii_status & RL_STAT_FULLDUP)
1489 printf(", full duplex");
1490 else
1491 printf(", half duplex");
1492 printf("\n");
1493 #endif
1495 dump_phy(rep);
1498 /*===========================================================================*
1499 * rl_do_reset *
1500 *===========================================================================*/
1501 static void rl_do_reset(rep)
1502 re_t *rep;
1504 rep->re_need_reset = FALSE;
1505 rl_reset_hw(rep);
1506 rl_rec_mode(rep);
1508 rep->re_tx_head = 0;
1509 if (rep->re_flags & REF_SEND_AVAIL) {
1510 rep->re_tx[rep->re_tx_head].ret_busy = FALSE;
1511 rep->re_send_int = TRUE;
1515 /*===========================================================================*
1516 * rl_getstat_s *
1517 *===========================================================================*/
1518 static void rl_getstat_s(mp)
1519 message *mp;
1521 int r;
1522 eth_stat_t stats;
1523 re_t *rep;
1525 rep = &re_state;
1527 assert(rep->re_mode == REM_ENABLED);
1528 assert(rep->re_flags & REF_ENABLED);
1530 stats = rep->re_stat;
1532 r = sys_safecopyto(mp->m_source, mp->DL_GRANT, 0,
1533 (vir_bytes) &stats, sizeof(stats));
1534 if (r != OK)
1535 panic("rl_getstat_s: sys_safecopyto failed: %d", r);
1537 mp->m_type = DL_STAT_REPLY;
1538 r = send(mp->m_source, mp);
1539 if (r != OK)
1540 panic("rl_getstat_s: send failed: %d", r);
1543 /*===========================================================================*
1544 * reply *
1545 *===========================================================================*/
1546 static void reply(rep)
1547 re_t *rep;
1549 message reply;
1550 int flags;
1551 int r;
1553 flags = DL_NOFLAGS;
1554 if (rep->re_flags & REF_PACK_SENT)
1555 flags |= DL_PACK_SEND;
1556 if (rep->re_flags & REF_PACK_RECV)
1557 flags |= DL_PACK_RECV;
1559 reply.m_type = DL_TASK_REPLY;
1560 reply.DL_FLAGS = flags;
1561 reply.DL_COUNT = rep->re_read_s;
1563 r = send(rep->re_client, &reply);
1565 if (r < 0) {
1566 printf("RTL8169 tried sending to %d, type %d\n",
1567 rep->re_client, reply.m_type);
1568 panic("send failed: %d", r);
1571 rep->re_read_s = 0;
1572 rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
1575 /*===========================================================================*
1576 * mess_reply *
1577 *===========================================================================*/
1578 static void mess_reply(req, reply_mess)
1579 message *req;
1580 message *reply_mess;
1582 if (send(req->m_source, reply_mess) != OK)
1583 panic("unable to mess_reply");
1586 static void dump_phy(const re_t *rep)
1588 #if VERBOSE
1589 port_t port;
1590 u32_t t;
1592 port = rep->re_base_port;
1594 t = rl_inb(port, RL_CONFIG0);
1595 printf("CONFIG0\t\t:");
1596 t = t & RL_CFG0_ROM;
1597 if (t == RL_CFG0_ROM128K)
1598 printf(" 128K Boot ROM");
1599 else if (t == RL_CFG0_ROM64K)
1600 printf(" 64K Boot ROM");
1601 else if (t == RL_CFG0_ROM32K)
1602 printf(" 32K Boot ROM");
1603 else if (t == RL_CFG0_ROM16K)
1604 printf(" 16K Boot ROM");
1605 else if (t == RL_CFG0_ROM8K)
1606 printf(" 8K Boot ROM");
1607 else if (t == RL_CFG0_ROMNO)
1608 printf(" No Boot ROM");
1609 printf("\n");
1611 t = rl_inb(port, RL_CONFIG1);
1612 printf("CONFIG1\t\t:");
1613 if (t & RL_CFG1_LEDS1)
1614 printf(" LED1");
1615 if (t & RL_CFG1_LEDS0)
1616 printf(" LED0");
1617 if (t & RL_CFG1_DVRLOAD)
1618 printf(" Driver");
1619 if (t & RL_CFG1_LWACT)
1620 printf(" LWAKE");
1621 if (t & RL_CFG1_IOMAP)
1622 printf(" IOMAP");
1623 if (t & RL_CFG1_MEMMAP)
1624 printf(" MEMMAP");
1625 if (t & RL_CFG1_VPD)
1626 printf(" VPD");
1627 if (t & RL_CFG1_PME)
1628 printf(" PME");
1629 printf("\n");
1631 t = rl_inb(port, RL_CONFIG2);
1632 printf("CONFIG2\t\t:");
1633 if (t & RL_CFG2_AUX)
1634 printf(" AUX");
1635 if (t & RL_CFG2_PCIBW)
1636 printf(" PCI-64-Bit");
1637 else
1638 printf(" PCI-32-Bit");
1639 t = t & RL_CFG2_PCICLK;
1640 if (t == RL_CFG2_66MHZ)
1641 printf(" 66 MHz");
1642 else if (t == RL_CFG2_33MHZ)
1643 printf(" 33 MHz");
1644 printf("\n");
1646 t = mdio_read(port, MII_CTRL);
1647 printf("MII_CTRL\t:");
1648 if (t & MII_CTRL_RST)
1649 printf(" Reset");
1650 if (t & MII_CTRL_LB)
1651 printf(" Loopback");
1652 if (t & MII_CTRL_ANE)
1653 printf(" ANE");
1654 if (t & MII_CTRL_PD)
1655 printf(" Power-down");
1656 if (t & MII_CTRL_ISO)
1657 printf(" Isolate");
1658 if (t & MII_CTRL_RAN)
1659 printf(" RAN");
1660 if (t & MII_CTRL_DM)
1661 printf(" Full-duplex");
1662 if (t & MII_CTRL_CT)
1663 printf(" COL-signal");
1664 t = t & (MII_CTRL_SP_LSB | MII_CTRL_SP_MSB);
1665 if (t == MII_CTRL_SP_10)
1666 printf(" 10 Mb/s");
1667 else if (t == MII_CTRL_SP_100)
1668 printf(" 100 Mb/s");
1669 else if (t == MII_CTRL_SP_1000)
1670 printf(" 1000 Mb/s");
1671 printf("\n");
1673 t = mdio_read(port, MII_STATUS);
1674 printf("MII_STATUS\t:");
1675 if (t & MII_STATUS_100T4)
1676 printf(" 100Base-T4");
1677 if (t & MII_STATUS_100XFD)
1678 printf(" 100BaseX-FD");
1679 if (t & MII_STATUS_100XHD)
1680 printf(" 100BaseX-HD");
1681 if (t & MII_STATUS_10FD)
1682 printf(" 10Mbps-FD");
1683 if (t & MII_STATUS_10HD)
1684 printf(" 10Mbps-HD");
1685 if (t & MII_STATUS_100T2FD)
1686 printf(" 100Base-T2-FD");
1687 if (t & MII_STATUS_100T2HD)
1688 printf(" 100Base-T2-HD");
1689 if (t & MII_STATUS_EXT_STAT)
1690 printf(" Ext-stat");
1691 if (t & MII_STATUS_RES)
1692 printf(" res-0x%x", t & MII_STATUS_RES);
1693 if (t & MII_STATUS_MFPS)
1694 printf(" MFPS");
1695 if (t & MII_STATUS_ANC)
1696 printf(" ANC");
1697 if (t & MII_STATUS_RF)
1698 printf(" remote-fault");
1699 if (t & MII_STATUS_ANA)
1700 printf(" ANA");
1701 if (t & MII_STATUS_LS)
1702 printf(" Link");
1703 if (t & MII_STATUS_JD)
1704 printf(" Jabber");
1705 if (t & MII_STATUS_EC)
1706 printf(" Extended-capability");
1707 printf("\n");
1709 t = mdio_read(port, MII_ANA);
1710 printf("MII_ANA\t\t: 0x%04x\n", t);
1712 t = mdio_read(port, MII_ANLPA);
1713 printf("MII_ANLPA\t: 0x%04x\n", t);
1715 t = mdio_read(port, MII_ANE);
1716 printf("MII_ANE\t\t:");
1717 if (t & MII_ANE_RES)
1718 printf(" res-0x%x", t & MII_ANE_RES);
1719 if (t & MII_ANE_PDF)
1720 printf(" Par-Detect-Fault");
1721 if (t & MII_ANE_LPNPA)
1722 printf(" LP-Next-Page-Able");
1723 if (t & MII_ANE_NPA)
1724 printf(" Loc-Next-Page-Able");
1725 if (t & MII_ANE_PR)
1726 printf(" Page-Received");
1727 if (t & MII_ANE_LPANA)
1728 printf(" LP-Auto-Neg-Able");
1729 printf("\n");
1731 t = mdio_read(port, MII_1000_CTRL);
1732 printf("MII_1000_CTRL\t:");
1733 if (t & MII_1000C_FULL)
1734 printf(" 1000BaseT-FD");
1735 if (t & MII_1000C_HALF)
1736 printf(" 1000BaseT-HD");
1737 printf("\n");
1739 t = mdio_read(port, MII_1000_STATUS);
1740 if (t) {
1741 printf("MII_1000_STATUS\t:");
1742 if (t & MII_1000S_LRXOK)
1743 printf(" Local-Receiver");
1744 if (t & MII_1000S_RRXOK)
1745 printf(" Remote-Receiver");
1746 if (t & MII_1000S_HALF)
1747 printf(" 1000BaseT-HD");
1748 if (t & MII_1000S_FULL)
1749 printf(" 1000BaseT-FD");
1750 printf("\n");
1752 t = mdio_read(port, MII_EXT_STATUS);
1753 printf("MII_EXT_STATUS\t:");
1754 if (t & MII_ESTAT_1000XFD)
1755 printf(" 1000BaseX-FD");
1756 if (t & MII_ESTAT_1000XHD)
1757 printf(" 1000BaseX-HD");
1758 if (t & MII_ESTAT_1000TFD)
1759 printf(" 1000BaseT-FD");
1760 if (t & MII_ESTAT_1000THD)
1761 printf(" 1000BaseT-HD");
1762 printf("\n");
1764 #endif
1767 static void do_hard_int(void)
1769 int s;
1771 /* Run interrupt handler at driver level. */
1772 rl_handler(&re_state);
1774 /* Reenable interrupts for this hook. */
1775 if ((s = sys_irqenable(&re_state.re_hook_id)) != OK)
1776 printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
1779 /*===========================================================================*
1780 * rl_handler *
1781 *===========================================================================*/
1782 static void rl_handler(re_t *rep)
1784 int i, port, tx_head, tx_tail, link_up;
1785 u16_t isr;
1786 re_desc *desc;
1787 int_event_check = FALSE; /* disable check by default */
1789 port = rep->re_base_port;
1791 /* Ack interrupt */
1792 isr = rl_inw(port, RL_ISR);
1793 if(!isr)
1794 return;
1795 rl_outw(port, RL_ISR, isr);
1796 rep->interrupts++;
1798 if (isr & RL_IMR_FOVW) {
1799 isr &= ~RL_IMR_FOVW;
1800 /* Should do anything? */
1802 rep->re_stat.ets_fifoOver++;
1804 if (isr & RL_IMR_PUN) {
1805 isr &= ~RL_IMR_PUN;
1808 * Either the link status changed or there was a TX fifo
1809 * underrun.
1811 link_up = !(!(rl_inb(port, RL_PHYSTAT) & RL_STAT_LINK));
1812 if (link_up != rep->re_link_up) {
1813 rep->re_report_link = TRUE;
1814 rep->re_got_int = TRUE;
1815 int_event_check = TRUE;
1819 if (isr & (RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK)) {
1820 if (isr & RL_ISR_RER)
1821 rep->re_stat.ets_recvErr++;
1822 isr &= ~(RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK);
1824 if (!rep->re_got_int && (rep->re_flags & REF_READING)) {
1825 rep->re_got_int = TRUE;
1826 int_event_check = TRUE;
1830 if ((isr & (RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK)) || 1) {
1831 if (isr & RL_ISR_TER)
1832 rep->re_stat.ets_sendErr++;
1833 isr &= ~(RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK);
1835 /* Transmit completed */
1836 tx_head = rep->re_tx_head;
1837 tx_tail = tx_head+1;
1838 if (tx_tail >= N_TX_DESC)
1839 tx_tail = 0;
1840 for (i = 0; i < 2 * N_TX_DESC; i++) {
1841 if (!rep->re_tx[tx_tail].ret_busy) {
1842 /* Strange, this buffer is not in-use.
1843 * Increment tx_tail until tx_head is
1844 * reached (or until we find a buffer that
1845 * is in-use.
1847 if (tx_tail == tx_head)
1848 break;
1849 if (++tx_tail >= N_TX_DESC)
1850 tx_tail = 0;
1851 assert(tx_tail < N_TX_DESC);
1852 continue;
1854 desc = rep->re_tx_desc;
1855 desc += tx_tail;
1856 if (desc->status & DESC_OWN) {
1857 /* Buffer is not yet ready */
1858 break;
1861 rep->re_stat.ets_packetT++;
1862 rep->re_tx[tx_tail].ret_busy = FALSE;
1864 if (++tx_tail >= N_TX_DESC)
1865 tx_tail = 0;
1866 assert(tx_tail < N_TX_DESC);
1868 if (rep->re_flags & REF_SEND_AVAIL) {
1869 rep->re_send_int = TRUE;
1870 if (!rep->re_got_int) {
1871 rep->re_got_int = TRUE;
1872 int_event_check = TRUE;
1876 assert(i < 2 * N_TX_DESC);
1879 /* Ignore Reserved Interrupt */
1880 if (isr & RL_ISR_RES)
1881 isr &= ~RL_ISR_RES;
1883 if (isr)
1884 printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr);
1887 /*===========================================================================*
1888 * rl_watchdog_f *
1889 *===========================================================================*/
1890 static void rl_watchdog_f(tp)
1891 timer_t *tp;
1893 re_t *rep;
1894 /* Use a synchronous alarm instead of a watchdog timer. */
1895 sys_setalarm(system_hz, 0);
1897 rep = &re_state;
1899 if (rep->re_mode != REM_ENABLED)
1900 return;
1902 /* Should collect statistics */
1903 if (!(++rep->dtcc_counter % RE_DTCC_VALUE))
1904 rtl8169_update_stat(rep);
1906 if (!(rep->re_flags & REF_SEND_AVAIL)) {
1907 /* Assume that an idle system is alive */
1908 rep->re_tx_alive = TRUE;
1909 return;
1911 if (rep->re_tx_alive) {
1912 rep->re_tx_alive = FALSE;
1913 return;
1915 printf("rl_watchdog_f: resetting instance %d mode 0x%x flags 0x%x\n",
1916 re_instance, rep->re_mode, rep->re_flags);
1917 printf("tx_head :%8d busy %d\t",
1918 rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
1919 rep->re_need_reset = TRUE;
1920 rep->re_got_int = TRUE;
1922 check_int_events();