4 * This file contains a ethernet device driver for Realtek rtl8169 based
9 #include <minix/drivers.h>
10 #include <minix/netdriver.h>
15 #include <minix/com.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>
23 #include <net/gen/ether.h>
24 #include <net/gen/eth_io.h>
25 #include <machine/pci.h>
27 #include <sys/types.h>
30 #include "kernel/const.h"
31 #include "kernel/config.h"
32 #include "kernel/type.h"
34 #define VERBOSE 0 /* display message during init */
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 */
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 */
103 re_desc
*re_rx_desc
; /* Rx descriptor buffer */
104 phys_bytes p_rx_desc
; /* Rx descriptor buffer physical */
113 re_desc
*re_tx_desc
; /* Tx descriptor buffer */
114 phys_bytes p_tx_desc
; /* Tx descriptor buffer physical */
117 int re_seen
; /* TRUE iff device available */
120 int re_hook_id
; /* IRQ hook id at kernel */
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
;
128 char re_name
[sizeof("rtl8169#n")];
129 iovec_t re_iovec
[IOVEC_NR
];
130 iovec_s_t re_iovec_s
[IOVEC_NR
];
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
)
156 if ((s
= sys_inb(port
, &value
)) != OK
)
157 printf("RTL8169: warning, sys_inb failed: %d\n", s
);
160 static unsigned my_inw(u16_t port
)
164 if ((s
= sys_inw(port
, &value
)) != OK
)
165 printf("RTL8169: warning, sys_inw failed: %d\n", s
);
168 static unsigned my_inl(u16_t port
)
172 if ((s
= sys_inl(port
, &value
)) != OK
)
173 printf("RTL8169: warning, sys_inl failed: %d\n", s
);
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
)
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
)
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
)
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.
233 static int int_event_check
; /* set to TRUE if events arrived */
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 /*===========================================================================*
244 *===========================================================================*/
245 int main(int argc
, char *argv
[])
250 /* SEF local startup. */
251 env_setargs(argc
, argv
);
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
)) {
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.
277 if (int_event_check
) {
282 panic("illegal notify from: %d", m
.m_type
);
285 /* done, get nwe message */
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;
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. */
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. */
329 system_hz
= sys_hz();
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();
344 /*===========================================================================*
345 * sef_cb_signal_handler *
346 *===========================================================================*/
347 static void sef_cb_signal_handler(int signo
)
351 /* Only check for termination signal, ignore anything else. */
352 if (signo
!= SIGTERM
) return;
355 if (rep
->re_mode
== REM_ENABLED
)
356 rl_outb(rep
->re_base_port
, RL_CR
, RL_CR_RST
);
361 static void mdio_write(u16_t port
, int regaddr
, int value
)
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
372 if (!(rl_inl(port
, RL_PHYAR
) & 0x80000000))
379 static int mdio_read(u16_t port
, int regaddr
)
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);
399 /*===========================================================================*
401 *===========================================================================*/
402 static void check_int_events(void)
408 if (rep
->re_mode
!= REM_ENABLED
)
410 if (!rep
->re_got_int
)
413 assert(rep
->re_flags
& REF_ENABLED
);
417 static void rtl8169_update_stat(re_t
*rep
)
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
))
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
;
446 /*===========================================================================*
448 *===========================================================================*/
449 static void rtl8169_dump(void)
457 if (rep
->re_mode
== REM_DISABLED
)
458 printf("Realtek RTL 8169 instance %d is disabled\n",
461 if (rep
->re_mode
!= REM_ENABLED
)
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
;
494 printf("TxOk :%8ld%08ld\t", dtcc
->TxOk_high
, dtcc
->TxOk_low
);
496 printf("TxOk :%16lu\t", dtcc
->TxOk_low
);
499 printf("RxOk :%8ld%08ld\n", dtcc
->RxOk_high
, dtcc
->RxOk_low
);
501 printf("RxOk :%16lu\n", dtcc
->RxOk_low
);
504 printf("TxEr :%8ld%08ld\t", dtcc
->TxEr_high
, dtcc
->TxEr_low
);
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
);
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
);
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
);
534 /*===========================================================================*
536 *===========================================================================*/
537 static void rl_init(mp
)
540 static int first_time
= 1;
547 rl_pci_conf(); /* Configure PCI devices. */
549 /* Use a synchronous alarm instead of a watchdog timer. */
550 sys_setalarm(system_hz
, 0);
554 if (rep
->re_mode
== REM_DISABLED
) {
555 /* This is the default, try to (re)locate the device. */
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
);
564 if (rep
->re_mode
== REM_ENABLED
)
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
;
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 /*===========================================================================*
593 *===========================================================================*/
594 static void rl_pci_conf()
600 strlcpy(rep
->re_name
, "rtl8169#0", sizeof(rep
->re_name
));
601 rep
->re_name
[8] += re_instance
;
602 rep
->re_seen
= FALSE
;
606 if (rl_probe(rep
, re_instance
))
610 /*===========================================================================*
612 *===========================================================================*/
613 static int rl_probe(rep
, skip
)
625 r
= pci_first_dev(&devind
, &vid
, &did
);
630 r
= pci_next_dev(&devind
, &vid
, &did
);
636 dname
= pci_dev_name(vid
, did
);
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
));
644 bar
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
646 panic("base address is not properly configured");
648 rep
->re_base_port
= bar
;
650 ilr
= pci_attr_r8(devind
, PCI_ILR
);
653 printf("%s: using I/O address 0x%lx, IRQ %d\n",
654 rep
->re_name
, (unsigned long)bar
, ilr
);
660 /*===========================================================================*
662 *===========================================================================*/
663 static void rl_conf_hw(rep
)
666 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
668 rep
->re_mode
= REM_DISABLED
; /* Superfluous */
671 rep
->re_mode
= REM_ENABLED
; /* PCI device is present */
672 if (rep
->re_mode
!= REM_ENABLED
)
675 rep
->re_flags
= REF_EMPTY
;
678 rep
->re_send_int
= 0;
679 rep
->re_report_link
= 0;
680 rep
->re_need_reset
= 0;
681 rep
->re_tx_alive
= 0;
685 rep
->re_stat
= empty_stat
;
686 rep
->dtcc_counter
= 0;
689 /*===========================================================================*
691 *===========================================================================*/
692 static void rl_init_buf(rep
)
695 size_t rx_bufsize
, tx_bufsize
, rx_descsize
, tx_descsize
, tot_bufsize
;
696 struct re_desc
*desc
;
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
;
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");
723 rep
->re_rx_desc
= (re_desc
*)mallocbuf
;
724 rep
->p_rx_desc
= buf
;
725 memset(mallocbuf
, 0x00, rx_descsize
);
727 mallocbuf
+= rx_descsize
;
730 rep
->re_tx_desc
= (re_desc
*)mallocbuf
;
731 rep
->p_tx_desc
= buf
;
732 memset(mallocbuf
, 0x00, 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
;
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
);
748 desc
->status
= DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
750 desc
->addr_low
= rep
->re_rx
[d
].ret_buf
;
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
;
759 mallocbuf
+= tx_bufsize
;
761 /* Setting Tx descriptor */
762 desc
->addr_low
= rep
->re_tx
[d
].ret_buf
;
766 /* Dump Tally Counter buffer */
768 rep
->v_dtcc_buf
= (re_dtcc
*)mallocbuf
;
773 /*===========================================================================*
775 *===========================================================================*/
776 static void rl_init_hw(rep
)
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
);
798 if ((s
= sys_irqenable(&rep
->re_hook_id
)) != OK
)
799 printf("RTL8169: error, couldn't enable interrupts: %d\n", s
);
802 printf("%s: model: %s mac: 0x%08x\n",
803 rep
->re_name
, rep
->re_model
, rep
->re_mac
);
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
],
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 /*===========================================================================*
922 *===========================================================================*/
923 static void rl_reset_hw(rep
)
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);
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 */
958 case RL_TCR_HWVER_RTL8110S
:
959 rep
->re_model
= "RTL8110S";
961 rtl8169s_phy_config(port
);
963 rl_outw(port
, RL_CCR_UNDOC
, 0x01);
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);
974 case RL_TCR_HWVER_RTL8110SCd
:
975 rep
->re_model
= "RTL8110SCd";
977 rtl8169scd_phy_config(port
);
979 rl_outw(port
, RL_CCR_UNDOC
, 0x01);
981 case RL_TCR_HWVER_RTL8105E
:
982 rep
->re_model
= "RTL8105E";
985 rep
->re_model
= "Unknown";
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
))
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));
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
);
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
);
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 */
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 /*===========================================================================*
1058 *===========================================================================*/
1059 static void rl_confaddr(rep
)
1062 static char eakey
[] = RL_ENVVAR
"#_EA";
1063 static char eafmt
[] = "x:x:x:x:x:x";
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
)
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 */
1086 port
= rep
->re_base_port
;
1087 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_CONFIG
);
1089 for (i
= 0; i
< 4; i
++)
1090 w
|= (rep
->re_address
.ea_addr
[i
] << (i
* 8));
1091 rl_outl(port
, RL_IDR
, w
);
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 /*===========================================================================*
1106 *===========================================================================*/
1107 static void rl_rec_mode(rep
)
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
)
1126 if (rep
->re_flags
& REF_MULTI
)
1129 rl_outl(port
, RL_RCR
, RL_RCR_RXFTH_UNLIM
| RL_RCR_MXDMA_1024
| rcr
);
1132 void transmittest(re_t
*rep
)
1137 tx_head
= rep
->re_tx_head
;
1139 if(rep
->re_tx
[tx_head
].ret_busy
) {
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
;
1153 /*===========================================================================*
1155 *===========================================================================*/
1156 static void rl_readv_s(const message
*mp
, int from_int
)
1158 int i
, j
, n
, s
, count
, size
, index
;
1160 unsigned totlen
, packlen
;
1162 u32_t rxstat
= 0x12345678;
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
;
1188 rxstat
= desc
->status
;
1190 if (rxstat
& DESC_OWN
)
1193 if (rxstat
& DESC_RX_CRC
)
1194 rep
->re_stat
.ets_CRCerr
++;
1196 if ((rxstat
& (DESC_FS
| DESC_LS
)) != (DESC_FS
| DESC_LS
)) {
1198 printf("rl_readv_s: packet is fragmented\n");
1200 /* Fix the fragmented packet */
1201 if (index
== N_RX_DESC
- 1) {
1202 desc
->status
= DESC_EOR
| DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
1204 desc
= rep
->re_rx_desc
;
1206 desc
->status
= DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
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",
1221 /* Should subtract the CRC */
1222 packlen
= totlen
- ETH_CRC_SIZE
;
1225 for (i
= 0; i
< count
; i
+= IOVEC_NR
,
1226 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
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]));
1236 panic("rl_readv_s: sys_safecopyfrom failed: %d", cps
);
1239 for (j
= 0, iovp
= rep
->re_iovec_s
; j
< n
; j
++, iovp
++) {
1241 if (size
+ s
> packlen
) {
1242 assert(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
);
1249 panic("rl_readv_s: sys_safecopyto failed: %d", cps
);
1252 if (size
== packlen
)
1255 if (size
== packlen
)
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
);
1267 desc
->status
= DESC_OWN
| (RX_BUFSIZE
& DESC_RX_LENMASK
);
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
;
1281 assert(rep
->re_flags
& REF_READING
);
1283 /* No need to store any state */
1287 rep
->re_rx_mess
= *mp
;
1288 assert(!(rep
->re_flags
& REF_READING
));
1289 rep
->re_flags
|= REF_READING
;
1294 /*===========================================================================*
1296 *===========================================================================*/
1297 static void rl_writev_s(const message
*mp
, int from_int
)
1299 int i
, j
, n
, s
, count
, size
;
1310 rep
->re_client
= mp
->m_source
;
1311 count
= mp
->m_net_netdrv_dl_writev_s
.count
;
1314 assert(rep
->re_mode
== REM_ENABLED
);
1315 assert(rep
->re_flags
& REF_ENABLED
);
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
;
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
);
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
)
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.
1351 printf("rl_writev_s: race detected\n");
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
));
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]))
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]));
1373 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps
);
1376 for (j
= 0, iovp
= rep
->re_iovec_s
; j
< n
; j
++, iovp
++) {
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
);
1384 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps
);
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
;
1400 desc
->status
= DESC_OWN
| DESC_FS
| DESC_LS
| size
;
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.
1421 panic("should not be sending");
1423 rep
->re_tx_mess
= *mp
;
1427 /*===========================================================================*
1429 *===========================================================================*/
1430 static void rl_check_ints(rep
)
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
)
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
))
1462 /*===========================================================================*
1464 *===========================================================================*/
1465 static void rl_report_link(rep
)
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
);
1480 rep
->re_link_up
= 0;
1481 printf("%s: link down\n", rep
->re_name
);
1485 if (mii_status
& RL_STAT_1000
)
1486 printf("1000 Mbps");
1487 else if (mii_status
& RL_STAT_100
)
1489 else if (mii_status
& RL_STAT_10
)
1492 if (mii_status
& RL_STAT_FULLDUP
)
1493 printf(", full duplex");
1495 printf(", half duplex");
1502 /*===========================================================================*
1504 *===========================================================================*/
1505 static void rl_do_reset(rep
)
1508 rep
->re_need_reset
= FALSE
;
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 /*===========================================================================*
1521 *===========================================================================*/
1522 static void rl_getstat_s(mp
)
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
));
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
);
1544 panic("rl_getstat_s: ipc_send failed: %d", r
);
1547 /*===========================================================================*
1549 *===========================================================================*/
1550 static void reply(rep
)
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
);
1570 printf("RTL8169 tried sending to %d, type %d\n",
1571 rep
->re_client
, reply
.m_type
);
1572 panic("ipc_send failed: %d", r
);
1576 rep
->re_flags
&= ~(REF_PACK_SENT
| REF_PACK_RECV
);
1579 /*===========================================================================*
1581 *===========================================================================*/
1582 static void mess_reply(req
, reply_mess
)
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
)
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");
1615 t
= rl_inb(port
, RL_CONFIG1
);
1616 printf("CONFIG1\t\t:");
1617 if (t
& RL_CFG1_LEDS1
)
1619 if (t
& RL_CFG1_LEDS0
)
1621 if (t
& RL_CFG1_DVRLOAD
)
1623 if (t
& RL_CFG1_LWACT
)
1625 if (t
& RL_CFG1_IOMAP
)
1627 if (t
& RL_CFG1_MEMMAP
)
1629 if (t
& RL_CFG1_VPD
)
1631 if (t
& RL_CFG1_PME
)
1635 t
= rl_inb(port
, RL_CONFIG2
);
1636 printf("CONFIG2\t\t:");
1637 if (t
& RL_CFG2_AUX
)
1639 if (t
& RL_CFG2_PCIBW
)
1640 printf(" PCI-64-Bit");
1642 printf(" PCI-32-Bit");
1643 t
= t
& RL_CFG2_PCICLK
;
1644 if (t
== RL_CFG2_66MHZ
)
1646 else if (t
== RL_CFG2_33MHZ
)
1650 t
= mdio_read(port
, MII_CTRL
);
1651 printf("MII_CTRL\t:");
1652 if (t
& MII_CTRL_RST
)
1654 if (t
& MII_CTRL_LB
)
1655 printf(" Loopback");
1656 if (t
& MII_CTRL_ANE
)
1658 if (t
& MII_CTRL_PD
)
1659 printf(" Power-down");
1660 if (t
& MII_CTRL_ISO
)
1662 if (t
& MII_CTRL_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
)
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");
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
)
1699 if (t
& MII_STATUS_ANC
)
1701 if (t
& MII_STATUS_RF
)
1702 printf(" remote-fault");
1703 if (t
& MII_STATUS_ANA
)
1705 if (t
& MII_STATUS_LS
)
1707 if (t
& MII_STATUS_JD
)
1709 if (t
& MII_STATUS_EC
)
1710 printf(" Extended-capability");
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");
1730 printf(" Page-Received");
1731 if (t
& MII_ANE_LPANA
)
1732 printf(" LP-Auto-Neg-Able");
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");
1743 t
= mdio_read(port
, MII_1000_STATUS
);
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");
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");
1771 static void do_hard_int(void)
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 /*===========================================================================*
1785 *===========================================================================*/
1786 static void rl_handler(re_t
*rep
)
1788 int i
, port
, tx_head
, tx_tail
, link_up
;
1791 int_event_check
= FALSE
; /* disable check by default */
1793 port
= rep
->re_base_port
;
1796 isr
= rl_inw(port
, RL_ISR
);
1799 rl_outw(port
, RL_ISR
, isr
);
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
) {
1812 * Either the link status changed or there was a TX fifo
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
)
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
1851 if (tx_tail
== tx_head
)
1853 if (++tx_tail
>= N_TX_DESC
)
1855 assert(tx_tail
< N_TX_DESC
);
1858 desc
= rep
->re_tx_desc
;
1860 if (desc
->status
& DESC_OWN
) {
1861 /* Buffer is not yet ready */
1865 rep
->re_stat
.ets_packetT
++;
1866 rep
->re_tx
[tx_tail
].ret_busy
= FALSE
;
1868 if (++tx_tail
>= N_TX_DESC
)
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
)
1888 printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr
);
1891 /*===========================================================================*
1893 *===========================================================================*/
1894 static void rl_watchdog_f(tp
)
1898 /* Use a synchronous alarm instead of a watchdog timer. */
1899 sys_setalarm(system_hz
, 0);
1903 if (rep
->re_mode
!= REM_ENABLED
)
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
;
1915 if (rep
->re_tx_alive
) {
1916 rep
->re_tx_alive
= FALSE
;
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
;