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