custom message type for VM_INFO
[minix3.git] / drivers / rtl8169 / rtl8169.c
blob420736e30443e6dbc17cb69b10d08a3e4c0861f1
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 <minix/timers.h>
22 #include <net/hton.h>
23 #include <net/gen/ether.h>
24 #include <net/gen/eth_io.h>
25 #include <machine/pci.h>
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(minix_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.m_netdrv_net_dl_conf.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->m_net_netdrv_dl_conf.mode & DL_PROMISC_REQ)
574 rep->re_flags |= REF_PROMISC;
575 if (mp->m_net_netdrv_dl_conf.mode & DL_MULTI_REQ)
576 rep->re_flags |= REF_MULTI;
577 if (mp->m_net_netdrv_dl_conf.mode & DL_BROAD_REQ)
578 rep->re_flags |= REF_BROAD;
580 rl_rec_mode(rep);
582 reply_mess.m_type = DL_CONF_REPLY;
583 reply_mess.m_netdrv_net_dl_conf.stat = OK;
584 memcpy(reply_mess.m_netdrv_net_dl_conf.hw_addr,
585 rep->re_address.ea_addr,
586 sizeof(reply_mess.m_netdrv_net_dl_conf.hw_addr));
588 mess_reply(mp, &reply_mess);
591 /*===========================================================================*
592 * rl_pci_conf *
593 *===========================================================================*/
594 static void rl_pci_conf()
596 re_t *rep;
598 rep = &re_state;
600 strlcpy(rep->re_name, "rtl8169#0", sizeof(rep->re_name));
601 rep->re_name[8] += re_instance;
602 rep->re_seen = FALSE;
604 pci_init();
606 if (rl_probe(rep, re_instance))
607 rep->re_seen = TRUE;
610 /*===========================================================================*
611 * rl_probe *
612 *===========================================================================*/
613 static int rl_probe(rep, skip)
614 re_t *rep;
615 int skip;
617 int r, devind;
618 u16_t vid, did;
619 u32_t bar;
620 u8_t ilr;
621 #if VERBOSE
622 char *dname;
623 #endif
625 r = pci_first_dev(&devind, &vid, &did);
626 if (r == 0)
627 return 0;
629 while (skip--) {
630 r = pci_next_dev(&devind, &vid, &did);
631 if (!r)
632 return 0;
635 #if VERBOSE
636 dname = pci_dev_name(vid, did);
637 if (!dname)
638 dname = "unknown device";
639 printf("%s: ", rep->re_name);
640 printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
641 #endif
643 pci_reserve(devind);
644 bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
645 if (bar < 0x400) {
646 panic("base address is not properly configured");
648 rep->re_base_port = bar;
650 ilr = pci_attr_r8(devind, PCI_ILR);
651 rep->re_irq = ilr;
652 #if VERBOSE
653 printf("%s: using I/O address 0x%lx, IRQ %d\n",
654 rep->re_name, (unsigned long)bar, ilr);
655 #endif
657 return TRUE;
660 /*===========================================================================*
661 * rl_conf_hw *
662 *===========================================================================*/
663 static void rl_conf_hw(rep)
664 re_t *rep;
666 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
668 rep->re_mode = REM_DISABLED; /* Superfluous */
670 if (rep->re_seen)
671 rep->re_mode = REM_ENABLED; /* PCI device is present */
672 if (rep->re_mode != REM_ENABLED)
673 return;
675 rep->re_flags = REF_EMPTY;
676 rep->re_link_up = 0;
677 rep->re_got_int = 0;
678 rep->re_send_int = 0;
679 rep->re_report_link = 0;
680 rep->re_need_reset = 0;
681 rep->re_tx_alive = 0;
682 rep->re_rx_head = 0;
683 rep->re_read_s = 0;
684 rep->re_tx_head = 0;
685 rep->re_stat = empty_stat;
686 rep->dtcc_counter = 0;
689 /*===========================================================================*
690 * rl_init_buf *
691 *===========================================================================*/
692 static void rl_init_buf(rep)
693 re_t *rep;
695 size_t rx_bufsize, tx_bufsize, rx_descsize, tx_descsize, tot_bufsize;
696 struct re_desc *desc;
697 phys_bytes buf;
698 char *mallocbuf;
699 int d;
701 assert(!rep->setup);
703 /* Allocate receive and transmit descriptors */
704 rx_descsize = (N_RX_DESC * sizeof(struct re_desc));
705 tx_descsize = (N_TX_DESC * sizeof(struct re_desc));
707 /* Allocate receive and transmit buffers */
708 tx_bufsize = ETH_MAX_PACK_SIZE_TAGGED;
709 if (tx_bufsize % 4)
710 tx_bufsize += 4-(tx_bufsize % 4); /* Align */
711 rx_bufsize = RX_BUFSIZE;
712 tot_bufsize = rx_descsize + tx_descsize;
713 tot_bufsize += (N_TX_DESC * tx_bufsize) + (N_RX_DESC * rx_bufsize);
714 tot_bufsize += sizeof(struct re_dtcc);
716 if (tot_bufsize % 4096)
717 tot_bufsize += 4096 - (tot_bufsize % 4096);
719 if (!(mallocbuf = alloc_contig(tot_bufsize, AC_ALIGN64K, &buf)))
720 panic("Couldn't allocate kernel buffer");
722 /* Rx Descriptor */
723 rep->re_rx_desc = (re_desc *)mallocbuf;
724 rep->p_rx_desc = buf;
725 memset(mallocbuf, 0x00, rx_descsize);
726 buf += rx_descsize;
727 mallocbuf += rx_descsize;
729 /* Tx Descriptor */
730 rep->re_tx_desc = (re_desc *)mallocbuf;
731 rep->p_tx_desc = buf;
732 memset(mallocbuf, 0x00, tx_descsize);
733 buf += tx_descsize;
734 mallocbuf += tx_descsize;
736 desc = rep->re_rx_desc;
737 for (d = 0; d < N_RX_DESC; d++) {
738 /* Setting Rx buffer */
739 rep->re_rx[d].ret_buf = buf;
740 rep->re_rx[d].v_ret_buf = mallocbuf;
741 buf += rx_bufsize;
742 mallocbuf += rx_bufsize;
744 /* Setting Rx descriptor */
745 if (d == (N_RX_DESC - 1)) /* Last descriptor? if so, set the EOR bit */
746 desc->status = DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
747 else
748 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
750 desc->addr_low = rep->re_rx[d].ret_buf;
751 desc++;
753 desc = rep->re_tx_desc;
754 for (d = 0; d < N_TX_DESC; d++) {
755 rep->re_tx[d].ret_busy = FALSE;
756 rep->re_tx[d].ret_buf = buf;
757 rep->re_tx[d].v_ret_buf = mallocbuf;
758 buf += tx_bufsize;
759 mallocbuf += tx_bufsize;
761 /* Setting Tx descriptor */
762 desc->addr_low = rep->re_tx[d].ret_buf;
763 desc++;
766 /* Dump Tally Counter buffer */
767 rep->dtcc_buf = buf;
768 rep->v_dtcc_buf = (re_dtcc *)mallocbuf;
770 rep->setup = 1;
773 /*===========================================================================*
774 * rl_init_hw *
775 *===========================================================================*/
776 static void rl_init_hw(rep)
777 re_t *rep;
779 int s;
780 #if VERBOSE
781 int i;
782 #endif
784 rep->re_flags = REF_EMPTY;
785 rep->re_flags |= REF_ENABLED;
788 * Set the interrupt handler. The policy is to only send HARD_INT
789 * notifications. Don't reenable interrupts automatically. The id
790 * that is passed back is the interrupt line number.
792 rep->re_hook_id = rep->re_irq;
793 if ((s = sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
794 printf("RTL8169: error, couldn't set IRQ policy: %d\n", s);
796 rl_reset_hw(rep);
798 if ((s = sys_irqenable(&rep->re_hook_id)) != OK)
799 printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
801 #if VERBOSE
802 printf("%s: model: %s mac: 0x%08x\n",
803 rep->re_name, rep->re_model, rep->re_mac);
804 #endif
806 rl_confaddr(rep);
807 #if VERBOSE
808 printf("%s: Ethernet address ", rep->re_name);
809 for (i = 0; i < 6; i++) {
810 printf("%x%c", rep->re_address.ea_addr[i],
811 i < 5 ? ':' : '\n');
813 #endif
816 static void rtl8169s_phy_config(port_t port)
818 mdio_write(port, 0x1f, 0x0001);
819 mdio_write(port, 0x06, 0x006e);
820 mdio_write(port, 0x08, 0x0708);
821 mdio_write(port, 0x15, 0x4000);
822 mdio_write(port, 0x18, 0x65c7);
824 mdio_write(port, 0x1f, 0x0001);
825 mdio_write(port, 0x03, 0x00a1);
826 mdio_write(port, 0x02, 0x0008);
827 mdio_write(port, 0x01, 0x0120);
828 mdio_write(port, 0x00, 0x1000);
829 mdio_write(port, 0x04, 0x0800);
830 mdio_write(port, 0x04, 0x0000);
832 mdio_write(port, 0x03, 0xff41);
833 mdio_write(port, 0x02, 0xdf60);
834 mdio_write(port, 0x01, 0x0140);
835 mdio_write(port, 0x00, 0x0077);
836 mdio_write(port, 0x04, 0x7800);
837 mdio_write(port, 0x04, 0x7000);
839 mdio_write(port, 0x03, 0x802f);
840 mdio_write(port, 0x02, 0x4f02);
841 mdio_write(port, 0x01, 0x0409);
842 mdio_write(port, 0x00, 0xf0f9);
843 mdio_write(port, 0x04, 0x9800);
844 mdio_write(port, 0x04, 0x9000);
846 mdio_write(port, 0x03, 0xdf01);
847 mdio_write(port, 0x02, 0xdf20);
848 mdio_write(port, 0x01, 0xff95);
849 mdio_write(port, 0x00, 0xba00);
850 mdio_write(port, 0x04, 0xa800);
851 mdio_write(port, 0x04, 0xa000);
853 mdio_write(port, 0x03, 0xff41);
854 mdio_write(port, 0x02, 0xdf20);
855 mdio_write(port, 0x01, 0x0140);
856 mdio_write(port, 0x00, 0x00bb);
857 mdio_write(port, 0x04, 0xb800);
858 mdio_write(port, 0x04, 0xb000);
860 mdio_write(port, 0x03, 0xdf41);
861 mdio_write(port, 0x02, 0xdc60);
862 mdio_write(port, 0x01, 0x6340);
863 mdio_write(port, 0x00, 0x007d);
864 mdio_write(port, 0x04, 0xd800);
865 mdio_write(port, 0x04, 0xd000);
867 mdio_write(port, 0x03, 0xdf01);
868 mdio_write(port, 0x02, 0xdf20);
869 mdio_write(port, 0x01, 0x100a);
870 mdio_write(port, 0x00, 0xa0ff);
871 mdio_write(port, 0x04, 0xf800);
872 mdio_write(port, 0x04, 0xf000);
874 mdio_write(port, 0x1f, 0x0000);
875 mdio_write(port, 0x0b, 0x0000);
876 mdio_write(port, 0x00, 0x9200);
879 static void rtl8169scd_phy_config(port_t port)
881 mdio_write(port, 0x1f, 0x0001);
882 mdio_write(port, 0x04, 0x0000);
883 mdio_write(port, 0x03, 0x00a1);
884 mdio_write(port, 0x02, 0x0008);
885 mdio_write(port, 0x01, 0x0120);
886 mdio_write(port, 0x00, 0x1000);
887 mdio_write(port, 0x04, 0x0800);
888 mdio_write(port, 0x04, 0x9000);
889 mdio_write(port, 0x03, 0x802f);
890 mdio_write(port, 0x02, 0x4f02);
891 mdio_write(port, 0x01, 0x0409);
892 mdio_write(port, 0x00, 0xf099);
893 mdio_write(port, 0x04, 0x9800);
894 mdio_write(port, 0x04, 0xa000);
895 mdio_write(port, 0x03, 0xdf01);
896 mdio_write(port, 0x02, 0xdf20);
897 mdio_write(port, 0x01, 0xff95);
898 mdio_write(port, 0x00, 0xba00);
899 mdio_write(port, 0x04, 0xa800);
900 mdio_write(port, 0x04, 0xf000);
901 mdio_write(port, 0x03, 0xdf01);
902 mdio_write(port, 0x02, 0xdf20);
903 mdio_write(port, 0x01, 0x101a);
904 mdio_write(port, 0x00, 0xa0ff);
905 mdio_write(port, 0x04, 0xf800);
906 mdio_write(port, 0x04, 0x0000);
907 mdio_write(port, 0x1f, 0x0000);
909 mdio_write(port, 0x1f, 0x0001);
910 mdio_write(port, 0x10, 0xf41b);
911 mdio_write(port, 0x14, 0xfb54);
912 mdio_write(port, 0x18, 0xf5c7);
913 mdio_write(port, 0x1f, 0x0000);
915 mdio_write(port, 0x1f, 0x0001);
916 mdio_write(port, 0x17, 0x0cc0);
917 mdio_write(port, 0x1f, 0x0000);
920 /*===========================================================================*
921 * rl_reset_hw *
922 *===========================================================================*/
923 static void rl_reset_hw(rep)
924 re_t *rep;
926 port_t port;
927 u32_t t;
928 int i;
930 port = rep->re_base_port;
932 rl_outw(port, RL_IMR, 0x0000);
934 /* Reset the device */
935 rl_outb(port, RL_CR, RL_CR_RST);
936 SPIN_UNTIL(!(rl_inb(port, RL_CR) & RL_CR_RST), 1000000);
937 if (rl_inb(port, RL_CR) & RL_CR_RST)
938 printf("rtl8169: reset failed to complete");
939 rl_outw(port, RL_ISR, 0xFFFF);
941 /* Get Model and MAC info */
942 t = rl_inl(port, RL_TCR);
943 rep->re_mac = (t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
944 switch (rep->re_mac) {
945 case RL_TCR_HWVER_RTL8169:
946 rep->re_model = "RTL8169";
948 rl_outw(port, RL_CCR_UNDOC, 0x01);
949 break;
950 case RL_TCR_HWVER_RTL8169S:
951 rep->re_model = "RTL8169S";
953 rtl8169s_phy_config(port);
955 rl_outw(port, RL_CCR_UNDOC, 0x01);
956 mdio_write(port, 0x0b, 0x0000); /* w 0x0b 15 0 0 */
957 break;
958 case RL_TCR_HWVER_RTL8110S:
959 rep->re_model = "RTL8110S";
961 rtl8169s_phy_config(port);
963 rl_outw(port, RL_CCR_UNDOC, 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 rl_outw(port, RL_CCR_UNDOC, 0x01);
973 break;
974 case RL_TCR_HWVER_RTL8110SCd:
975 rep->re_model = "RTL8110SCd";
977 rtl8169scd_phy_config(port);
979 rl_outw(port, RL_CCR_UNDOC, 0x01);
980 break;
981 case RL_TCR_HWVER_RTL8105E:
982 rep->re_model = "RTL8105E";
983 break;
984 default:
985 rep->re_model = "Unknown";
986 rep->re_mac = t;
987 break;
990 mdio_write(port, MII_CTRL, MII_CTRL_RST);
991 for (i = 0; i < 1000; i++) {
992 t = mdio_read(port, MII_CTRL);
993 if (!(t & MII_CTRL_RST))
994 break;
995 else
996 micro_delay(100);
999 t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_DM | MII_CTRL_SP_1000;
1000 mdio_write(port, MII_CTRL, t);
1002 t = mdio_read(port, MII_ANA);
1003 t |= MII_ANA_10THD | MII_ANA_10TFD | MII_ANA_100TXHD | MII_ANA_100TXFD;
1004 t |= MII_ANA_PAUSE_SYM | MII_ANA_PAUSE_ASYM;
1005 mdio_write(port, MII_ANA, t);
1007 t = mdio_read(port, MII_1000_CTRL) | 0x300;
1008 mdio_write(port, MII_1000_CTRL, t);
1010 /* Restart Auto-Negotiation Process */
1011 t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_RAN;
1012 mdio_write(port, MII_CTRL, t);
1014 rl_outw(port, RL_9346CR, RL_9346CR_EEM_CONFIG); /* Unlock */
1016 switch (rep->re_mac) {
1017 case RL_TCR_HWVER_RTL8169S:
1018 case RL_TCR_HWVER_RTL8110S:
1019 /* Bit-3 and bit-14 of the C+CR register MUST be 1. */
1020 t = rl_inw(port, RL_CPLUSCMD);
1021 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW | (1 << 14));
1022 break;
1023 case RL_TCR_HWVER_RTL8169:
1024 case RL_TCR_HWVER_RTL8169SB:
1025 case RL_TCR_HWVER_RTL8110SCd:
1026 t = rl_inw(port, RL_CPLUSCMD);
1027 rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW);
1028 break;
1031 rl_outw(port, RL_INTRMITIGATE, 0x00);
1033 t = rl_inb(port, RL_CR);
1034 rl_outb(port, RL_CR, t | RL_CR_RE | RL_CR_TE);
1036 /* Initialize Rx */
1037 rl_outw(port, RL_RMS, RX_BUFSIZE); /* Maximum rx packet size */
1038 t = rl_inl(port, RL_RCR) & RX_CONFIG_MASK;
1039 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | t);
1040 rl_outl(port, RL_RDSAR_LO, rep->p_rx_desc);
1041 rl_outl(port, RL_RDSAR_HI, 0x00); /* For 64 bit */
1043 /* Initialize Tx */
1044 rl_outw(port, RL_ETTHR, 0x3f); /* No early transmit */
1045 rl_outl(port, RL_TCR, RL_TCR_MXDMA_2048 | RL_TCR_IFG_STD);
1046 rl_outl(port, RL_TNPDS_LO, rep->p_tx_desc);
1047 rl_outl(port, RL_TNPDS_HI, 0x00); /* For 64 bit */
1049 rl_outw(port, RL_9346CR, RL_9346CR_EEM_NORMAL); /* Lock */
1051 rl_outw(port, RL_MPC, 0x00);
1052 rl_outw(port, RL_MULINT, rl_inw(port, RL_MULINT) & 0xF000);
1053 rl_outw(port, RL_IMR, RE_INTR_MASK);
1056 /*===========================================================================*
1057 * rl_confaddr *
1058 *===========================================================================*/
1059 static void rl_confaddr(rep)
1060 re_t *rep;
1062 static char eakey[] = RL_ENVVAR "#_EA";
1063 static char eafmt[] = "x:x:x:x:x:x";
1065 int i;
1066 port_t port;
1067 u32_t w;
1068 long v;
1070 /* User defined ethernet address? */
1071 eakey[sizeof(RL_ENVVAR)-1] = '0' + re_instance;
1073 port = rep->re_base_port;
1075 for (i = 0; i < 6; i++) {
1076 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
1077 break;
1078 rep->re_address.ea_addr[i] = v;
1081 if (i != 0 && i != 6)
1082 env_panic(eakey); /* It's all or nothing */
1084 /* Should update ethernet address in hardware */
1085 if (i == 6) {
1086 port = rep->re_base_port;
1087 rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
1088 w = 0;
1089 for (i = 0; i < 4; i++)
1090 w |= (rep->re_address.ea_addr[i] << (i * 8));
1091 rl_outl(port, RL_IDR, w);
1092 w = 0;
1093 for (i = 4; i < 6; i++)
1094 w |= (rep->re_address.ea_addr[i] << ((i-4) * 8));
1095 rl_outl(port, RL_IDR + 4, w);
1096 rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
1099 /* Get ethernet address */
1100 for (i = 0; i < 6; i++)
1101 rep->re_address.ea_addr[i] = rl_inb(port, RL_IDR+i);
1104 /*===========================================================================*
1105 * rl_rec_mode *
1106 *===========================================================================*/
1107 static void rl_rec_mode(rep)
1108 re_t *rep;
1110 port_t port;
1111 u32_t rcr;
1112 u32_t mc_filter[2]; /* Multicast hash filter */
1114 port = rep->re_base_port;
1116 mc_filter[1] = mc_filter[0] = 0xffffffff;
1117 rl_outl(port, RL_MAR + 0, mc_filter[0]);
1118 rl_outl(port, RL_MAR + 4, mc_filter[1]);
1120 rcr = rl_inl(port, RL_RCR);
1121 rcr &= ~(RL_RCR_AB | RL_RCR_AM | RL_RCR_APM | RL_RCR_AAP);
1122 if (rep->re_flags & REF_PROMISC)
1123 rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
1124 if (rep->re_flags & REF_BROAD)
1125 rcr |= RL_RCR_AB;
1126 if (rep->re_flags & REF_MULTI)
1127 rcr |= RL_RCR_AM;
1128 rcr |= RL_RCR_APM;
1129 rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | rcr);
1132 void transmittest(re_t *rep)
1134 int tx_head;
1135 int ipc_status;
1137 tx_head = rep->re_tx_head;
1139 if(rep->re_tx[tx_head].ret_busy) {
1140 do {
1141 message m;
1142 int r;
1143 if ((r = netdriver_receive(ANY, &m, &ipc_status)) != OK)
1144 panic("netdriver_receive failed: %d", r);
1145 } while(m.m_source != HARDWARE);
1146 assert(!(rep->re_flags & REF_SEND_AVAIL));
1147 rep->re_flags |= REF_SEND_AVAIL;
1150 return;
1153 /*===========================================================================*
1154 * rl_readv_s *
1155 *===========================================================================*/
1156 static void rl_readv_s(const message *mp, int from_int)
1158 int i, j, n, s, count, size, index;
1159 port_t port;
1160 unsigned totlen, packlen;
1161 re_desc *desc;
1162 u32_t rxstat = 0x12345678;
1163 re_t *rep;
1164 iovec_s_t *iovp;
1165 int cps;
1166 int iov_offset = 0;
1168 rep = &re_state;
1170 rep->re_client = mp->m_source;
1171 count = mp->m_net_netdrv_dl_readv_s.count;
1173 assert(rep->re_mode == REM_ENABLED);
1174 assert(rep->re_flags & REF_ENABLED);
1176 port = rep->re_base_port;
1179 * Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1181 if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
1182 goto suspend; /* Receive buffer is empty, suspend */
1184 index = rep->re_rx_head;
1185 desc = rep->re_rx_desc;
1186 desc += index;
1187 readvs_loop:
1188 rxstat = desc->status;
1190 if (rxstat & DESC_OWN)
1191 goto suspend;
1193 if (rxstat & DESC_RX_CRC)
1194 rep->re_stat.ets_CRCerr++;
1196 if ((rxstat & (DESC_FS | DESC_LS)) != (DESC_FS | DESC_LS)) {
1197 #if VERBOSE
1198 printf("rl_readv_s: packet is fragmented\n");
1199 #endif
1200 /* Fix the fragmented packet */
1201 if (index == N_RX_DESC - 1) {
1202 desc->status = DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1203 index = 0;
1204 desc = rep->re_rx_desc;
1205 } else {
1206 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1207 index++;
1208 desc++;
1210 goto readvs_loop; /* Loop until we get correct packet */
1213 totlen = rxstat & DESC_RX_LENMASK;
1214 if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
1215 /* Someting went wrong */
1216 printf("rl_readv_s: bad length (%u) in status 0x%08x\n",
1217 totlen, rxstat);
1218 panic(NULL);
1221 /* Should subtract the CRC */
1222 packlen = totlen - ETH_CRC_SIZE;
1224 size = 0;
1225 for (i = 0; i < count; i += IOVEC_NR,
1226 iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
1228 n = IOVEC_NR;
1229 if (i + n > count)
1230 n = count-i;
1231 cps = sys_safecopyfrom(mp->m_source,
1232 mp->m_net_netdrv_dl_readv_s.grant, iov_offset,
1233 (vir_bytes) rep->re_iovec_s,
1234 n * sizeof(rep->re_iovec_s[0]));
1235 if (cps != OK) {
1236 panic("rl_readv_s: sys_safecopyfrom failed: %d", cps);
1239 for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
1240 s = iovp->iov_size;
1241 if (size + s > packlen) {
1242 assert(packlen > size);
1243 s = packlen-size;
1246 cps = sys_safecopyto(mp->m_source, iovp->iov_grant, 0,
1247 (vir_bytes) rep->re_rx[index].v_ret_buf + size, s);
1248 if (cps != OK)
1249 panic("rl_readv_s: sys_safecopyto failed: %d", cps);
1251 size += s;
1252 if (size == packlen)
1253 break;
1255 if (size == packlen)
1256 break;
1258 if (size < packlen)
1259 assert(0);
1261 rep->re_stat.ets_packetR++;
1262 rep->re_read_s = packlen;
1263 if (index == N_RX_DESC - 1) {
1264 desc->status = DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1265 index = 0;
1266 } else {
1267 desc->status = DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
1268 index++;
1270 rep->re_rx_head = index;
1271 assert(rep->re_rx_head < N_RX_DESC);
1272 rep->re_flags = (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
1274 if (!from_int)
1275 reply(rep);
1277 return;
1279 suspend:
1280 if (from_int) {
1281 assert(rep->re_flags & REF_READING);
1283 /* No need to store any state */
1284 return;
1287 rep->re_rx_mess = *mp;
1288 assert(!(rep->re_flags & REF_READING));
1289 rep->re_flags |= REF_READING;
1291 reply(rep);
1294 /*===========================================================================*
1295 * rl_writev_s *
1296 *===========================================================================*/
1297 static void rl_writev_s(const message *mp, int from_int)
1299 int i, j, n, s, count, size;
1300 int tx_head;
1301 re_t *rep;
1302 iovec_s_t *iovp;
1303 re_desc *desc;
1304 char *ret;
1305 int cps;
1306 int iov_offset = 0;
1308 rep = &re_state;
1310 rep->re_client = mp->m_source;
1311 count = mp->m_net_netdrv_dl_writev_s.count;
1312 assert(rep->setup);
1314 assert(rep->re_mode == REM_ENABLED);
1315 assert(rep->re_flags & REF_ENABLED);
1317 if (from_int) {
1318 assert(rep->re_flags & REF_SEND_AVAIL);
1319 rep->re_flags &= ~REF_SEND_AVAIL;
1320 rep->re_send_int = FALSE;
1321 rep->re_tx_alive = TRUE;
1324 tx_head = rep->re_tx_head;
1326 desc = rep->re_tx_desc;
1327 desc += tx_head;
1329 if(!desc || !rep->re_tx_desc) {
1330 printf("desc %p, re_tx_desc %p, tx_head %d, setup %d\n",
1331 desc, rep->re_tx_desc, tx_head, rep->setup);
1334 assert(rep->re_tx_desc);
1335 assert(rep->re_tx_head >= 0 && rep->re_tx_head < N_TX_DESC);
1337 assert(desc);
1339 if (rep->re_tx[tx_head].ret_busy) {
1340 assert(!(rep->re_flags & REF_SEND_AVAIL));
1341 rep->re_flags |= REF_SEND_AVAIL;
1342 if (rep->re_tx[tx_head].ret_busy)
1343 goto suspend;
1346 * Race condition, the interrupt handler may clear re_busy
1347 * before we got a chance to set REF_SEND_AVAIL. Checking
1348 * ret_busy twice should be sufficient.
1350 #if VERBOSE
1351 printf("rl_writev_s: race detected\n");
1352 #endif
1353 rep->re_flags &= ~REF_SEND_AVAIL;
1354 rep->re_send_int = FALSE;
1357 assert(!(rep->re_flags & REF_SEND_AVAIL));
1358 assert(!(rep->re_flags & REF_PACK_SENT));
1360 size = 0;
1361 ret = rep->re_tx[tx_head].v_ret_buf;
1362 for (i = 0; i < count; i += IOVEC_NR,
1363 iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
1365 n = IOVEC_NR;
1366 if (i + n > count)
1367 n = count - i;
1368 cps = sys_safecopyfrom(mp->m_source,
1369 mp->m_net_netdrv_dl_writev_s.grant, iov_offset,
1370 (vir_bytes) rep->re_iovec_s,
1371 n * sizeof(rep->re_iovec_s[0]));
1372 if (cps != OK) {
1373 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps);
1376 for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
1377 s = iovp->iov_size;
1378 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
1379 panic("invalid packet size");
1381 cps = sys_safecopyfrom(mp->m_source, iovp->iov_grant,
1382 0, (vir_bytes) ret, s);
1383 if (cps != OK) {
1384 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps);
1386 size += s;
1387 ret += s;
1390 assert(desc);
1391 if (size < ETH_MIN_PACK_SIZE)
1392 panic("invalid packet size: %d", size);
1394 rep->re_tx[tx_head].ret_busy = TRUE;
1396 if (tx_head == N_TX_DESC - 1) {
1397 desc->status = DESC_EOR | DESC_OWN | DESC_FS | DESC_LS | size;
1398 tx_head = 0;
1399 } else {
1400 desc->status = DESC_OWN | DESC_FS | DESC_LS | size;
1401 tx_head++;
1404 assert(tx_head < N_TX_DESC);
1405 rep->re_tx_head = tx_head;
1407 rl_outl(rep->re_base_port, RL_TPPOLL, RL_TPPOLL_NPQ);
1408 rep->re_flags |= REF_PACK_SENT;
1411 * If the interrupt handler called, don't send a reply. The reply
1412 * will be sent after all interrupts are handled.
1414 if (from_int)
1415 return;
1416 reply(rep);
1417 return;
1419 suspend:
1420 if (from_int)
1421 panic("should not be sending");
1423 rep->re_tx_mess = *mp;
1424 reply(rep);
1427 /*===========================================================================*
1428 * rl_check_ints *
1429 *===========================================================================*/
1430 static void rl_check_ints(rep)
1431 re_t *rep;
1433 int re_flags;
1435 re_flags = rep->re_flags;
1437 if ((re_flags & REF_READING) &&
1438 !(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE))
1440 assert(rep->re_rx_mess.m_type == DL_READV_S);
1441 rl_readv_s(&rep->re_rx_mess, TRUE /* from int */);
1444 if (rep->re_need_reset)
1445 rl_do_reset(rep);
1447 if (rep->re_send_int) {
1448 assert(rep->re_tx_mess.m_type == DL_WRITEV_S);
1449 rl_writev_s(&rep->re_tx_mess, TRUE /* from int */);
1452 if (rep->re_report_link) {
1453 rep->re_report_link = FALSE;
1455 rl_report_link(rep);
1458 if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV))
1459 reply(rep);
1462 /*===========================================================================*
1463 * rl_report_link *
1464 *===========================================================================*/
1465 static void rl_report_link(rep)
1466 re_t *rep;
1468 #if VERBOSE
1469 port_t port;
1470 u8_t mii_status;
1472 port = rep->re_base_port;
1474 mii_status = rl_inb(port, RL_PHYSTAT);
1476 if (mii_status & RL_STAT_LINK) {
1477 rep->re_link_up = 1;
1478 printf("%s: link up at ", rep->re_name);
1479 } else {
1480 rep->re_link_up = 0;
1481 printf("%s: link down\n", rep->re_name);
1482 return;
1485 if (mii_status & RL_STAT_1000)
1486 printf("1000 Mbps");
1487 else if (mii_status & RL_STAT_100)
1488 printf("100 Mbps");
1489 else if (mii_status & RL_STAT_10)
1490 printf("10 Mbps");
1492 if (mii_status & RL_STAT_FULLDUP)
1493 printf(", full duplex");
1494 else
1495 printf(", half duplex");
1496 printf("\n");
1497 #endif
1499 dump_phy(rep);
1502 /*===========================================================================*
1503 * rl_do_reset *
1504 *===========================================================================*/
1505 static void rl_do_reset(rep)
1506 re_t *rep;
1508 rep->re_need_reset = FALSE;
1509 rl_reset_hw(rep);
1510 rl_rec_mode(rep);
1512 rep->re_tx_head = 0;
1513 if (rep->re_flags & REF_SEND_AVAIL) {
1514 rep->re_tx[rep->re_tx_head].ret_busy = FALSE;
1515 rep->re_send_int = TRUE;
1519 /*===========================================================================*
1520 * rl_getstat_s *
1521 *===========================================================================*/
1522 static void rl_getstat_s(mp)
1523 message *mp;
1525 int r;
1526 eth_stat_t stats;
1527 re_t *rep;
1529 rep = &re_state;
1531 assert(rep->re_mode == REM_ENABLED);
1532 assert(rep->re_flags & REF_ENABLED);
1534 stats = rep->re_stat;
1536 r = sys_safecopyto(mp->m_source, mp->m_net_netdrv_dl_getstat_s.grant,
1537 0, (vir_bytes) &stats, sizeof(stats));
1538 if (r != OK)
1539 panic("rl_getstat_s: sys_safecopyto failed: %d", r);
1541 mp->m_type = DL_STAT_REPLY;
1542 r = ipc_send(mp->m_source, mp);
1543 if (r != OK)
1544 panic("rl_getstat_s: ipc_send failed: %d", r);
1547 /*===========================================================================*
1548 * reply *
1549 *===========================================================================*/
1550 static void reply(rep)
1551 re_t *rep;
1553 message reply;
1554 int flags;
1555 int r;
1557 flags = DL_NOFLAGS;
1558 if (rep->re_flags & REF_PACK_SENT)
1559 flags |= DL_PACK_SEND;
1560 if (rep->re_flags & REF_PACK_RECV)
1561 flags |= DL_PACK_RECV;
1563 reply.m_type = DL_TASK_REPLY;
1564 reply.m_netdrv_net_dl_task.flags = flags;
1565 reply.m_netdrv_net_dl_task.count = rep->re_read_s;
1567 r = ipc_send(rep->re_client, &reply);
1569 if (r < 0) {
1570 printf("RTL8169 tried sending to %d, type %d\n",
1571 rep->re_client, reply.m_type);
1572 panic("ipc_send failed: %d", r);
1575 rep->re_read_s = 0;
1576 rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
1579 /*===========================================================================*
1580 * mess_reply *
1581 *===========================================================================*/
1582 static void mess_reply(req, reply_mess)
1583 message *req;
1584 message *reply_mess;
1586 if (ipc_send(req->m_source, reply_mess) != OK)
1587 panic("unable to mess_reply");
1590 static void dump_phy(const re_t *rep)
1592 #if VERBOSE
1593 port_t port;
1594 u32_t t;
1596 port = rep->re_base_port;
1598 t = rl_inb(port, RL_CONFIG0);
1599 printf("CONFIG0\t\t:");
1600 t = t & RL_CFG0_ROM;
1601 if (t == RL_CFG0_ROM128K)
1602 printf(" 128K Boot ROM");
1603 else if (t == RL_CFG0_ROM64K)
1604 printf(" 64K Boot ROM");
1605 else if (t == RL_CFG0_ROM32K)
1606 printf(" 32K Boot ROM");
1607 else if (t == RL_CFG0_ROM16K)
1608 printf(" 16K Boot ROM");
1609 else if (t == RL_CFG0_ROM8K)
1610 printf(" 8K Boot ROM");
1611 else if (t == RL_CFG0_ROMNO)
1612 printf(" No Boot ROM");
1613 printf("\n");
1615 t = rl_inb(port, RL_CONFIG1);
1616 printf("CONFIG1\t\t:");
1617 if (t & RL_CFG1_LEDS1)
1618 printf(" LED1");
1619 if (t & RL_CFG1_LEDS0)
1620 printf(" LED0");
1621 if (t & RL_CFG1_DVRLOAD)
1622 printf(" Driver");
1623 if (t & RL_CFG1_LWACT)
1624 printf(" LWAKE");
1625 if (t & RL_CFG1_IOMAP)
1626 printf(" IOMAP");
1627 if (t & RL_CFG1_MEMMAP)
1628 printf(" MEMMAP");
1629 if (t & RL_CFG1_VPD)
1630 printf(" VPD");
1631 if (t & RL_CFG1_PME)
1632 printf(" PME");
1633 printf("\n");
1635 t = rl_inb(port, RL_CONFIG2);
1636 printf("CONFIG2\t\t:");
1637 if (t & RL_CFG2_AUX)
1638 printf(" AUX");
1639 if (t & RL_CFG2_PCIBW)
1640 printf(" PCI-64-Bit");
1641 else
1642 printf(" PCI-32-Bit");
1643 t = t & RL_CFG2_PCICLK;
1644 if (t == RL_CFG2_66MHZ)
1645 printf(" 66 MHz");
1646 else if (t == RL_CFG2_33MHZ)
1647 printf(" 33 MHz");
1648 printf("\n");
1650 t = mdio_read(port, MII_CTRL);
1651 printf("MII_CTRL\t:");
1652 if (t & MII_CTRL_RST)
1653 printf(" Reset");
1654 if (t & MII_CTRL_LB)
1655 printf(" Loopback");
1656 if (t & MII_CTRL_ANE)
1657 printf(" ANE");
1658 if (t & MII_CTRL_PD)
1659 printf(" Power-down");
1660 if (t & MII_CTRL_ISO)
1661 printf(" Isolate");
1662 if (t & MII_CTRL_RAN)
1663 printf(" RAN");
1664 if (t & MII_CTRL_DM)
1665 printf(" Full-duplex");
1666 if (t & MII_CTRL_CT)
1667 printf(" COL-signal");
1668 t = t & (MII_CTRL_SP_LSB | MII_CTRL_SP_MSB);
1669 if (t == MII_CTRL_SP_10)
1670 printf(" 10 Mb/s");
1671 else if (t == MII_CTRL_SP_100)
1672 printf(" 100 Mb/s");
1673 else if (t == MII_CTRL_SP_1000)
1674 printf(" 1000 Mb/s");
1675 printf("\n");
1677 t = mdio_read(port, MII_STATUS);
1678 printf("MII_STATUS\t:");
1679 if (t & MII_STATUS_100T4)
1680 printf(" 100Base-T4");
1681 if (t & MII_STATUS_100XFD)
1682 printf(" 100BaseX-FD");
1683 if (t & MII_STATUS_100XHD)
1684 printf(" 100BaseX-HD");
1685 if (t & MII_STATUS_10FD)
1686 printf(" 10Mbps-FD");
1687 if (t & MII_STATUS_10HD)
1688 printf(" 10Mbps-HD");
1689 if (t & MII_STATUS_100T2FD)
1690 printf(" 100Base-T2-FD");
1691 if (t & MII_STATUS_100T2HD)
1692 printf(" 100Base-T2-HD");
1693 if (t & MII_STATUS_EXT_STAT)
1694 printf(" Ext-stat");
1695 if (t & MII_STATUS_RES)
1696 printf(" res-0x%x", t & MII_STATUS_RES);
1697 if (t & MII_STATUS_MFPS)
1698 printf(" MFPS");
1699 if (t & MII_STATUS_ANC)
1700 printf(" ANC");
1701 if (t & MII_STATUS_RF)
1702 printf(" remote-fault");
1703 if (t & MII_STATUS_ANA)
1704 printf(" ANA");
1705 if (t & MII_STATUS_LS)
1706 printf(" Link");
1707 if (t & MII_STATUS_JD)
1708 printf(" Jabber");
1709 if (t & MII_STATUS_EC)
1710 printf(" Extended-capability");
1711 printf("\n");
1713 t = mdio_read(port, MII_ANA);
1714 printf("MII_ANA\t\t: 0x%04x\n", t);
1716 t = mdio_read(port, MII_ANLPA);
1717 printf("MII_ANLPA\t: 0x%04x\n", t);
1719 t = mdio_read(port, MII_ANE);
1720 printf("MII_ANE\t\t:");
1721 if (t & MII_ANE_RES)
1722 printf(" res-0x%x", t & MII_ANE_RES);
1723 if (t & MII_ANE_PDF)
1724 printf(" Par-Detect-Fault");
1725 if (t & MII_ANE_LPNPA)
1726 printf(" LP-Next-Page-Able");
1727 if (t & MII_ANE_NPA)
1728 printf(" Loc-Next-Page-Able");
1729 if (t & MII_ANE_PR)
1730 printf(" Page-Received");
1731 if (t & MII_ANE_LPANA)
1732 printf(" LP-Auto-Neg-Able");
1733 printf("\n");
1735 t = mdio_read(port, MII_1000_CTRL);
1736 printf("MII_1000_CTRL\t:");
1737 if (t & MII_1000C_FULL)
1738 printf(" 1000BaseT-FD");
1739 if (t & MII_1000C_HALF)
1740 printf(" 1000BaseT-HD");
1741 printf("\n");
1743 t = mdio_read(port, MII_1000_STATUS);
1744 if (t) {
1745 printf("MII_1000_STATUS\t:");
1746 if (t & MII_1000S_LRXOK)
1747 printf(" Local-Receiver");
1748 if (t & MII_1000S_RRXOK)
1749 printf(" Remote-Receiver");
1750 if (t & MII_1000S_HALF)
1751 printf(" 1000BaseT-HD");
1752 if (t & MII_1000S_FULL)
1753 printf(" 1000BaseT-FD");
1754 printf("\n");
1756 t = mdio_read(port, MII_EXT_STATUS);
1757 printf("MII_EXT_STATUS\t:");
1758 if (t & MII_ESTAT_1000XFD)
1759 printf(" 1000BaseX-FD");
1760 if (t & MII_ESTAT_1000XHD)
1761 printf(" 1000BaseX-HD");
1762 if (t & MII_ESTAT_1000TFD)
1763 printf(" 1000BaseT-FD");
1764 if (t & MII_ESTAT_1000THD)
1765 printf(" 1000BaseT-HD");
1766 printf("\n");
1768 #endif
1771 static void do_hard_int(void)
1773 int s;
1775 /* Run interrupt handler at driver level. */
1776 rl_handler(&re_state);
1778 /* Reenable interrupts for this hook. */
1779 if ((s = sys_irqenable(&re_state.re_hook_id)) != OK)
1780 printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
1783 /*===========================================================================*
1784 * rl_handler *
1785 *===========================================================================*/
1786 static void rl_handler(re_t *rep)
1788 int i, port, tx_head, tx_tail, link_up;
1789 u16_t isr;
1790 re_desc *desc;
1791 int_event_check = FALSE; /* disable check by default */
1793 port = rep->re_base_port;
1795 /* Ack interrupt */
1796 isr = rl_inw(port, RL_ISR);
1797 if(!isr)
1798 return;
1799 rl_outw(port, RL_ISR, isr);
1800 rep->interrupts++;
1802 if (isr & RL_IMR_FOVW) {
1803 isr &= ~RL_IMR_FOVW;
1804 /* Should do anything? */
1806 rep->re_stat.ets_fifoOver++;
1808 if (isr & RL_IMR_PUN) {
1809 isr &= ~RL_IMR_PUN;
1812 * Either the link status changed or there was a TX fifo
1813 * underrun.
1815 link_up = !(!(rl_inb(port, RL_PHYSTAT) & RL_STAT_LINK));
1816 if (link_up != rep->re_link_up) {
1817 rep->re_report_link = TRUE;
1818 rep->re_got_int = TRUE;
1819 int_event_check = TRUE;
1823 if (isr & (RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK)) {
1824 if (isr & RL_ISR_RER)
1825 rep->re_stat.ets_recvErr++;
1826 isr &= ~(RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK);
1828 if (!rep->re_got_int && (rep->re_flags & REF_READING)) {
1829 rep->re_got_int = TRUE;
1830 int_event_check = TRUE;
1834 if ((isr & (RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK)) || 1) {
1835 if (isr & RL_ISR_TER)
1836 rep->re_stat.ets_sendErr++;
1837 isr &= ~(RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK);
1839 /* Transmit completed */
1840 tx_head = rep->re_tx_head;
1841 tx_tail = tx_head+1;
1842 if (tx_tail >= N_TX_DESC)
1843 tx_tail = 0;
1844 for (i = 0; i < 2 * N_TX_DESC; i++) {
1845 if (!rep->re_tx[tx_tail].ret_busy) {
1846 /* Strange, this buffer is not in-use.
1847 * Increment tx_tail until tx_head is
1848 * reached (or until we find a buffer that
1849 * is in-use.
1851 if (tx_tail == tx_head)
1852 break;
1853 if (++tx_tail >= N_TX_DESC)
1854 tx_tail = 0;
1855 assert(tx_tail < N_TX_DESC);
1856 continue;
1858 desc = rep->re_tx_desc;
1859 desc += tx_tail;
1860 if (desc->status & DESC_OWN) {
1861 /* Buffer is not yet ready */
1862 break;
1865 rep->re_stat.ets_packetT++;
1866 rep->re_tx[tx_tail].ret_busy = FALSE;
1868 if (++tx_tail >= N_TX_DESC)
1869 tx_tail = 0;
1870 assert(tx_tail < N_TX_DESC);
1872 if (rep->re_flags & REF_SEND_AVAIL) {
1873 rep->re_send_int = TRUE;
1874 if (!rep->re_got_int) {
1875 rep->re_got_int = TRUE;
1876 int_event_check = TRUE;
1880 assert(i < 2 * N_TX_DESC);
1883 /* Ignore Reserved Interrupt */
1884 if (isr & RL_ISR_RES)
1885 isr &= ~RL_ISR_RES;
1887 if (isr)
1888 printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr);
1891 /*===========================================================================*
1892 * rl_watchdog_f *
1893 *===========================================================================*/
1894 static void rl_watchdog_f(tp)
1895 minix_timer_t *tp;
1897 re_t *rep;
1898 /* Use a synchronous alarm instead of a watchdog timer. */
1899 sys_setalarm(system_hz, 0);
1901 rep = &re_state;
1903 if (rep->re_mode != REM_ENABLED)
1904 return;
1906 /* Should collect statistics */
1907 if (!(++rep->dtcc_counter % RE_DTCC_VALUE))
1908 rtl8169_update_stat(rep);
1910 if (!(rep->re_flags & REF_SEND_AVAIL)) {
1911 /* Assume that an idle system is alive */
1912 rep->re_tx_alive = TRUE;
1913 return;
1915 if (rep->re_tx_alive) {
1916 rep->re_tx_alive = FALSE;
1917 return;
1919 printf("rl_watchdog_f: resetting instance %d mode 0x%x flags 0x%x\n",
1920 re_instance, rep->re_mode, rep->re_flags);
1921 printf("tx_head :%8d busy %d\t",
1922 rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
1923 rep->re_need_reset = TRUE;
1924 rep->re_got_int = TRUE;
1926 check_int_events();