4 * This file contains a ethernet device driver for Realtek rtl8169 based
9 #include "../drivers.h"
14 #include <minix/com.h>
16 #include <minix/syslib.h>
17 #include <minix/type.h>
18 #include <minix/sysutil.h>
19 #include <minix/endpoint.h>
22 #include <net/gen/ether.h>
23 #include <net/gen/eth_io.h>
26 #include <sys/types.h>
29 #include "../../kernel/const.h"
30 #include "../../kernel/config.h"
31 #include "../../kernel/type.h"
34 #define printW() ((void)0)
36 #define VERBOSE 0 /* display message during init */
40 #define RE_PORT_NR 1 /* Minix */
42 #define IOVEC_NR 16 /* I/O vectors are handled IOVEC_NR entries at a time. */
44 #define RE_DTCC_VALUE 600 /* DTCC Update after every 10 minutes */
46 #define RX_CONFIG_MASK 0xff7e1880 /* Clears the bits supported by chip */
48 #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)
50 #define RL_ENVVAR "RTLETH" /* Configuration */
59 { 0x10ec, 0x8129, 0 }, /* Realtek RTL8129 */
60 { 0x10ec, 0x8167, 0 }, /* Realtek RTL8169/8110 Family Gigabit NIC */
61 { 0x10ec, 0x8169, 0 }, /* Realtek RTL8169 */
63 { 0x1186, 0x4300, 0 }, /* D-Link DGE-528T Gigabit adaptor */
65 { 0x1259, 0xc107, 0 }, /* Allied Telesyn International Gigabit Ethernet Adapter */
67 { 0x1385, 0x8169, 0 }, /* Netgear Gigabit Ethernet Adapter */
69 { 0x16ec, 0x0116, 0 }, /* US Robotics Realtek 8169S chip */
71 { 0x1737, 0x1032, 0 }, /* Linksys Instant Gigabit Desktop Network Interface */
76 typedef struct re_desc
78 u32_t status
; /* command/status */
79 u32_t vlan
; /* VLAN */
80 u32_t addr_low
; /* low 32-bits of physical buffer address */
81 u32_t addr_high
; /* high 32-bits of physical buffer address */
84 typedef struct re_dtcc
86 u32_t TxOk_low
; /* low 32-bits of Tx Ok packets */
87 u32_t TxOk_high
; /* high 32-bits of Tx Ok packets */
88 u32_t RxOk_low
; /* low 32-bits of Rx Ok packets */
89 u32_t RxOk_high
; /* high 32-bits of Rx Ok packets */
90 u32_t TxEr_low
; /* low 32-bits of Tx errors */
91 u32_t TxEr_high
; /* high 32-bits of Tx errors */
92 u32_t RxEr
; /* Rx errors */
93 u16_t MissPkt
; /* Missed packets */
94 u16_t FAE
; /* Frame Aignment Error packets (MII mode only) */
95 u32_t Tx1Col
; /* Tx Ok packets with only 1 collision happened before Tx Ok */
96 u32_t TxMCol
; /* Tx Ok packets with > 1 and < 16 collisions happened before Tx Ok */
97 u32_t RxOkPhy_low
; /* low 32-bits of Rx Ok packets with physical addr destination ID */
98 u32_t RxOkPhy_high
; /* high 32-bits of Rx Ok packets with physical addr destination ID */
99 u32_t RxOkBrd_low
; /* low 32-bits of Rx Ok packets with broadcast destination ID */
100 u32_t RxOkBrd_high
; /* high 32-bits of Rx Ok packets with broadcast destination ID */
101 u32_t RxOkMul
; /* Rx Ok Packets with multicast destination ID */
102 u16_t TxAbt
; /* Tx abort packets */
103 u16_t TxUndrn
; /* Tx underrun packets */
111 endpoint_t re_client
;
131 re_desc
*re_rx_desc
; /* Rx descriptor buffer */
132 phys_bytes p_rx_desc
; /* Rx descriptor buffer physical */
141 re_desc
*re_tx_desc
; /* Tx descriptor buffer */
142 phys_bytes p_tx_desc
; /* Tx descriptor buffer physical */
145 int re_seen
; /* TRUE iff device available */
151 int re_hook_id
; /* IRQ hook id at kernel */
153 phys_bytes dtcc_buf
; /* Dump Tally Counter buffer physical */
154 re_dtcc
*v_dtcc_buf
; /* Dump Tally Counter buffer */
155 u32_t dtcc_counter
; /* DTCC update counter */
156 ether_addr_t re_address
;
159 char re_name
[sizeof("rtl8169#n")];
160 iovec_t re_iovec
[IOVEC_NR
];
161 iovec_s_t re_iovec_s
[IOVEC_NR
];
166 #define REM_DISABLED 0x0
167 #define REM_ENABLED 0x1
169 #define REF_PACK_SENT 0x001
170 #define REF_PACK_RECV 0x002
171 #define REF_SEND_AVAIL 0x004
172 #define REF_READING 0x010
173 #define REF_EMPTY 0x000
174 #define REF_PROMISC 0x040
175 #define REF_MULTI 0x080
176 #define REF_BROAD 0x100
177 #define REF_ENABLED 0x200
179 static re_t re_table
[RE_PORT_NR
];
181 static u16_t eth_ign_proto
;
182 static timer_t rl_watchdog
;
184 FORWARD
_PROTOTYPE(unsigned my_inb
, (U16_t port
));
185 FORWARD
_PROTOTYPE(unsigned my_inw
, (U16_t port
));
186 FORWARD
_PROTOTYPE(unsigned my_inl
, (U16_t port
));
187 static unsigned my_inb(U16_t port
)
191 if ((s
= sys_inb(port
, &value
)) != OK
)
192 printf("RTL8169: warning, sys_inb failed: %d\n", s
);
195 static unsigned my_inw(U16_t port
)
199 if ((s
= sys_inw(port
, &value
)) != OK
)
200 printf("RTL8169: warning, sys_inw failed: %d\n", s
);
203 static unsigned my_inl(U16_t port
)
207 if ((s
= sys_inl(port
, &value
)) != OK
)
208 printf("RTL8169: warning, sys_inl failed: %d\n", s
);
211 #define rl_inb(port, offset) (my_inb((port) + (offset)))
212 #define rl_inw(port, offset) (my_inw((port) + (offset)))
213 #define rl_inl(port, offset) (my_inl((port) + (offset)))
215 FORWARD
_PROTOTYPE(void my_outb
, (U16_t port
, U8_t value
));
216 FORWARD
_PROTOTYPE(void my_outw
, (U16_t port
, U16_t value
));
217 FORWARD
_PROTOTYPE(void my_outl
, (U16_t port
, U32_t value
));
218 static void my_outb(U16_t port
, U8_t value
)
222 if ((s
= sys_outb(port
, value
)) != OK
)
223 printf("RTL8169: warning, sys_outb failed: %d\n", s
);
225 static void my_outw(U16_t port
, U16_t value
)
229 if ((s
= sys_outw(port
, value
)) != OK
)
230 printf("RTL8169: warning, sys_outw failed: %d\n", s
);
232 static void my_outl(U16_t port
, U32_t value
)
236 if ((s
= sys_outl(port
, value
)) != OK
)
237 printf("RTL8169: warning, sys_outl failed: %d\n", s
);
239 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value)))
240 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
241 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
243 _PROTOTYPE( static void rl_init
, (message
*mp
) );
244 _PROTOTYPE( static void rl_pci_conf
, (void) );
245 _PROTOTYPE( static int rl_probe
, (re_t
*rep
) );
246 _PROTOTYPE( static void rl_conf_hw
, (re_t
*rep
) );
247 _PROTOTYPE( static void rl_init_buf
, (re_t
*rep
) );
248 _PROTOTYPE( static void rl_init_hw
, (re_t
*rep
) );
249 _PROTOTYPE( static void rl_reset_hw
, (re_t
*rep
) );
250 _PROTOTYPE( static void rl_confaddr
, (re_t
*rep
) );
251 _PROTOTYPE( static void rl_rec_mode
, (re_t
*rep
) );
252 _PROTOTYPE( static void rl_readv_s
, (message
*mp
, int from_int
) );
253 _PROTOTYPE( static void rl_writev_s
, (message
*mp
, int from_int
) );
254 _PROTOTYPE( static void rl_check_ints
, (re_t
*rep
) );
255 _PROTOTYPE( static void rl_report_link
, (re_t
*rep
) );
256 _PROTOTYPE( static void rl_do_reset
, (re_t
*rep
) );
257 _PROTOTYPE( static void rl_getstat
, (message
*mp
) );
258 _PROTOTYPE( static void rl_getstat_s
, (message
*mp
) );
259 _PROTOTYPE( static void rl_getname
, (message
*mp
) );
260 _PROTOTYPE( static void reply
, (re_t
*rep
, int err
, int may_block
) );
261 _PROTOTYPE( static void mess_reply
, (message
*req
, message
*reply
) );
262 _PROTOTYPE( static void rtl8169_stop
, (void) );
263 _PROTOTYPE( static void check_int_events
, (void) );
264 _PROTOTYPE( static void do_hard_int
, (void) );
265 _PROTOTYPE( static void rtl8169_dump
, (void) );
266 _PROTOTYPE( static void dump_phy
, (re_t
*rep
) );
267 _PROTOTYPE( static int rl_handler
, (re_t
*rep
) );
268 _PROTOTYPE( static void rl_watchdog_f
, (timer_t
*tp
) );
271 * The message used in the main loop is made global, so that rl_watchdog_f()
272 * can change its message type to fake an interrupt message.
275 PRIVATE
int int_event_check
; /* set to TRUE if events arrived */
277 static char *progname
;
280 /* SEF functions and variables. */
281 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
282 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
284 EXTERN
char **env_argv
;
286 /*===========================================================================*
288 *===========================================================================*/
289 int main(int argc
, char *argv
[])
293 /* SEF local startup. */
294 env_setargs(argc
, argv
);
298 if ((r
= sef_receive(ANY
, &m
)) != OK
)
299 panic("rtl8169", "sef_receive failed", r
);
301 if (is_notify(m
.m_type
)) {
302 switch (_ENDPOINT_P(m
.m_source
)) {
305 * Under MINIX, synchronous alarms are used
306 * instead of watchdog functions.
307 * The approach is very different: MINIX VMD
308 * timeouts are handled within the kernel
309 * (the watchdog is executed by CLOCK), and
310 * notify() the driver in some cases. MINIX
311 * timeouts result in a SYN_ALARM message to
312 * the driver and thus are handled where they
313 * should be handled. Locally, watchdog
314 * functions are used again.
320 if (int_event_check
) {
328 if (getsigset(&set
) != 0) break;
330 if (sigismember(&set
, SIGTERM
))
336 panic("rtl8169", "illegal notify from",
340 /* done, get nwe message */
345 case DL_WRITEV_S
: rl_writev_s(&m
, FALSE
); break;
346 case DL_READV_S
: rl_readv_s(&m
, FALSE
); break;
347 case DL_CONF
: rl_init(&m
); break;
348 case DL_GETSTAT
: rl_getstat(&m
); break;
349 case DL_GETSTAT_S
: rl_getstat_s(&m
); break;
350 case DL_GETNAME
: rl_getname(&m
); break;
352 panic("rtl8169", "illegal message", m
.m_type
);
357 /*===========================================================================*
358 * sef_local_startup *
359 *===========================================================================*/
360 PRIVATE
void sef_local_startup()
362 /* Register init callbacks. */
363 sef_setcb_init_fresh(sef_cb_init_fresh
);
364 sef_setcb_init_restart(sef_cb_init_fresh
);
366 /* No live update support for now. */
368 /* Let SEF perform startup. */
372 /*===========================================================================*
373 * sef_cb_init_fresh *
374 *===========================================================================*/
375 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*info
)
377 /* Initialize the rtl8169 driver. */
383 system_hz
= sys_hz();
385 (progname
= strrchr(env_argv
[0], '/')) ? progname
++
386 : (progname
= env_argv
[0]);
389 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v
, 0x0000L
, 0xFFFFL
);
390 eth_ign_proto
= htons((u16_t
) v
);
392 /* Claim buffer memory now under Minix, before MM takes it all. */
393 for (rep
= &re_table
[0]; rep
< re_table
+ RE_PORT_NR
; rep
++)
397 * Try to notify INET that we are present (again). If INET cannot
398 * be found, assume this is the first time we started and INET is
402 r
= ds_retrieve_label_num("inet", &inet_proc_nr
);
404 notify(inet_proc_nr
);
406 printf("rtl8169: ds_retrieve_label_num failed for 'inet': %d\n",
413 static void mdio_write(U16_t port
, int regaddr
, int value
)
417 rl_outl(port
, RL_PHYAR
, 0x80000000 | (regaddr
& 0x1F) << 16 | (value
& 0xFFFF));
419 for (i
= 20; i
> 0; i
--) {
421 * Check if the RTL8169 has completed writing to the specified
424 if (!(rl_inl(port
, RL_PHYAR
) & 0x80000000))
431 static int mdio_read(U16_t port
, int regaddr
)
435 rl_outl(port
, RL_PHYAR
, (regaddr
& 0x1F) << 16);
437 for (i
= 20; i
> 0; i
--) {
439 * Check if the RTL8169 has completed retrieving data from
440 * the specified MII register
442 if (rl_inl(port
, RL_PHYAR
) & 0x80000000) {
443 value
= (int)(rl_inl(port
, RL_PHYAR
) & 0xFFFF);
451 /*===========================================================================*
453 *===========================================================================*/
454 static void check_int_events(void)
459 for (i
= 0, rep
= &re_table
[0]; i
< RE_PORT_NR
; i
++, rep
++) {
460 if (rep
->re_mode
!= REM_ENABLED
)
462 if (!rep
->re_got_int
)
465 assert(rep
->re_flags
& REF_ENABLED
);
470 /*===========================================================================*
472 *===========================================================================*/
473 static void rtl8169_stop()
478 for (i
= 0, rep
= &re_table
[0]; i
< RE_PORT_NR
; i
++, rep
++) {
479 if (rep
->re_mode
!= REM_ENABLED
)
481 rl_outb(rep
->re_base_port
, RL_CR
, 0);
487 static void rtl8169_update_stat(re_t
*rep
)
492 port
= rep
->re_base_port
;
494 /* Fetch Missed Packets */
495 rep
->re_stat
.ets_missedP
+= rl_inw(port
, RL_MPC
);
496 rl_outw(port
, RL_MPC
, 0x00);
498 /* Dump Tally Counter Command */
499 rl_outl(port
, RL_DTCCR_HI
, 0); /* 64 bits */
500 rl_outl(port
, RL_DTCCR_LO
, rep
->dtcc_buf
| RL_DTCCR_CMD
);
501 for (i
= 0; i
< 1000; i
++) {
502 if (!(rl_inl(port
, RL_DTCCR_LO
) & RL_DTCCR_CMD
))
507 /* Update counters */
508 rep
->re_stat
.ets_frameAll
= rep
->v_dtcc_buf
->FAE
;
509 rep
->re_stat
.ets_transDef
= rep
->v_dtcc_buf
->TxUndrn
;
510 rep
->re_stat
.ets_transAb
= rep
->v_dtcc_buf
->TxAbt
;
511 rep
->re_stat
.ets_collision
=
512 rep
->v_dtcc_buf
->Tx1Col
+ rep
->v_dtcc_buf
->TxMCol
;
515 /*===========================================================================*
517 *===========================================================================*/
518 static void rtl8169_dump(void)
525 for (i
= 0, rep
= &re_table
[0]; i
< RE_PORT_NR
; i
++, rep
++) {
526 if (rep
->re_mode
== REM_DISABLED
)
527 printf("Realtek RTL 8169 port %d is disabled\n", i
);
529 if (rep
->re_mode
!= REM_ENABLED
)
532 rtl8169_update_stat(rep
);
534 printf("Realtek RTL 8169 statistics of port %d:\n", i
);
536 printf("recvErr :%8ld\t", rep
->re_stat
.ets_recvErr
);
537 printf("sendErr :%8ld\t", rep
->re_stat
.ets_sendErr
);
538 printf("OVW :%8ld\n", rep
->re_stat
.ets_OVW
);
540 printf("CRCerr :%8ld\t", rep
->re_stat
.ets_CRCerr
);
541 printf("frameAll :%8ld\t", rep
->re_stat
.ets_frameAll
);
542 printf("missedP :%8ld\n", rep
->re_stat
.ets_missedP
);
544 printf("packetR :%8ld\t", rep
->re_stat
.ets_packetR
);
545 printf("packetT :%8ld\t", rep
->re_stat
.ets_packetT
);
546 printf("transDef :%8ld\n", rep
->re_stat
.ets_transDef
);
548 printf("collision :%8ld\t", rep
->re_stat
.ets_collision
);
549 printf("transAb :%8ld\t", rep
->re_stat
.ets_transAb
);
550 printf("carrSense :%8ld\n", rep
->re_stat
.ets_carrSense
);
552 printf("fifoUnder :%8ld\t", rep
->re_stat
.ets_fifoUnder
);
553 printf("fifoOver :%8ld\t", rep
->re_stat
.ets_fifoOver
);
554 printf("OWC :%8ld\n", rep
->re_stat
.ets_OWC
);
555 printf("interrupts :%8lu\n", rep
->interrupts
);
557 printf("\nRealtek RTL 8169 Tally Counters:\n");
559 dtcc
= rep
->v_dtcc_buf
;
562 printf("TxOk :%8ld%08ld\t", dtcc
->TxOk_high
, dtcc
->TxOk_low
);
564 printf("TxOk :%16lu\t", dtcc
->TxOk_low
);
567 printf("RxOk :%8ld%08ld\n", dtcc
->RxOk_high
, dtcc
->RxOk_low
);
569 printf("RxOk :%16lu\n", dtcc
->RxOk_low
);
572 printf("TxEr :%8ld%08ld\t", dtcc
->TxEr_high
, dtcc
->TxEr_low
);
574 printf("TxEr :%16ld\t", dtcc
->TxEr_low
);
576 printf("RxEr :%16ld\n", dtcc
->RxEr
);
578 printf("Tx1Col :%16ld\t", dtcc
->Tx1Col
);
579 printf("TxMCol :%16ld\n", dtcc
->TxMCol
);
581 if (dtcc
->RxOkPhy_high
)
582 printf("RxOkPhy :%8ld%08ld\t", dtcc
->RxOkPhy_high
, dtcc
->RxOkPhy_low
);
584 printf("RxOkPhy :%16ld\t", dtcc
->RxOkPhy_low
);
586 if (dtcc
->RxOkBrd_high
)
587 printf("RxOkBrd :%8ld%08ld\n", dtcc
->RxOkBrd_high
, dtcc
->RxOkBrd_low
);
589 printf("RxOkBrd :%16ld\n", dtcc
->RxOkBrd_low
);
591 printf("RxOkMul :%16ld\t", dtcc
->RxOkMul
);
592 printf("MissPkt :%16d\n", dtcc
->MissPkt
);
594 printf("\nRealtek RTL 8169 Miscellaneous Info:\n");
596 printf("re_flags : 0x%08x\n", rep
->re_flags
);
597 printf("tx_head :%8d busy %d\t",
598 rep
->re_tx_head
, rep
->re_tx
[rep
->re_tx_head
].ret_busy
);
602 /*===========================================================================*
604 *===========================================================================*/
605 static void rl_init(mp
)
608 static int first_time
= 1;
616 rl_pci_conf(); /* Configure PCI devices. */
618 tmr_inittimer(&rl_watchdog
);
619 /* Use a synchronous alarm instead of a watchdog timer. */
620 sys_setalarm(system_hz
, 0);
624 if (port
< 0 || port
>= RE_PORT_NR
) {
625 reply_mess
.m_type
= DL_CONF_REPLY
;
626 reply_mess
.m3_i1
= ENXIO
;
627 mess_reply(mp
, &reply_mess
);
630 rep
= &re_table
[port
];
631 if (rep
->re_mode
== REM_DISABLED
) {
632 /* This is the default, try to (re)locate the device. */
634 if (rep
->re_mode
== REM_DISABLED
) {
635 /* Probe failed, or the device is configured off. */
636 reply_mess
.m_type
= DL_CONF_REPLY
;
637 reply_mess
.m3_i1
= ENXIO
;
638 mess_reply(mp
, &reply_mess
);
641 if (rep
->re_mode
== REM_ENABLED
)
645 assert(rep
->re_mode
== REM_ENABLED
);
646 assert(rep
->re_flags
& REF_ENABLED
);
648 rep
->re_flags
&= ~(REF_PROMISC
| REF_MULTI
| REF_BROAD
);
650 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
651 rep
->re_flags
|= REF_PROMISC
;
652 if (mp
->DL_MODE
& DL_MULTI_REQ
)
653 rep
->re_flags
|= REF_MULTI
;
654 if (mp
->DL_MODE
& DL_BROAD_REQ
)
655 rep
->re_flags
|= REF_BROAD
;
657 rep
->re_client
= mp
->m_source
;
660 reply_mess
.m_type
= DL_CONF_REPLY
;
661 reply_mess
.m3_i1
= mp
->DL_PORT
;
662 reply_mess
.m3_i2
= RE_PORT_NR
;
663 *(ether_addr_t
*) reply_mess
.m3_ca1
= rep
->re_address
;
665 mess_reply(mp
, &reply_mess
);
668 /*===========================================================================*
670 *===========================================================================*/
671 static void rl_pci_conf()
675 static char envvar
[] = RL_ENVVAR
"#";
676 static char envfmt
[] = "*:d.d.d";
677 static char val
[128];
680 for (i
= 0, rep
= re_table
; i
< RE_PORT_NR
; i
++, rep
++) {
681 strcpy(rep
->re_name
, "rtl8169#0");
682 rep
->re_name
[8] += i
;
683 rep
->re_seen
= FALSE
;
684 envvar
[sizeof(RL_ENVVAR
)-1] = '0' + i
;
685 if (0 == env_get_param(envvar
, val
, sizeof(val
)) &&
686 !env_prefix(envvar
, "pci"))
691 (void) env_parse(envvar
, envfmt
, 1, &v
, 0, 255);
694 (void) env_parse(envvar
, envfmt
, 2, &v
, 0, 255);
697 (void) env_parse(envvar
, envfmt
, 3, &v
, 0, 255);
703 for (h
= 1; h
>= 0; h
--) {
704 for (i
= 0, rep
= re_table
; i
< RE_PORT_NR
; i
++, rep
++) {
705 if (((rep
->re_pcibus
| rep
->re_pcidev
|
706 rep
->re_pcifunc
) != 0) != h
) {
715 /*===========================================================================*
717 *===========================================================================*/
718 static int rl_probe(rep
)
721 int i
, r
, devind
, just_one
;
727 if ((rep
->re_pcibus
| rep
->re_pcidev
| rep
->re_pcifunc
) != 0) {
728 /* Look for specific PCI device */
729 r
= pci_find_dev(rep
->re_pcibus
, rep
->re_pcidev
,
730 rep
->re_pcifunc
, &devind
);
732 printf("%s: no PCI found at %d.%d.%d\n",
733 rep
->re_name
, rep
->re_pcibus
,
734 rep
->re_pcidev
, rep
->re_pcifunc
);
737 pci_ids(devind
, &vid
, &did
);
740 r
= pci_first_dev(&devind
, &vid
, &did
);
747 for (i
= 0; pcitab
[i
].vid
!= 0; i
++) {
748 if (pcitab
[i
].vid
!= vid
)
750 if (pcitab
[i
].did
!= did
)
752 if (pcitab
[i
].checkclass
) {
754 "class check not implemented", NO_NUM
);
758 if (pcitab
[i
].vid
!= 0)
762 printf("%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
763 rep
->re_name
, vid
, did
,
765 rep
->re_pcidev
, rep
->re_pcifunc
);
769 r
= pci_next_dev(&devind
, &vid
, &did
);
774 dname
= pci_dev_name(vid
, did
);
776 dname
= "unknown device";
777 printf("%s: ", rep
->re_name
);
778 printf("%s (%x/%x) at %s\n", dname
, vid
, did
, pci_slot_name(devind
));
781 bar
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
784 "base address is not properly configured", NO_NUM
);
786 rep
->re_base_port
= bar
;
788 ilr
= pci_attr_r8(devind
, PCI_ILR
);
791 printf("%s: using I/O address 0x%lx, IRQ %d\n",
792 rep
->re_name
, (unsigned long)bar
, ilr
);
798 /*===========================================================================*
800 *===========================================================================*/
801 static void rl_conf_hw(rep
)
804 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
806 rep
->re_mode
= REM_DISABLED
; /* Superfluous */
809 rep
->re_mode
= REM_ENABLED
; /* PCI device is present */
810 if (rep
->re_mode
!= REM_ENABLED
)
813 rep
->re_flags
= REF_EMPTY
;
816 rep
->re_send_int
= 0;
817 rep
->re_report_link
= 0;
818 rep
->re_need_reset
= 0;
819 rep
->re_tx_alive
= 0;
823 rep
->re_stat
= empty_stat
;
824 rep
->dtcc_counter
= 0;
827 /*===========================================================================*
829 *===========================================================================*/
830 static void rl_init_buf(rep
)
833 size_t rx_bufsize
, tx_bufsize
, rx_descsize
, tx_descsize
, tot_bufsize
;
834 struct re_desc
*desc
;
841 /* Allocate receive and transmit descriptors */
842 rx_descsize
= (N_RX_DESC
* sizeof(struct re_desc
));
843 tx_descsize
= (N_TX_DESC
* sizeof(struct re_desc
));
845 /* Allocate receive and transmit buffers */
846 tx_bufsize
= ETH_MAX_PACK_SIZE_TAGGED
;
848 tx_bufsize
+= 4-(tx_bufsize
% 4); /* Align */
849 rx_bufsize
= RX_BUFSIZE
;
850 tot_bufsize
= rx_descsize
+ tx_descsize
;
851 tot_bufsize
+= (N_TX_DESC
* tx_bufsize
) + (N_RX_DESC
* rx_bufsize
);
852 tot_bufsize
+= sizeof(struct re_dtcc
);
854 if (tot_bufsize
% 4096)
855 tot_bufsize
+= 4096 - (tot_bufsize
% 4096);
857 if (!(mallocbuf
= alloc_contig(tot_bufsize
, AC_ALIGN64K
, &buf
)))
858 panic("RTL8169", "Couldn't allocate kernel buffer", NO_NUM
);
861 rep
->re_rx_desc
= (re_desc
*)mallocbuf
;
862 rep
->p_rx_desc
= buf
;
863 memset(mallocbuf
, 0x00, rx_descsize
);
865 mallocbuf
+= rx_descsize
;
868 rep
->re_tx_desc
= (re_desc
*)mallocbuf
;
869 rep
->p_tx_desc
= buf
;
870 memset(mallocbuf
, 0x00, tx_descsize
);
872 mallocbuf
+= tx_descsize
;
874 desc
= rep
->re_rx_desc
;
875 for (d
= 0; d
< N_RX_DESC
; d
++) {
876 /* Setting Rx buffer */
877 rep
->re_rx
[d
].ret_buf
= buf
;
878 rep
->re_rx
[d
].v_ret_buf
= mallocbuf
;
880 mallocbuf
+= rx_bufsize
;
882 /* Setting Rx descriptor */
883 if (d
== (N_RX_DESC
- 1)) /* Last descriptor? if so, set the EOR bit */
884 desc
->status
= DESC_EOR
| DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
886 desc
->status
= DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
888 desc
->addr_low
= rep
->re_rx
[d
].ret_buf
;
891 desc
= rep
->re_tx_desc
;
892 for (d
= 0; d
< N_TX_DESC
; d
++) {
893 rep
->re_tx
[d
].ret_busy
= FALSE
;
894 rep
->re_tx
[d
].ret_buf
= buf
;
895 rep
->re_tx
[d
].v_ret_buf
= mallocbuf
;
897 mallocbuf
+= tx_bufsize
;
899 /* Setting Tx descriptor */
900 desc
->addr_low
= rep
->re_tx
[d
].ret_buf
;
904 /* Dump Tally Counter buffer */
906 rep
->v_dtcc_buf
= (re_dtcc
*)mallocbuf
;
911 /*===========================================================================*
913 *===========================================================================*/
914 static void rl_init_hw(rep
)
919 rep
->re_flags
= REF_EMPTY
;
920 rep
->re_flags
|= REF_ENABLED
;
923 * Set the interrupt handler. The policy is to only send HARD_INT
924 * notifications. Don't reenable interrupts automatically. The id
925 * that is passed back is the interrupt line number.
927 rep
->re_hook_id
= rep
->re_irq
;
928 if ((s
= sys_irqsetpolicy(rep
->re_irq
, 0, &rep
->re_hook_id
)) != OK
)
929 printf("RTL8169: error, couldn't set IRQ policy: %d\n", s
);
933 if ((s
= sys_irqenable(&rep
->re_hook_id
)) != OK
)
934 printf("RTL8169: error, couldn't enable interrupts: %d\n", s
);
936 printf("%s: model: %s mac: 0x%08lx\n",
937 rep
->re_name
, rep
->re_model
, rep
->re_mac
);
941 printf("%s: Ethernet address ", rep
->re_name
);
942 for (i
= 0; i
< 6; i
++) {
943 printf("%x%c", rep
->re_address
.ea_addr
[i
],
949 static void rtl8169s_phy_config(port_t port
)
951 mdio_write(port
, 0x1f, 0x0001);
952 mdio_write(port
, 0x06, 0x006e);
953 mdio_write(port
, 0x08, 0x0708);
954 mdio_write(port
, 0x15, 0x4000);
955 mdio_write(port
, 0x18, 0x65c7);
957 mdio_write(port
, 0x1f, 0x0001);
958 mdio_write(port
, 0x03, 0x00a1);
959 mdio_write(port
, 0x02, 0x0008);
960 mdio_write(port
, 0x01, 0x0120);
961 mdio_write(port
, 0x00, 0x1000);
962 mdio_write(port
, 0x04, 0x0800);
963 mdio_write(port
, 0x04, 0x0000);
965 mdio_write(port
, 0x03, 0xff41);
966 mdio_write(port
, 0x02, 0xdf60);
967 mdio_write(port
, 0x01, 0x0140);
968 mdio_write(port
, 0x00, 0x0077);
969 mdio_write(port
, 0x04, 0x7800);
970 mdio_write(port
, 0x04, 0x7000);
972 mdio_write(port
, 0x03, 0x802f);
973 mdio_write(port
, 0x02, 0x4f02);
974 mdio_write(port
, 0x01, 0x0409);
975 mdio_write(port
, 0x00, 0xf0f9);
976 mdio_write(port
, 0x04, 0x9800);
977 mdio_write(port
, 0x04, 0x9000);
979 mdio_write(port
, 0x03, 0xdf01);
980 mdio_write(port
, 0x02, 0xdf20);
981 mdio_write(port
, 0x01, 0xff95);
982 mdio_write(port
, 0x00, 0xba00);
983 mdio_write(port
, 0x04, 0xa800);
984 mdio_write(port
, 0x04, 0xa000);
986 mdio_write(port
, 0x03, 0xff41);
987 mdio_write(port
, 0x02, 0xdf20);
988 mdio_write(port
, 0x01, 0x0140);
989 mdio_write(port
, 0x00, 0x00bb);
990 mdio_write(port
, 0x04, 0xb800);
991 mdio_write(port
, 0x04, 0xb000);
993 mdio_write(port
, 0x03, 0xdf41);
994 mdio_write(port
, 0x02, 0xdc60);
995 mdio_write(port
, 0x01, 0x6340);
996 mdio_write(port
, 0x00, 0x007d);
997 mdio_write(port
, 0x04, 0xd800);
998 mdio_write(port
, 0x04, 0xd000);
1000 mdio_write(port
, 0x03, 0xdf01);
1001 mdio_write(port
, 0x02, 0xdf20);
1002 mdio_write(port
, 0x01, 0x100a);
1003 mdio_write(port
, 0x00, 0xa0ff);
1004 mdio_write(port
, 0x04, 0xf800);
1005 mdio_write(port
, 0x04, 0xf000);
1007 mdio_write(port
, 0x1f, 0x0000);
1008 mdio_write(port
, 0x0b, 0x0000);
1009 mdio_write(port
, 0x00, 0x9200);
1012 static void rtl8169scd_phy_config(port_t port
)
1014 mdio_write(port
, 0x1f, 0x0001);
1015 mdio_write(port
, 0x04, 0x0000);
1016 mdio_write(port
, 0x03, 0x00a1);
1017 mdio_write(port
, 0x02, 0x0008);
1018 mdio_write(port
, 0x01, 0x0120);
1019 mdio_write(port
, 0x00, 0x1000);
1020 mdio_write(port
, 0x04, 0x0800);
1021 mdio_write(port
, 0x04, 0x9000);
1022 mdio_write(port
, 0x03, 0x802f);
1023 mdio_write(port
, 0x02, 0x4f02);
1024 mdio_write(port
, 0x01, 0x0409);
1025 mdio_write(port
, 0x00, 0xf099);
1026 mdio_write(port
, 0x04, 0x9800);
1027 mdio_write(port
, 0x04, 0xa000);
1028 mdio_write(port
, 0x03, 0xdf01);
1029 mdio_write(port
, 0x02, 0xdf20);
1030 mdio_write(port
, 0x01, 0xff95);
1031 mdio_write(port
, 0x00, 0xba00);
1032 mdio_write(port
, 0x04, 0xa800);
1033 mdio_write(port
, 0x04, 0xf000);
1034 mdio_write(port
, 0x03, 0xdf01);
1035 mdio_write(port
, 0x02, 0xdf20);
1036 mdio_write(port
, 0x01, 0x101a);
1037 mdio_write(port
, 0x00, 0xa0ff);
1038 mdio_write(port
, 0x04, 0xf800);
1039 mdio_write(port
, 0x04, 0x0000);
1040 mdio_write(port
, 0x1f, 0x0000);
1042 mdio_write(port
, 0x1f, 0x0001);
1043 mdio_write(port
, 0x10, 0xf41b);
1044 mdio_write(port
, 0x14, 0xfb54);
1045 mdio_write(port
, 0x18, 0xf5c7);
1046 mdio_write(port
, 0x1f, 0x0000);
1048 mdio_write(port
, 0x1f, 0x0001);
1049 mdio_write(port
, 0x17, 0x0cc0);
1050 mdio_write(port
, 0x1f, 0x0000);
1053 /*===========================================================================*
1055 *===========================================================================*/
1056 static void rl_reset_hw(rep
)
1064 port
= rep
->re_base_port
;
1066 rl_outw(port
, RL_IMR
, 0x0000);
1068 /* Reset the device */
1069 printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
1070 port
, rl_inb(port
, RL_CR
));
1071 rl_outb(port
, RL_CR
, RL_CR_RST
);
1074 if (!(rl_inb(port
, RL_CR
) & RL_CR_RST
))
1076 } while (getuptime(&t1
) == OK
&& (t1
- t0
) < system_hz
);
1077 printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
1078 port
, rl_inb(port
, RL_CR
));
1079 if (rl_inb(port
, RL_CR
) & RL_CR_RST
)
1080 printf("rtl8169: reset failed to complete");
1081 rl_outw(port
, RL_ISR
, 0xFFFF);
1083 /* Get Model and MAC info */
1084 t
= rl_inl(port
, RL_TCR
);
1085 rep
->re_mac
= (t
& (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
));
1086 switch (rep
->re_mac
) {
1087 case RL_TCR_HWVER_RTL8169
:
1088 rep
->re_model
= "RTL8169";
1090 printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
1091 rl_outw(port
, 0x82, 0x01);
1093 case RL_TCR_HWVER_RTL8169S
:
1094 rep
->re_model
= "RTL8169S";
1096 rtl8169s_phy_config(port
);
1098 printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
1099 rl_outw(port
, 0x82, 0x01);
1100 printf("Set PHY Reg 0x0bh = 0x00h\n");
1101 mdio_write(port
, 0x0b, 0x0000); /* w 0x0b 15 0 0 */
1103 case RL_TCR_HWVER_RTL8110S
:
1104 rep
->re_model
= "RTL8110S";
1106 rtl8169s_phy_config(port
);
1108 printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
1109 rl_outw(port
, 0x82, 0x01);
1111 case RL_TCR_HWVER_RTL8169SB
:
1112 rep
->re_model
= "RTL8169SB";
1114 mdio_write(port
, 0x1f, 0x02);
1115 mdio_write(port
, 0x01, 0x90d0);
1116 mdio_write(port
, 0x1f, 0x00);
1118 printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
1119 rl_outw(port
, 0x82, 0x01);
1121 case RL_TCR_HWVER_RTL8110SCd
:
1122 rep
->re_model
= "RTL8110SCd";
1124 rtl8169scd_phy_config(port
);
1126 printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
1127 rl_outw(port
, 0x82, 0x01);
1130 rep
->re_model
= "Unknown";
1135 mdio_write(port
, MII_CTRL
, MII_CTRL_RST
);
1136 for (i
= 0; i
< 1000; i
++) {
1137 t
= mdio_read(port
, MII_CTRL
);
1138 if (!(t
& MII_CTRL_RST
))
1144 t
= mdio_read(port
, MII_CTRL
) | MII_CTRL_ANE
| MII_CTRL_DM
| MII_CTRL_SP_1000
;
1145 mdio_write(port
, MII_CTRL
, t
);
1147 t
= mdio_read(port
, MII_ANA
);
1148 t
|= MII_ANA_10THD
| MII_ANA_10TFD
| MII_ANA_100TXHD
| MII_ANA_100TXFD
;
1149 t
|= MII_ANA_PAUSE_SYM
| MII_ANA_PAUSE_ASYM
;
1150 mdio_write(port
, MII_ANA
, t
);
1152 t
= mdio_read(port
, MII_1000_CTRL
) | 0x300;
1153 mdio_write(port
, MII_1000_CTRL
, t
);
1155 /* Restart Auto-Negotiation Process */
1156 t
= mdio_read(port
, MII_CTRL
) | MII_CTRL_ANE
| MII_CTRL_RAN
;
1157 mdio_write(port
, MII_CTRL
, t
);
1159 rl_outw(port
, RL_9346CR
, RL_9346CR_EEM_CONFIG
); /* Unlock */
1161 t
= rl_inw(port
, RL_CPLUSCMD
);
1162 if ((rep
->re_mac
== RL_TCR_HWVER_RTL8169S
) ||
1163 (rep
->re_mac
== RL_TCR_HWVER_RTL8110S
)) {
1164 printf("Set MAC Reg C+CR Offset 0xE0. "
1165 "Bit-3 and bit-14 MUST be 1\n");
1166 rl_outw(port
, RL_CPLUSCMD
, t
| RL_CPLUS_MULRW
| (1 << 14));
1168 rl_outw(port
, RL_CPLUSCMD
, t
| RL_CPLUS_MULRW
);
1170 rl_outw(port
, RL_INTRMITIGATE
, 0x00);
1172 t
= rl_inb(port
, RL_CR
);
1173 rl_outb(port
, RL_CR
, t
| RL_CR_RE
| RL_CR_TE
);
1176 rl_outw(port
, RL_RMS
, RX_BUFSIZE
); /* Maximum rx packet size */
1177 t
= rl_inl(port
, RL_RCR
) & RX_CONFIG_MASK
;
1178 rl_outl(port
, RL_RCR
, RL_RCR_RXFTH_UNLIM
| RL_RCR_MXDMA_1024
| t
);
1179 rl_outl(port
, RL_RDSAR_LO
, rep
->p_rx_desc
);
1180 rl_outl(port
, RL_RDSAR_HI
, 0x00); /* For 64 bit */
1183 rl_outw(port
, RL_ETTHR
, 0x3f); /* No early transmit */
1184 rl_outl(port
, RL_TCR
, RL_TCR_MXDMA_2048
| RL_TCR_IFG_STD
);
1185 rl_outl(port
, RL_TNPDS_LO
, rep
->p_tx_desc
);
1186 rl_outl(port
, RL_TNPDS_HI
, 0x00); /* For 64 bit */
1188 rl_outw(port
, RL_9346CR
, RL_9346CR_EEM_NORMAL
); /* Lock */
1190 rl_outw(port
, RL_MPC
, 0x00);
1191 rl_outw(port
, RL_MULINT
, rl_inw(port
, RL_MULINT
) & 0xF000);
1192 rl_outw(port
, RL_IMR
, RE_INTR_MASK
);
1195 /*===========================================================================*
1197 *===========================================================================*/
1198 static void rl_confaddr(rep
)
1201 static char eakey
[] = RL_ENVVAR
"#_EA";
1202 static char eafmt
[] = "x:x:x:x:x:x";
1209 /* User defined ethernet address? */
1210 eakey
[sizeof(RL_ENVVAR
)-1] = '0' + (rep
-re_table
);
1212 port
= rep
->re_base_port
;
1214 for (i
= 0; i
< 6; i
++) {
1215 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
1217 rep
->re_address
.ea_addr
[i
] = v
;
1220 if (i
!= 0 && i
!= 6)
1221 env_panic(eakey
); /* It's all or nothing */
1223 /* Should update ethernet address in hardware */
1225 port
= rep
->re_base_port
;
1226 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_CONFIG
);
1228 for (i
= 0; i
< 4; i
++)
1229 w
|= (rep
->re_address
.ea_addr
[i
] << (i
* 8));
1230 rl_outl(port
, RL_IDR
, w
);
1232 for (i
= 4; i
< 6; i
++)
1233 w
|= (rep
->re_address
.ea_addr
[i
] << ((i
-4) * 8));
1234 rl_outl(port
, RL_IDR
+ 4, w
);
1235 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_NORMAL
);
1238 /* Get ethernet address */
1239 for (i
= 0; i
< 6; i
++)
1240 rep
->re_address
.ea_addr
[i
] = rl_inb(port
, RL_IDR
+i
);
1243 /*===========================================================================*
1245 *===========================================================================*/
1246 static void rl_rec_mode(rep
)
1251 u32_t mc_filter
[2]; /* Multicast hash filter */
1253 port
= rep
->re_base_port
;
1255 mc_filter
[1] = mc_filter
[0] = 0xffffffff;
1256 rl_outl(port
, RL_MAR
+ 0, mc_filter
[0]);
1257 rl_outl(port
, RL_MAR
+ 4, mc_filter
[1]);
1259 rcr
= rl_inl(port
, RL_RCR
);
1260 rcr
&= ~(RL_RCR_AB
| RL_RCR_AM
| RL_RCR_APM
| RL_RCR_AAP
);
1261 if (rep
->re_flags
& REF_PROMISC
)
1262 rcr
|= RL_RCR_AB
| RL_RCR_AM
| RL_RCR_AAP
;
1263 if (rep
->re_flags
& REF_BROAD
)
1265 if (rep
->re_flags
& REF_MULTI
)
1268 rl_outl(port
, RL_RCR
, RL_RCR_RXFTH_UNLIM
| RL_RCR_MXDMA_1024
| rcr
);
1271 void transmittest(re_t
*rep
)
1275 tx_head
= rep
->re_tx_head
;
1277 if(rep
->re_tx
[tx_head
].ret_busy
) {
1281 if ((r
= sef_receive(ANY
, &m
)) != OK
)
1282 panic("rtl8169", "sef_receive failed", r
);
1283 } while(m
.m_source
!= HARDWARE
);
1284 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1285 rep
->re_flags
|= REF_SEND_AVAIL
;
1291 /*===========================================================================*
1293 *===========================================================================*/
1294 static void rl_readv_s(message
*mp
, int from_int
)
1296 int i
, j
, n
, s
, dl_port
, re_client
, count
, size
, index
;
1298 unsigned totlen
, packlen
;
1300 u32_t rxstat
= 0x12345678;
1306 dl_port
= mp
->DL_PORT
;
1307 count
= mp
->DL_COUNT
;
1308 if (dl_port
< 0 || dl_port
>= RE_PORT_NR
)
1309 panic("rtl8169", " illegal port", dl_port
);
1310 rep
= &re_table
[dl_port
];
1311 re_client
= mp
->DL_PROC
;
1312 rep
->re_client
= re_client
;
1314 assert(rep
->re_mode
== REM_ENABLED
);
1315 assert(rep
->re_flags
& REF_ENABLED
);
1317 port
= rep
->re_base_port
;
1320 * Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1322 if (!from_int
&& (rl_inb(port
, RL_CR
) & RL_CR_BUFE
))
1323 goto suspend
; /* Receive buffer is empty, suspend */
1325 index
= rep
->re_rx_head
;
1327 desc
= rep
->re_rx_desc
;
1330 rxstat
= desc
->status
;
1332 if (rxstat
& DESC_OWN
)
1335 if (rxstat
& DESC_RX_CRC
)
1336 rep
->re_stat
.ets_CRCerr
++;
1338 if ((rxstat
& (DESC_FS
| DESC_LS
)) != (DESC_FS
| DESC_LS
)) {
1339 printf("rl_readv_s: packet is fragmented\n");
1340 /* Fix the fragmented packet */
1341 if (index
== N_RX_DESC
- 1) {
1342 desc
->status
= DESC_EOR
| DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
1344 desc
= rep
->re_rx_desc
;
1346 desc
->status
= DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
1350 goto readvs_loop
; /* Loop until we get correct packet */
1353 totlen
= rxstat
& DESC_RX_LENMASK
;
1354 if (totlen
< 8 || totlen
> 2 * ETH_MAX_PACK_SIZE
) {
1355 /* Someting went wrong */
1356 printf("rl_readv_s: bad length (%u) in status 0x%08lx\n",
1358 panic(NULL
, NULL
, NO_NUM
);
1361 /* Should subtract the CRC */
1362 packlen
= totlen
- ETH_CRC_SIZE
;
1365 for (i
= 0; i
< count
; i
+= IOVEC_NR
,
1366 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1371 cps
= sys_safecopyfrom(re_client
, mp
->DL_GRANT
, iov_offset
,
1372 (vir_bytes
) rep
->re_iovec_s
,
1373 n
* sizeof(rep
->re_iovec_s
[0]), D
);
1375 panic(__FILE__
, "rl_readv_s: sys_safecopyfrom failed",
1379 for (j
= 0, iovp
= rep
->re_iovec_s
; j
< n
; j
++, iovp
++) {
1381 if (size
+ s
> packlen
) {
1382 assert(packlen
> size
);
1386 cps
= sys_safecopyto(re_client
, iovp
->iov_grant
, 0,
1387 (vir_bytes
) rep
->re_rx
[index
].v_ret_buf
+ size
, s
, D
);
1390 "rl_readv_s: sys_safecopyto failed", cps
);
1393 if (size
== packlen
)
1396 if (size
== packlen
)
1402 rep
->re_stat
.ets_packetR
++;
1403 rep
->re_read_s
= packlen
;
1404 if (index
== N_RX_DESC
- 1) {
1405 desc
->status
= DESC_EOR
| DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
1408 desc
->status
= DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
1411 rep
->re_rx_head
= index
;
1412 assert(rep
->re_rx_head
< N_RX_DESC
);
1413 rep
->re_flags
= (rep
->re_flags
& ~REF_READING
) | REF_PACK_RECV
;
1416 reply(rep
, OK
, FALSE
);
1422 assert(rep
->re_flags
& REF_READING
);
1424 /* No need to store any state */
1428 rep
->re_rx_mess
= *mp
;
1429 assert(!(rep
->re_flags
& REF_READING
));
1430 rep
->re_flags
|= REF_READING
;
1432 reply(rep
, OK
, FALSE
);
1435 /*===========================================================================*
1437 *===========================================================================*/
1438 static void rl_writev_s(message
*mp
, int from_int
)
1440 int i
, j
, n
, s
, port
, count
, size
;
1441 int tx_head
, re_client
;
1450 count
= mp
->DL_COUNT
;
1451 if (port
< 0 || port
>= RE_PORT_NR
)
1452 panic("rtl8169", "illegal port", port
);
1453 rep
= &re_table
[port
];
1455 assert(port
>= 0 && port
< RE_PORT_NR
);
1457 re_client
= mp
->DL_PROC
;
1458 rep
->re_client
= re_client
;
1460 assert(rep
->re_mode
== REM_ENABLED
);
1461 assert(rep
->re_flags
& REF_ENABLED
);
1464 assert(rep
->re_flags
& REF_SEND_AVAIL
);
1465 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1466 rep
->re_send_int
= FALSE
;
1467 rep
->re_tx_alive
= TRUE
;
1470 tx_head
= rep
->re_tx_head
;
1472 desc
= rep
->re_tx_desc
;
1475 if(!desc
|| !rep
->re_tx_desc
) {
1476 printf("desc 0x%lx, re_tx_desc 0x%lx, tx_head %d, setup %d\n",
1477 desc
, rep
->re_tx_desc
, tx_head
, rep
->setup
);
1480 assert(rep
->re_tx_desc
);
1481 assert(rep
->re_tx_head
>= 0 && rep
->re_tx_head
< N_TX_DESC
);
1486 if (rep
->re_tx
[tx_head
].ret_busy
) {
1487 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1488 rep
->re_flags
|= REF_SEND_AVAIL
;
1489 if (rep
->re_tx
[tx_head
].ret_busy
)
1493 * Race condition, the interrupt handler may clear re_busy
1494 * before we got a chance to set REF_SEND_AVAIL. Checking
1495 * ret_busy twice should be sufficient.
1498 printf("rl_writev_s: race detected\n");
1500 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1501 rep
->re_send_int
= FALSE
;
1504 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1505 assert(!(rep
->re_flags
& REF_PACK_SENT
));
1508 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1509 for (i
= 0; i
< count
; i
+= IOVEC_NR
,
1510 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1515 cps
= sys_safecopyfrom(re_client
, mp
->DL_GRANT
, iov_offset
,
1516 (vir_bytes
) rep
->re_iovec_s
,
1517 n
* sizeof(rep
->re_iovec_s
[0]), D
);
1519 panic(__FILE__
, "rl_writev_s: sys_safecopyfrom failed",
1523 for (j
= 0, iovp
= rep
->re_iovec_s
; j
< n
; j
++, iovp
++) {
1525 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
)
1526 panic("rtl8169", "invalid packet size", NO_NUM
);
1528 cps
= sys_safecopyfrom(re_client
, iovp
->iov_grant
, 0,
1529 (vir_bytes
) ret
, s
, D
);
1532 "rl_writev_s: sys_safecopyfrom failed",
1540 if (size
< ETH_MIN_PACK_SIZE
)
1541 panic("rtl8169", "invalid packet size", size
);
1543 rep
->re_tx
[tx_head
].ret_busy
= TRUE
;
1545 if (tx_head
== N_TX_DESC
- 1) {
1546 desc
->status
= DESC_EOR
| DESC_OWN
| DESC_FS
| DESC_LS
| size
;
1549 desc
->status
= DESC_OWN
| DESC_FS
| DESC_LS
| size
;
1553 assert(tx_head
< N_TX_DESC
);
1554 rep
->re_tx_head
= tx_head
;
1556 rl_outl(rep
->re_base_port
, RL_TPPOLL
, RL_TPPOLL_NPQ
);
1557 rep
->re_flags
|= REF_PACK_SENT
;
1560 * If the interrupt handler called, don't send a reply. The reply
1561 * will be sent after all interrupts are handled.
1565 reply(rep
, OK
, FALSE
);
1570 panic("rtl8169", "should not be sending\n", NO_NUM
);
1572 rep
->re_tx_mess
= *mp
;
1573 reply(rep
, OK
, FALSE
);
1576 /*===========================================================================*
1578 *===========================================================================*/
1579 static void rl_check_ints(rep
)
1584 re_flags
= rep
->re_flags
;
1586 if ((re_flags
& REF_READING
) &&
1587 !(rl_inb(rep
->re_base_port
, RL_CR
) & RL_CR_BUFE
))
1589 assert(rep
->re_rx_mess
.m_type
== DL_READV_S
);
1590 rl_readv_s(&rep
->re_rx_mess
, TRUE
/* from int */);
1593 if (rep
->re_need_reset
)
1596 if (rep
->re_send_int
) {
1597 assert(rep
->re_tx_mess
.m_type
== DL_WRITEV_S
);
1598 rl_writev_s(&rep
->re_tx_mess
, TRUE
/* from int */);
1601 if (rep
->re_report_link
)
1602 rl_report_link(rep
);
1604 if (rep
->re_flags
& (REF_PACK_SENT
| REF_PACK_RECV
))
1605 reply(rep
, OK
, TRUE
);
1608 /*===========================================================================*
1610 *===========================================================================*/
1611 static void rl_report_link(rep
)
1617 rep
->re_report_link
= FALSE
;
1618 port
= rep
->re_base_port
;
1620 mii_status
= rl_inb(port
, RL_PHYSTAT
);
1622 if (mii_status
& RL_STAT_LINK
) {
1623 rep
->re_link_up
= 1;
1624 printf("%s: link up at ", rep
->re_name
);
1626 rep
->re_link_up
= 0;
1627 printf("%s: link down\n", rep
->re_name
);
1631 if (mii_status
& RL_STAT_1000
)
1632 printf("1000 Mbps");
1633 else if (mii_status
& RL_STAT_100
)
1635 else if (mii_status
& RL_STAT_10
)
1638 if (mii_status
& RL_STAT_FULLDUP
)
1639 printf(", full duplex");
1641 printf(", half duplex");
1647 /*===========================================================================*
1649 *===========================================================================*/
1650 static void rl_do_reset(rep
)
1653 rep
->re_need_reset
= FALSE
;
1657 rep
->re_tx_head
= 0;
1658 if (rep
->re_flags
& REF_SEND_AVAIL
) {
1659 rep
->re_tx
[rep
->re_tx_head
].ret_busy
= FALSE
;
1660 rep
->re_send_int
= TRUE
;
1664 /*===========================================================================*
1666 *===========================================================================*/
1667 static void rl_getstat(mp
)
1675 if (port
< 0 || port
>= RE_PORT_NR
)
1676 panic("rtl8169", "illegal port", port
);
1677 rep
= &re_table
[port
];
1678 rep
->re_client
= mp
->DL_PROC
;
1680 assert(rep
->re_mode
== REM_ENABLED
);
1681 assert(rep
->re_flags
& REF_ENABLED
);
1683 stats
= rep
->re_stat
;
1685 r
= sys_datacopy(SELF
, (vir_bytes
) &stats
, mp
->DL_PROC
,
1686 (vir_bytes
) mp
->DL_ADDR
, sizeof(stats
));
1688 panic(__FILE__
, "rl_getstat: sys_datacopy failed", r
);
1690 mp
->m_type
= DL_STAT_REPLY
;
1693 r
= send(mp
->m_source
, mp
);
1695 panic("RTL8169", "rl_getstat: send failed: %d\n", r
);
1698 /*===========================================================================*
1700 *===========================================================================*/
1701 static void rl_getstat_s(mp
)
1709 if (port
< 0 || port
>= RE_PORT_NR
)
1710 panic("rtl8169", "illegal port", port
);
1711 rep
= &re_table
[port
];
1712 rep
->re_client
= mp
->DL_PROC
;
1714 assert(rep
->re_mode
== REM_ENABLED
);
1715 assert(rep
->re_flags
& REF_ENABLED
);
1717 stats
= rep
->re_stat
;
1719 r
= sys_safecopyto(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
1720 (vir_bytes
) &stats
, sizeof(stats
), D
);
1722 panic(__FILE__
, "rl_getstat_s: sys_safecopyto failed", r
);
1724 mp
->m_type
= DL_STAT_REPLY
;
1727 r
= send(mp
->m_source
, mp
);
1729 panic("RTL8169", "rl_getstat_s: send failed: %d\n", r
);
1733 /*===========================================================================*
1735 *===========================================================================*/
1736 static void rl_getname(mp
)
1741 strncpy(mp
->DL_NAME
, progname
, sizeof(mp
->DL_NAME
));
1742 mp
->DL_NAME
[sizeof(mp
->DL_NAME
)-1] = '\0';
1743 mp
->m_type
= DL_NAME_REPLY
;
1744 r
= send(mp
->m_source
, mp
);
1746 panic("RTL8169", "rl_getname: send failed: %d\n", r
);
1750 /*===========================================================================*
1752 *===========================================================================*/
1753 static void reply(rep
, err
, may_block
)
1764 if (rep
->re_flags
& REF_PACK_SENT
)
1765 status
|= DL_PACK_SEND
;
1766 if (rep
->re_flags
& REF_PACK_RECV
)
1767 status
|= DL_PACK_RECV
;
1769 reply
.m_type
= DL_TASK_REPLY
;
1770 reply
.DL_PORT
= rep
- re_table
;
1771 reply
.DL_PROC
= rep
->re_client
;
1772 reply
.DL_STAT
= status
| ((u32_t
) err
<< 16);
1773 reply
.DL_COUNT
= rep
->re_read_s
;
1774 if (OK
!= (r
= getuptime(&now
)))
1775 panic("rtl8169", "getuptime() failed:", r
);
1776 reply
.DL_CLCK
= now
;
1778 r
= send(rep
->re_client
, &reply
);
1780 if (r
== ELOCKED
&& may_block
) {
1781 printW(); printf("send locked\n");
1786 printf("RTL8169 tried sending to %d, type %d\n",
1787 rep
->re_client
, reply
.m_type
);
1788 panic("rtl8169", "send failed:", r
);
1792 rep
->re_flags
&= ~(REF_PACK_SENT
| REF_PACK_RECV
);
1795 /*===========================================================================*
1797 *===========================================================================*/
1798 static void mess_reply(req
, reply_mess
)
1800 message
*reply_mess
;
1802 if (send(req
->m_source
, reply_mess
) != OK
)
1803 panic("rtl8169", "unable to mess_reply", NO_NUM
);
1806 static void dump_phy(re_t
*rep
)
1812 port
= rep
->re_base_port
;
1814 t
= rl_inb(port
, RL_CONFIG0
);
1815 printf("CONFIG0\t\t:");
1816 t
= t
& RL_CFG0_ROM
;
1817 if (t
== RL_CFG0_ROM128K
)
1818 printf(" 128K Boot ROM");
1819 else if (t
== RL_CFG0_ROM64K
)
1820 printf(" 64K Boot ROM");
1821 else if (t
== RL_CFG0_ROM32K
)
1822 printf(" 32K Boot ROM");
1823 else if (t
== RL_CFG0_ROM16K
)
1824 printf(" 16K Boot ROM");
1825 else if (t
== RL_CFG0_ROM8K
)
1826 printf(" 8K Boot ROM");
1827 else if (t
== RL_CFG0_ROMNO
)
1828 printf(" No Boot ROM");
1831 t
= rl_inb(port
, RL_CONFIG1
);
1832 printf("CONFIG1\t\t:");
1833 if (t
& RL_CFG1_LEDS1
)
1835 if (t
& RL_CFG1_LEDS0
)
1837 if (t
& RL_CFG1_DVRLOAD
)
1839 if (t
& RL_CFG1_LWACT
)
1841 if (t
& RL_CFG1_IOMAP
)
1843 if (t
& RL_CFG1_MEMMAP
)
1845 if (t
& RL_CFG1_VPD
)
1847 if (t
& RL_CFG1_PME
)
1851 t
= rl_inb(port
, RL_CONFIG2
);
1852 printf("CONFIG2\t\t:");
1853 if (t
& RL_CFG2_AUX
)
1855 if (t
& RL_CFG2_PCIBW
)
1856 printf(" PCI-64-Bit");
1858 printf(" PCI-32-Bit");
1859 t
= t
& RL_CFG2_PCICLK
;
1860 if (t
== RL_CFG2_66MHZ
)
1862 else if (t
== RL_CFG2_33MHZ
)
1866 t
= mdio_read(port
, MII_CTRL
);
1867 printf("MII_CTRL\t:");
1868 if (t
& MII_CTRL_RST
)
1870 if (t
& MII_CTRL_LB
)
1871 printf(" Loopback");
1872 if (t
& MII_CTRL_ANE
)
1874 if (t
& MII_CTRL_PD
)
1875 printf(" Power-down");
1876 if (t
& MII_CTRL_ISO
)
1878 if (t
& MII_CTRL_RAN
)
1880 if (t
& MII_CTRL_DM
)
1881 printf(" Full-duplex");
1882 if (t
& MII_CTRL_CT
)
1883 printf(" COL-signal");
1884 t
= t
& (MII_CTRL_SP_LSB
| MII_CTRL_SP_MSB
);
1885 if (t
== MII_CTRL_SP_10
)
1887 else if (t
== MII_CTRL_SP_100
)
1888 printf(" 100 Mb/s");
1889 else if (t
== MII_CTRL_SP_1000
)
1890 printf(" 1000 Mb/s");
1893 t
= mdio_read(port
, MII_STATUS
);
1894 printf("MII_STATUS\t:");
1895 if (t
& MII_STATUS_100T4
)
1896 printf(" 100Base-T4");
1897 if (t
& MII_STATUS_100XFD
)
1898 printf(" 100BaseX-FD");
1899 if (t
& MII_STATUS_100XHD
)
1900 printf(" 100BaseX-HD");
1901 if (t
& MII_STATUS_10FD
)
1902 printf(" 10Mbps-FD");
1903 if (t
& MII_STATUS_10HD
)
1904 printf(" 10Mbps-HD");
1905 if (t
& MII_STATUS_100T2FD
)
1906 printf(" 100Base-T2-FD");
1907 if (t
& MII_STATUS_100T2HD
)
1908 printf(" 100Base-T2-HD");
1909 if (t
& MII_STATUS_EXT_STAT
)
1910 printf(" Ext-stat");
1911 if (t
& MII_STATUS_RES
)
1912 printf(" res-0x%lx", t
& MII_STATUS_RES
);
1913 if (t
& MII_STATUS_MFPS
)
1915 if (t
& MII_STATUS_ANC
)
1917 if (t
& MII_STATUS_RF
)
1918 printf(" remote-fault");
1919 if (t
& MII_STATUS_ANA
)
1921 if (t
& MII_STATUS_LS
)
1923 if (t
& MII_STATUS_JD
)
1925 if (t
& MII_STATUS_EC
)
1926 printf(" Extended-capability");
1929 t
= mdio_read(port
, MII_ANA
);
1930 printf("MII_ANA\t\t: 0x%04lx\n", t
);
1932 t
= mdio_read(port
, MII_ANLPA
);
1933 printf("MII_ANLPA\t: 0x%04lx\n", t
);
1935 t
= mdio_read(port
, MII_ANE
);
1936 printf("MII_ANE\t\t:");
1937 if (t
& MII_ANE_RES
)
1938 printf(" res-0x%lx", t
& MII_ANE_RES
);
1939 if (t
& MII_ANE_PDF
)
1940 printf(" Par-Detect-Fault");
1941 if (t
& MII_ANE_LPNPA
)
1942 printf(" LP-Next-Page-Able");
1943 if (t
& MII_ANE_NPA
)
1944 printf(" Loc-Next-Page-Able");
1946 printf(" Page-Received");
1947 if (t
& MII_ANE_LPANA
)
1948 printf(" LP-Auto-Neg-Able");
1951 t
= mdio_read(port
, MII_1000_CTRL
);
1952 printf("MII_1000_CTRL\t:");
1953 if (t
& MII_1000C_FULL
)
1954 printf(" 1000BaseT-FD");
1955 if (t
& MII_1000C_HALF
)
1956 printf(" 1000BaseT-HD");
1959 t
= mdio_read(port
, MII_1000_STATUS
);
1961 printf("MII_1000_STATUS\t:");
1962 if (t
& MII_1000S_LRXOK
)
1963 printf(" Local-Receiver");
1964 if (t
& MII_1000S_RRXOK
)
1965 printf(" Remote-Receiver");
1966 if (t
& MII_1000S_HALF
)
1967 printf(" 1000BaseT-HD");
1968 if (t
& MII_1000S_FULL
)
1969 printf(" 1000BaseT-FD");
1972 t
= mdio_read(port
, MII_EXT_STATUS
);
1973 printf("MII_EXT_STATUS\t:");
1974 if (t
& MII_ESTAT_1000XFD
)
1975 printf(" 1000BaseX-FD");
1976 if (t
& MII_ESTAT_1000XHD
)
1977 printf(" 1000BaseX-HD");
1978 if (t
& MII_ESTAT_1000TFD
)
1979 printf(" 1000BaseT-FD");
1980 if (t
& MII_ESTAT_1000THD
)
1981 printf(" 1000BaseT-HD");
1987 static void do_hard_int(void)
1991 for (i
= 0; i
< RE_PORT_NR
; i
++) {
1993 /* Run interrupt handler at driver level. */
1994 rl_handler(&re_table
[i
]);
1996 /* Reenable interrupts for this hook. */
1997 if ((s
= sys_irqenable(&re_table
[i
].re_hook_id
)) != OK
)
1998 printf("RTL8169: error, couldn't enable interrupts: %d\n", s
);
2002 /*===========================================================================*
2004 *===========================================================================*/
2005 static int rl_handler(rep
)
2008 int i
, port
, tx_head
, tx_tail
, link_up
;
2011 int_event_check
= FALSE
; /* disable check by default */
2013 port
= rep
->re_base_port
;
2016 isr
= rl_inw(port
, RL_ISR
);
2019 rl_outw(port
, RL_ISR
, isr
);
2022 if (isr
& RL_IMR_FOVW
) {
2023 isr
&= ~RL_IMR_FOVW
;
2024 /* Should do anything? */
2026 rep
->re_stat
.ets_fifoOver
++;
2028 if (isr
& RL_IMR_PUN
) {
2032 * Either the link status changed or there was a TX fifo
2035 link_up
= !(!(rl_inb(port
, RL_PHYSTAT
) & RL_STAT_LINK
));
2036 if (link_up
!= rep
->re_link_up
) {
2037 rep
->re_report_link
= TRUE
;
2038 rep
->re_got_int
= TRUE
;
2039 int_event_check
= TRUE
;
2043 if (isr
& (RL_ISR_RDU
| RL_ISR_RER
| RL_ISR_ROK
)) {
2044 if (isr
& RL_ISR_RER
)
2045 rep
->re_stat
.ets_recvErr
++;
2046 isr
&= ~(RL_ISR_RDU
| RL_ISR_RER
| RL_ISR_ROK
);
2048 if (!rep
->re_got_int
&& (rep
->re_flags
& REF_READING
)) {
2049 rep
->re_got_int
= TRUE
;
2050 int_event_check
= TRUE
;
2054 if ((isr
& (RL_ISR_TDU
| RL_ISR_TER
| RL_ISR_TOK
)) || 1) {
2055 if (isr
& RL_ISR_TER
)
2056 rep
->re_stat
.ets_sendErr
++;
2057 isr
&= ~(RL_ISR_TDU
| RL_ISR_TER
| RL_ISR_TOK
);
2059 /* Transmit completed */
2060 tx_head
= rep
->re_tx_head
;
2061 tx_tail
= tx_head
+1;
2062 if (tx_tail
>= N_TX_DESC
)
2064 for (i
= 0; i
< 2 * N_TX_DESC
; i
++) {
2065 if (!rep
->re_tx
[tx_tail
].ret_busy
) {
2066 /* Strange, this buffer is not in-use.
2067 * Increment tx_tail until tx_head is
2068 * reached (or until we find a buffer that
2071 if (tx_tail
== tx_head
)
2073 if (++tx_tail
>= N_TX_DESC
)
2075 assert(tx_tail
< N_TX_DESC
);
2078 desc
= rep
->re_tx_desc
;
2080 if (desc
->status
& DESC_OWN
) {
2081 /* Buffer is not yet ready */
2085 rep
->re_stat
.ets_packetT
++;
2086 rep
->re_tx
[tx_tail
].ret_busy
= FALSE
;
2088 if (++tx_tail
>= N_TX_DESC
)
2090 assert(tx_tail
< N_TX_DESC
);
2092 if (rep
->re_flags
& REF_SEND_AVAIL
) {
2093 rep
->re_send_int
= TRUE
;
2094 if (!rep
->re_got_int
) {
2095 rep
->re_got_int
= TRUE
;
2096 int_event_check
= TRUE
;
2100 assert(i
< 2 * N_TX_DESC
);
2103 /* Ignore Reserved Interrupt */
2104 if (isr
& RL_ISR_RES
)
2108 printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr
);
2113 /*===========================================================================*
2115 *===========================================================================*/
2116 static void rl_watchdog_f(tp
)
2121 /* Use a synchronous alarm instead of a watchdog timer. */
2122 sys_setalarm(system_hz
, 0);
2124 for (i
= 0, rep
= &re_table
[0]; i
< RE_PORT_NR
; i
++, rep
++) {
2125 if (rep
->re_mode
!= REM_ENABLED
)
2128 /* Should collect statistics */
2129 if (!(++rep
->dtcc_counter
% RE_DTCC_VALUE
))
2130 rtl8169_update_stat(rep
);
2132 if (!(rep
->re_flags
& REF_SEND_AVAIL
)) {
2133 /* Assume that an idle system is alive */
2134 rep
->re_tx_alive
= TRUE
;
2137 if (rep
->re_tx_alive
) {
2138 rep
->re_tx_alive
= FALSE
;
2141 printf("rl_watchdog_f: resetting port %d mode 0x%x flags 0x%x\n",
2142 i
, rep
->re_mode
, rep
->re_flags
);
2143 printf("tx_head :%8d busy %d\t",
2144 rep
->re_tx_head
, rep
->re_tx
[rep
->re_tx_head
].ret_busy
);
2145 rep
->re_need_reset
= TRUE
;
2146 rep
->re_got_int
= TRUE
;