4 * This file contains a ethernet device driver for Realtek rtl8139 based
7 * Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
9 * Aug 15, 2004 sync alarms replace watchdogs timers (Jorrit N. Herder)
10 * May 02, 2004 flag alarms replace micro_elapsed() (Jorrit N. Herder)
14 #define VERBOSE 0 /* Verbose debugging output */
15 #define RTL8139_FKEY 0 /* Use function key to dump RTL8139 status */
21 static int re_instance
;
23 static unsigned my_inb(u16_t port
) {
26 if ((s
=sys_inb(port
, &value
)) !=OK
)
27 printf("RTL8139: warning, sys_inb failed: %d\n", s
);
30 static unsigned my_inw(u16_t port
) {
33 if ((s
=sys_inw(port
, &value
)) !=OK
)
34 printf("RTL8139: warning, sys_inw failed: %d\n", s
);
37 static unsigned my_inl(u16_t port
) {
40 if ((s
=sys_inl(port
, &value
)) !=OK
)
41 printf("RTL8139: warning, sys_inl failed: %d\n", s
);
44 #define rl_inb(port, offset) (my_inb((port) + (offset)))
45 #define rl_inw(port, offset) (my_inw((port) + (offset)))
46 #define rl_inl(port, offset) (my_inl((port) + (offset)))
48 static void my_outb(u16_t port
, u8_t value
) {
50 if ((s
=sys_outb(port
, value
)) !=OK
)
51 printf("RTL8139: warning, sys_outb failed: %d\n", s
);
53 static void my_outw(u16_t port
, u16_t value
) {
55 if ((s
=sys_outw(port
, value
)) !=OK
)
56 printf("RTL8139: warning, sys_outw failed: %d\n", s
);
58 static void my_outl(u16_t port
, u32_t value
) {
60 if ((s
=sys_outl(port
, value
)) !=OK
)
61 printf("RTL8139: warning, sys_outl failed: %d\n", s
);
63 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value)))
64 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
65 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
67 static void rl_init(message
*mp
);
68 static void rl_pci_conf(void);
69 static int rl_probe(re_t
*rep
, int skip
);
70 static void rl_conf_hw(re_t
*rep
);
71 static void rl_init_buf(re_t
*rep
);
72 static void rl_init_hw(re_t
*rep
);
73 static void rl_reset_hw(re_t
*rep
);
74 static void rl_confaddr(re_t
*rep
);
75 static void rl_rec_mode(re_t
*rep
);
76 static void rl_readv_s(const message
*mp
, int from_int
);
77 static void rl_writev_s(const message
*mp
, int from_int
);
78 static void rl_check_ints(re_t
*rep
);
79 static void rl_report_link(re_t
*rep
);
80 static void mii_print_techab(u16_t techab
);
81 static void mii_print_stat_speed(u16_t stat
, u16_t extstat
);
82 static void rl_clear_rx(re_t
*rep
);
83 static void rl_do_reset(re_t
*rep
);
84 static void rl_getstat_s(message
*mp
);
85 static void reply(re_t
*rep
);
86 static void mess_reply(message
*req
, message
*reply
);
87 static void check_int_events(void);
88 static void do_hard_int(void);
89 static void rtl8139_dump(message
*m
);
91 static void dump_phy(re_t
*rep
);
93 static int rl_handler(re_t
*rep
);
94 static void rl_watchdog_f(timer_t
*tp
);
95 static void tell_dev(vir_bytes start
, size_t size
, int pci_bus
, int
96 pci_dev
, int pci_func
);
98 /* The message used in the main loop is made global, so that rl_watchdog_f()
99 * can change its message type to fake an interrupt message.
102 static int int_event_check
; /* set to TRUE if events arrived */
104 static u32_t system_hz
;
106 /* SEF functions and variables. */
107 static void sef_local_startup(void);
108 static int sef_cb_init_fresh(int type
, sef_init_info_t
*info
);
109 static void sef_cb_signal_handler(int signo
);
110 EXTERN
int sef_cb_lu_prepare(int state
);
111 EXTERN
int sef_cb_lu_state_isvalid(int state
);
112 EXTERN
void sef_cb_lu_state_dump(int state
);
114 /*===========================================================================*
116 *===========================================================================*/
117 int main(int argc
, char *argv
[])
122 /* SEF local startup. */
123 env_setargs(argc
, argv
);
128 if ((r
= netdriver_receive(ANY
, &m
, &ipc_status
)) != OK
)
129 panic("netdriver_receive failed: %d", r
);
131 if (is_ipc_notify(ipc_status
)) {
132 switch (_ENDPOINT_P(m
.m_source
)) {
135 * Under MINIX, synchronous alarms are
136 * used instead of watchdog functions.
137 * The approach is very different: MINIX
138 * VMD timeouts are handled within the
139 * kernel (the watchdog is executed by
140 * CLOCK), and notify() the driver in
141 * some cases. MINIX timeouts result in
142 * a SYN_ALARM message to the driver and
143 * thus are handled where they should be
144 * handled. Locally, watchdog functions
158 panic("illegal notify from: %d",
162 /* done, get nwe message */
168 case DL_WRITEV_S
: rl_writev_s(&m
, FALSE
); break;
169 case DL_READV_S
: rl_readv_s(&m
, FALSE
); break;
170 case DL_CONF
: rl_init(&m
); break;
171 case DL_GETSTAT_S
: rl_getstat_s(&m
); break;
173 panic("illegal message: %d", m
.m_type
);
178 /*===========================================================================*
179 * sef_local_startup *
180 *===========================================================================*/
181 static void sef_local_startup()
183 /* Register init callbacks. */
184 sef_setcb_init_fresh(sef_cb_init_fresh
);
185 sef_setcb_init_lu(sef_cb_init_fresh
);
186 sef_setcb_init_restart(sef_cb_init_fresh
);
188 /* Register live update callbacks. */
189 sef_setcb_lu_prepare(sef_cb_lu_prepare
);
190 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid
);
191 sef_setcb_lu_state_dump(sef_cb_lu_state_dump
);
193 /* Register signal callbacks. */
194 sef_setcb_signal_handler(sef_cb_signal_handler
);
196 /* Let SEF perform startup. */
200 /*===========================================================================*
201 * sef_cb_init_fresh *
202 *===========================================================================*/
203 static int sef_cb_init_fresh(int type
, sef_init_info_t
*UNUSED(info
))
205 /* Initialize the rtl8139 driver. */
208 int r
, fkeys
, sfkeys
;
211 system_hz
= sys_hz();
214 (void) env_parse("instance", "d", 0, &v
, 0, 255);
215 re_instance
= (int) v
;
218 /* Observe some function key for debug dumps. */
219 fkeys
= sfkeys
= 0; bit_set(sfkeys
, 9);
220 if ((r
=fkey_map(&fkeys
, &sfkeys
)) != OK
)
221 printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r
);
224 /* Claim buffer memory now. */
225 rl_init_buf(&re_state
);
227 /* Announce we are up! */
228 netdriver_announce();
233 /*===========================================================================*
234 * sef_cb_signal_handler *
235 *===========================================================================*/
236 static void sef_cb_signal_handler(int signo
)
240 /* Only check for termination signal, ignore anything else. */
241 if (signo
!= SIGTERM
) return;
244 if (rep
->re_mode
== REM_ENABLED
)
245 rl_outb(rep
->re_base_port
, RL_CR
, 0);
250 /*===========================================================================*
252 *===========================================================================*/
253 static void check_int_events(void)
259 if (rep
->re_mode
!= REM_ENABLED
)
261 if (!rep
->re_got_int
)
264 assert(rep
->re_flags
& REF_ENABLED
);
268 /*===========================================================================*
270 *===========================================================================*/
271 static void rtl8139_dump(m
)
272 message
*m
; /* pointer to request message */
279 if (rep
->re_mode
== REM_DISABLED
)
280 printf("Realtek RTL 8139 instance %d is disabled\n",
283 if (rep
->re_mode
!= REM_ENABLED
)
286 printf("Realtek RTL 8139 statistics of instance %d:\n", re_instance
);
288 printf("recvErr :%8ld\t", rep
->re_stat
.ets_recvErr
);
289 printf("sendErr :%8ld\t", rep
->re_stat
.ets_sendErr
);
290 printf("OVW :%8ld\n", rep
->re_stat
.ets_OVW
);
292 printf("CRCerr :%8ld\t", rep
->re_stat
.ets_CRCerr
);
293 printf("frameAll :%8ld\t", rep
->re_stat
.ets_frameAll
);
294 printf("missedP :%8ld\n", rep
->re_stat
.ets_missedP
);
296 printf("packetR :%8ld\t", rep
->re_stat
.ets_packetR
);
297 printf("packetT :%8ld\t", rep
->re_stat
.ets_packetT
);
298 printf("transDef :%8ld\n", rep
->re_stat
.ets_transDef
);
300 printf("collision :%8ld\t", rep
->re_stat
.ets_collision
);
301 printf("transAb :%8ld\t", rep
->re_stat
.ets_transAb
);
302 printf("carrSense :%8ld\n", rep
->re_stat
.ets_carrSense
);
304 printf("fifoUnder :%8ld\t", rep
->re_stat
.ets_fifoUnder
);
305 printf("fifoOver :%8ld\t", rep
->re_stat
.ets_fifoOver
);
306 printf("CDheartbeat:%8ld\n", rep
->re_stat
.ets_CDheartbeat
);
308 printf("OWC :%8ld\t", rep
->re_stat
.ets_OWC
);
310 printf("re_flags = 0x%x\n", rep
->re_flags
);
312 printf("TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
313 rl_inw(rep
->re_base_port
, RL_TSAD
),
314 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
315 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
316 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
317 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
318 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
319 rep
->re_tx_head
, rep
->re_tx_tail
,
320 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
321 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
324 /*===========================================================================*
326 *===========================================================================*/
327 static void rl_init(mp
)
330 static int first_time
= 1;
338 rl_pci_conf(); /* Configure PCI devices. */
340 /* Use a synchronous alarm instead of a watchdog timer. */
341 sys_setalarm(system_hz
, 0);
345 if (rep
->re_mode
== REM_DISABLED
)
347 /* This is the default, try to (re)locate the device. */
349 if (rep
->re_mode
== REM_DISABLED
)
351 /* Probe failed, or the device is configured off. */
352 reply_mess
.m_type
= DL_CONF_REPLY
;
353 reply_mess
.DL_STAT
= ENXIO
;
354 mess_reply(mp
, &reply_mess
);
357 if (rep
->re_mode
== REM_ENABLED
)
359 #if VERBOSE /* load silently ... can always check status later */
364 assert(rep
->re_mode
== REM_ENABLED
);
365 assert(rep
->re_flags
& REF_ENABLED
);
367 rep
->re_flags
&= ~(REF_PROMISC
| REF_MULTI
| REF_BROAD
);
369 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
370 rep
->re_flags
|= REF_PROMISC
;
371 if (mp
->DL_MODE
& DL_MULTI_REQ
)
372 rep
->re_flags
|= REF_MULTI
;
373 if (mp
->DL_MODE
& DL_BROAD_REQ
)
374 rep
->re_flags
|= REF_BROAD
;
378 reply_mess
.m_type
= DL_CONF_REPLY
;
379 reply_mess
.DL_STAT
= OK
;
380 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= rep
->re_address
;
382 mess_reply(mp
, &reply_mess
);
385 /*===========================================================================*
387 *===========================================================================*/
388 static void rl_pci_conf()
394 strlcpy(rep
->re_name
, "rtl8139#0", sizeof(rep
->re_name
));
395 rep
->re_name
[8] += re_instance
;
400 if (rl_probe(rep
, re_instance
))
404 /*===========================================================================*
406 *===========================================================================*/
407 static int rl_probe(rep
, skip
)
419 r
= pci_first_dev(&devind
, &vid
, &did
);
425 r
= pci_next_dev(&devind
, &vid
, &did
);
430 #if VERBOSE /* stay silent at startup, can always get status later */
431 dname
= pci_dev_name(vid
, did
);
433 dname
= "unknown device";
434 printf("%s: ", rep
->re_name
);
435 printf("%s (%x/%x) at %s\n", dname
, vid
, did
, pci_slot_name(devind
));
438 /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
439 bar
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
441 panic("base address is not properly configured");
443 rep
->re_base_port
= bar
;
445 ilr
= pci_attr_r8(devind
, PCI_ILR
);
449 printf("%s: using I/O address 0x%lx, IRQ %d\n",
450 rep
->re_name
, (unsigned long)bar
, ilr
);
456 /*===========================================================================*
458 *===========================================================================*/
459 static void rl_conf_hw(rep
)
462 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
464 rep
->re_mode
= REM_DISABLED
; /* Superfluous */
468 /* PCI device is present */
469 rep
->re_mode
= REM_ENABLED
;
471 if (rep
->re_mode
!= REM_ENABLED
)
474 rep
->re_flags
= REF_EMPTY
;
475 rep
->re_link_up
= -1; /* Unknown */
478 rep
->re_report_link
= 0;
480 rep
->re_need_reset
= 0;
485 rep
->re_ertxth
= RL_TSD_ERTXTH_8
;
486 rep
->re_stat
= empty_stat
;
489 /*===========================================================================*
491 *===========================================================================*/
492 static void rl_init_buf(rep
)
495 size_t rx_bufsize
, tx_bufsize
, tot_bufsize
;
500 /* Allocate receive and transmit buffers */
501 tx_bufsize
= ETH_MAX_PACK_SIZE_TAGGED
;
503 tx_bufsize
+= 4-(tx_bufsize
% 4); /* Align */
504 rx_bufsize
= RX_BUFSIZE
;
505 tot_bufsize
= N_TX_BUF
*tx_bufsize
+ rx_bufsize
;
507 if (tot_bufsize
% 4096)
508 tot_bufsize
+= 4096-(tot_bufsize
% 4096);
510 #define BUF_ALIGNMENT (64*1024)
512 if(!(mallocbuf
= alloc_contig(BUF_ALIGNMENT
+ tot_bufsize
, 0, &buf
))) {
513 panic("Couldn't allocate kernel buffer");
516 /* click-align mallocced buffer. this is what we used to get
517 * from kmalloc() too.
519 if((off
= buf
% BUF_ALIGNMENT
)) {
520 mallocbuf
+= BUF_ALIGNMENT
- off
;
521 buf
+= BUF_ALIGNMENT
- off
;
524 tell_dev((vir_bytes
)mallocbuf
, tot_bufsize
, 0, 0, 0);
526 for (i
= 0; i
<N_TX_BUF
; i
++)
528 rep
->re_tx
[i
].ret_buf
= buf
;
529 rep
->re_tx
[i
].v_ret_buf
= mallocbuf
;
531 mallocbuf
+= tx_bufsize
;
534 rep
->v_re_rx_buf
= mallocbuf
;
537 /*===========================================================================*
539 *===========================================================================*/
540 static void rl_init_hw(rep
)
545 rep
->re_flags
= REF_EMPTY
;
546 rep
->re_flags
|= REF_ENABLED
;
548 /* Set the interrupt handler. The policy is to only send HARD_INT
549 * notifications. Don't reenable interrupts automatically. The id
550 * that is passed back is the interrupt line number.
552 rep
->re_hook_id
= rep
->re_irq
;
553 if ((s
=sys_irqsetpolicy(rep
->re_irq
, 0, &rep
->re_hook_id
)) != OK
)
554 printf("RTL8139: error, couldn't set IRQ policy: %d\n", s
);
558 if ((s
=sys_irqenable(&rep
->re_hook_id
)) != OK
)
559 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
561 #if VERBOSE /* stay silent during startup, can always get status later */
563 printf("%s: model %s\n", rep
->re_name
, rep
->re_model
);
566 printf("%s: unknown model 0x%08x\n",
568 rl_inl(rep
->re_base_port
, RL_TCR
) &
569 (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
));
576 printf("%s: Ethernet address ", rep
->re_name
);
577 for (i
= 0; i
< 6; i
++)
579 printf("%x%c", rep
->re_address
.ea_addr
[i
],
585 /*===========================================================================*
587 *===========================================================================*/
588 static void rl_reset_hw(rep
)
596 port
= rep
->re_base_port
;
600 rl_outb(port
, RL_BMCR
, MII_CTRL_RST
);
601 SPIN_UNTIL(!(rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
), 1000000);
602 if (rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
)
603 panic("reset PHY failed to complete");
606 /* Reset the device */
608 printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
609 port
, rl_inb(port
, RL_CR
));
611 rl_outb(port
, RL_CR
, RL_CR_RST
);
612 SPIN_UNTIL(!(rl_inb(port
, RL_CR
) & RL_CR_RST
), 1000000);
614 printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
615 port
, rl_inb(port
, RL_CR
));
617 if (rl_inb(port
, RL_CR
) & RL_CR_RST
)
618 printf("rtl8139: reset failed to complete");
620 t
= rl_inl(port
, RL_TCR
);
621 switch(t
& (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
))
623 case RL_TCR_HWVER_RTL8139
: rep
->re_model
= "RTL8139"; break;
624 case RL_TCR_HWVER_RTL8139A
: rep
->re_model
= "RTL8139A"; break;
625 case RL_TCR_HWVER_RTL8139AG
:
626 rep
->re_model
= "RTL8139A-G / RTL8139C";
628 case RL_TCR_HWVER_RTL8139B
:
629 rep
->re_model
= "RTL8139B / RTL8130";
631 case RL_TCR_HWVER_RTL8100
: rep
->re_model
= "RTL8100"; break;
632 case RL_TCR_HWVER_RTL8100B
:
633 rep
->re_model
= "RTL8100B/RTL8139D";
635 case RL_TCR_HWVER_RTL8139CP
: rep
->re_model
= "RTL8139C+"; break;
636 case RL_TCR_HWVER_RTL8101
: rep
->re_model
= "RTL8101"; break;
643 printf("REVID: 0x%02x\n", rl_inb(port
, RL_REVID
));
648 /* Should init multicast mask */
650 08-0f R
/W MAR
[0-7] multicast
652 bus_buf
= vm_1phys2bus(rep
->re_rx_buf
);
653 rl_outl(port
, RL_RBSTART
, bus_buf
);
656 for (i
= 0; i
<N_TX_BUF
; i
++)
658 rep
->re_tx
[i
].ret_busy
= FALSE
;
659 bus_buf
= vm_1phys2bus(rep
->re_tx
[i
].ret_buf
);
660 rl_outl(port
, RL_TSAD0
+i
*4, bus_buf
);
661 t
= rl_inl(port
, RL_TSD0
+i
*4);
662 assert(t
& RL_TSD_OWN
);
669 t
= rl_inw(port
, RL_IMR
);
670 rl_outw(port
, RL_IMR
, t
| (RL_IMR_SERR
| RL_IMR_TIMEOUT
|
673 t
= rl_inw(port
, RL_IMR
);
674 rl_outw(port
, RL_IMR
, t
| (RL_IMR_FOVW
| RL_IMR_PUN
|
675 RL_IMR_RXOVW
| RL_IMR_RER
| RL_IMR_ROK
));
677 t
= rl_inw(port
, RL_IMR
);
678 rl_outw(port
, RL_IMR
, t
| (RL_IMR_TER
| RL_IMR_TOK
));
680 t
= rl_inb(port
, RL_CR
);
681 rl_outb(port
, RL_CR
, t
| RL_CR_RE
);
683 t
= rl_inb(port
, RL_CR
);
684 rl_outb(port
, RL_CR
, t
| RL_CR_TE
);
686 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
688 t
= rl_inl(port
, RL_TCR
);
689 rl_outl(port
, RL_TCR
, t
| RL_TCR_IFG_STD
);
692 /*===========================================================================*
694 *===========================================================================*/
695 static void rl_confaddr(rep
)
698 static char eakey
[]= RL_ENVVAR
"#_EA";
699 static char eafmt
[]= "x:x:x:x:x:x";
706 /* User defined ethernet address? */
707 eakey
[sizeof(RL_ENVVAR
)-1]= '0' + re_instance
;
709 port
= rep
->re_base_port
;
711 for (i
= 0; i
< 6; i
++)
713 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
715 rep
->re_address
.ea_addr
[i
]= v
;
718 if (i
!= 0 && i
!= 6) env_panic(eakey
); /* It's all or nothing */
720 /* Should update ethernet address in hardware */
723 port
= rep
->re_base_port
;
724 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_CONFIG
);
727 w
|= (rep
->re_address
.ea_addr
[i
] << (i
*8));
728 rl_outl(port
, RL_IDR
, w
);
731 w
|= (rep
->re_address
.ea_addr
[i
] << ((i
-4)*8));
732 rl_outl(port
, RL_IDR
+4, w
);
733 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_NORMAL
);
736 /* Get ethernet address */
738 rep
->re_address
.ea_addr
[i
]= rl_inb(port
, RL_IDR
+i
);
741 /*===========================================================================*
743 *===========================================================================*/
744 static void rl_rec_mode(rep
)
750 port
= rep
->re_base_port
;
751 rcr
= rl_inl(port
, RL_RCR
);
752 rcr
&= ~(RL_RCR_AB
|RL_RCR_AM
|RL_RCR_APM
|RL_RCR_AAP
);
753 if (rep
->re_flags
& REF_PROMISC
)
754 rcr
|= RL_RCR_AB
| RL_RCR_AM
| RL_RCR_AAP
;
755 if (rep
->re_flags
& REF_BROAD
)
757 if (rep
->re_flags
& REF_MULTI
)
761 rl_outl(port
, RL_RCR
, rcr
);
764 /*===========================================================================*
766 *===========================================================================*/
767 static void rl_readv_s(const message
*mp
, int from_int
)
769 int i
, j
, n
, o
, s
, s1
, count
, size
;
771 unsigned amount
, totlen
, packlen
;
772 u16_t d_start
, d_end
;
773 u32_t l
, rxstat
= 0x12345678;
781 rep
->re_client
= mp
->m_source
;
782 count
= mp
->DL_COUNT
;
784 if (rep
->re_clear_rx
)
785 goto suspend
; /* Buffer overflow */
787 assert(rep
->re_mode
== REM_ENABLED
);
788 assert(rep
->re_flags
& REF_ENABLED
);
790 port
= rep
->re_base_port
;
792 /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
794 if (!from_int
&& (rl_inb(port
, RL_CR
) & RL_CR_BUFE
))
796 /* Receive buffer is empty, suspend */
800 d_start
= rl_inw(port
, RL_CAPR
) + RL_CAPR_DATA_OFF
;
801 d_end
= rl_inw(port
, RL_CBR
) % RX_BUFSIZE
;
803 #if RX_BUFSIZE <= USHRT_MAX
804 if (d_start
>= RX_BUFSIZE
)
806 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
807 rl_inw(port
, RL_CAPR
));
808 d_start
%= RX_BUFSIZE
;
813 amount
= d_end
-d_start
;
815 amount
= d_end
+RX_BUFSIZE
- d_start
;
817 rxstat
= *(u32_t
*) (rep
->v_re_rx_buf
+ d_start
);
819 if (rep
->re_clear_rx
)
822 printf("rl_readv: late buffer overflow\n");
824 goto suspend
; /* Buffer overflow */
827 /* Should convert from little endian to host byte order */
829 if (!(rxstat
& RL_RXS_ROK
))
831 printf("rxstat = 0x%08x\n", rxstat
);
832 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%x\n",
833 d_start
, d_end
, rxstat
);
834 panic("received packet not OK");
836 totlen
= (rxstat
>> RL_RXS_LEN_S
);
837 if (totlen
< 8 || totlen
> 2*ETH_MAX_PACK_SIZE
)
839 /* Someting went wrong */
841 "rl_readv: bad length (%u) in status 0x%08x at offset 0x%x\n",
842 totlen
, rxstat
, d_start
);
844 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
845 d_start
, d_end
, totlen
, rxstat
);
850 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
851 d_start
, d_end
, totlen
, rxstat
);
854 if (totlen
+4 > amount
)
856 printf("rl_readv: packet not yet ready\n");
860 /* Should subtract the CRC */
861 packlen
= totlen
- ETH_CRC_SIZE
;
865 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
866 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
872 cps
= sys_safecopyfrom(mp
->m_source
, mp
->DL_GRANT
, iov_offset
,
873 (vir_bytes
) rep
->re_iovec_s
,
874 n
* sizeof(rep
->re_iovec_s
[0]));
876 panic("rl_readv_s: sys_safecopyfrom failed: %d",
880 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
883 if (size
+ s
> packlen
)
885 assert(packlen
> size
);
890 if (sys_umap(mp
->m_source
, D
, iovp
->iov_addr
, s
, &dst_phys
) != OK
)
891 panic("umap_local failed");
897 assert(o
< RX_BUFSIZE
);
900 if (o
+s
> RX_BUFSIZE
)
902 assert(o
<RX_BUFSIZE
);
905 cps
= sys_safecopyto(mp
->m_source
,
907 (vir_bytes
) rep
->v_re_rx_buf
+o
, s1
);
909 panic("rl_readv_s: sys_safecopyto failed: %d",
912 cps
= sys_safecopyto(mp
->m_source
,
914 (vir_bytes
) rep
->v_re_rx_buf
, s
-s1
);
916 panic("rl_readv_s: sys_safecopyto failed: %d", cps
);
921 cps
= sys_safecopyto(mp
->m_source
,
923 (vir_bytes
) rep
->v_re_rx_buf
+o
, s
);
925 panic("rl_readv_s: sys_safecopyto failed: %d", cps
);
941 if (rep
->re_clear_rx
)
943 /* For some reason the receiver FIFO is not stopped when
944 * the buffer is full.
947 printf("rl_readv: later buffer overflow\n");
949 goto suspend
; /* Buffer overflow */
952 rep
->re_stat
.ets_packetR
++;
953 rep
->re_read_s
= packlen
;
954 rep
->re_flags
= (rep
->re_flags
& ~REF_READING
) | REF_PACK_RECV
;
956 /* Avoid overflow in 16-bit computations */
959 l
= (l
+3) & ~3; /* align */
963 assert(l
< RX_BUFSIZE
);
965 rl_outw(port
, RL_CAPR
, l
-RL_CAPR_DATA_OFF
);
975 assert(rep
->re_flags
& REF_READING
);
977 /* No need to store any state */
981 rep
->re_rx_mess
= *mp
;
982 assert(!(rep
->re_flags
& REF_READING
));
983 rep
->re_flags
|= REF_READING
;
988 /*===========================================================================*
990 *===========================================================================*/
991 static void rl_writev_s(const message
*mp
, int from_int
)
993 int i
, j
, n
, s
, count
, size
;
1003 rep
->re_client
= mp
->m_source
;
1004 count
= mp
->DL_COUNT
;
1006 assert(rep
->re_mode
== REM_ENABLED
);
1007 assert(rep
->re_flags
& REF_ENABLED
);
1011 assert(rep
->re_flags
& REF_SEND_AVAIL
);
1012 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1013 rep
->re_send_int
= FALSE
;
1014 rep
->re_tx_alive
= TRUE
;
1017 tx_head
= rep
->re_tx_head
;
1018 if (rep
->re_tx
[tx_head
].ret_busy
)
1020 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1021 rep
->re_flags
|= REF_SEND_AVAIL
;
1025 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1026 assert(!(rep
->re_flags
& REF_PACK_SENT
));
1029 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1030 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1031 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1036 cps
= sys_safecopyfrom(mp
->m_source
, mp
->DL_GRANT
, iov_offset
,
1037 (vir_bytes
) rep
->re_iovec_s
,
1038 n
* sizeof(rep
->re_iovec_s
[0]));
1040 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps
);
1043 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
1046 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
) {
1047 panic("invalid packet size");
1049 cps
= sys_safecopyfrom(mp
->m_source
, iovp
->iov_grant
,
1050 0, (vir_bytes
) ret
, s
);
1052 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps
);
1058 if (size
< ETH_MIN_PACK_SIZE
)
1059 panic("invalid packet size: %d", size
);
1061 rl_outl(rep
->re_base_port
, RL_TSD0
+tx_head
*4,
1062 rep
->re_ertxth
| size
);
1063 rep
->re_tx
[tx_head
].ret_busy
= TRUE
;
1065 if (++tx_head
== N_TX_BUF
)
1067 assert(tx_head
< RL_N_TX
);
1068 rep
->re_tx_head
= tx_head
;
1070 rep
->re_flags
|= REF_PACK_SENT
;
1072 /* If the interrupt handler called, don't send a reply. The reply
1073 * will be sent after all interrupts are handled.
1082 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
1083 tx_head
, rep
->re_tx_tail
,
1084 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1085 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1086 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
1087 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
1088 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
1089 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
1090 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
1094 panic("should not be sending");
1096 rep
->re_tx_mess
= *mp
;
1100 /*===========================================================================*
1102 *===========================================================================*/
1103 static void rl_check_ints(rep
)
1107 10-1f R
/W TSD
[0-3] Transmit Status of Descriptor
[0-3]
1108 31 R CRS Carrier Sense Lost
1109 30 R TABT Transmit Abort
1110 29 R OWC Out of Window Collision
1111 27-24 R NCC
[3-0] Number of Collision Count
1113 21-16 R
/W ERTXH
[5-0] Early Tx Threshold
1114 15 R TOK Transmit OK
1115 14 R TUN Transmit FIFO Underrun
1117 12-0 R
/W SIZE Descriptor Size
1118 3e-3f R
/W ISR Interrupt Status Register
1119 6 R
/W FOVW Fx FIFO Overflow Interrupt
1120 5 R
/W PUN
/LinkChg Packet Underrun
/ Link Change Interrupt
1121 3 R
/W TER Transmit Error Interrupt
1122 2 R
/W TOK Transmit OK Interrupt
1123 3e-3f R
/W ISR Interrupt Status Register
1124 15 R
/W SERR System Error Interrupt
1125 14 R
/W TimeOut Time Out Interrupt
1126 13 R
/W LenChg Cable Length Change Interrupt
1127 3e-3f R
/W ISR Interrupt Status Register
1128 4 R
/W RXOVW Rx Buffer Overflow Interrupt
1129 1 R
/W RER Receive Error Interrupt
1130 0 R
/W ROK Receive OK Interrupt
1131 4c
-4f R
/W MPC Missed Packet Counter
1132 60-61 R TSAD Transmit Status of All Descriptors
1133 15-12 R TOK
[3-0] TOK bit of Descriptor
[3-0]
1134 11-8 R TUN
[3-0] TUN bit of Descriptor
[3-0]
1135 7-4 R TABT
[3-0] TABT bit of Descriptor
[3-0]
1136 3-0 R OWN
[3-0] OWN bit of Descriptor
[3-0]
1137 6c
-6d R DIS Disconnect Counter
1138 15-0 R DCNT Disconnect Counter
1139 6e-6f R FCSC False Carrier Sense Counter
1140 15-0 R FCSCNT False Carrier event counter
1141 72-73 R REC RX_ER Counter
1142 15-0 R RXERCNT Received packet counter
1147 re_flags
= rep
->re_flags
;
1149 if ((re_flags
& REF_READING
) &&
1150 !(rl_inb(rep
->re_base_port
, RL_CR
) & RL_CR_BUFE
))
1152 rl_readv_s(&rep
->re_rx_mess
, TRUE
/* from int */);
1154 if (rep
->re_clear_rx
)
1157 if (rep
->re_need_reset
)
1160 if (rep
->re_send_int
)
1162 rl_writev_s(&rep
->re_tx_mess
, TRUE
/* from int */);
1165 if (rep
->re_report_link
)
1166 rl_report_link(rep
);
1168 if (rep
->re_flags
& (REF_PACK_SENT
| REF_PACK_RECV
))
1172 /*===========================================================================*
1174 *===========================================================================*/
1175 static void rl_report_link(rep
)
1179 u16_t mii_ctrl
, mii_status
, mii_ana
, mii_anlpa
, mii_ane
, mii_extstat
;
1183 rep
->re_report_link
= FALSE
;
1184 port
= rep
->re_base_port
;
1185 msr
= rl_inb(port
, RL_MSR
);
1186 link_up
= !(msr
& RL_MSR_LINKB
);
1187 rep
->re_link_up
= link_up
;
1190 printf("%s: link down\n", rep
->re_name
);
1194 mii_ctrl
= rl_inw(port
, RL_BMCR
);
1195 mii_status
= rl_inw(port
, RL_BMSR
);
1196 mii_ana
= rl_inw(port
, RL_ANAR
);
1197 mii_anlpa
= rl_inw(port
, RL_ANLPAR
);
1198 mii_ane
= rl_inw(port
, RL_ANER
);
1201 if (mii_ctrl
& (MII_CTRL_LB
|MII_CTRL_PD
|MII_CTRL_ISO
))
1203 printf("%s: PHY: ", rep
->re_name
);
1205 if (mii_ctrl
& MII_CTRL_LB
)
1207 printf("loopback mode");
1210 if (mii_ctrl
& MII_CTRL_PD
)
1212 if (!f
) printf(", ");
1214 printf("powered down");
1216 if (mii_ctrl
& MII_CTRL_ISO
)
1218 if (!f
) printf(", ");
1225 if (!(mii_ctrl
& MII_CTRL_ANE
))
1227 printf("%s: manual config: ", rep
->re_name
);
1228 switch(mii_ctrl
& (MII_CTRL_SP_LSB
|MII_CTRL_SP_MSB
))
1230 case MII_CTRL_SP_10
: printf("10 Mbps"); break;
1231 case MII_CTRL_SP_100
: printf("100 Mbps"); break;
1232 case MII_CTRL_SP_1000
: printf("1000 Mbps"); break;
1233 case MII_CTRL_SP_RES
: printf("reserved speed"); break;
1235 if (mii_ctrl
& MII_CTRL_DM
)
1236 printf(", full duplex");
1238 printf(", half duplex");
1243 if (!debug
) goto resspeed
;
1245 printf("%s: ", rep
->re_name
);
1246 mii_print_stat_speed(mii_status
, mii_extstat
);
1249 if (!(mii_status
& MII_STATUS_ANC
))
1250 printf("%s: auto-negotiation not complete\n", rep
->re_name
);
1251 if (mii_status
& MII_STATUS_RF
)
1252 printf("%s: remote fault detected\n", rep
->re_name
);
1253 if (!(mii_status
& MII_STATUS_ANA
))
1255 printf("%s: local PHY has no auto-negotiation ability\n",
1258 if (!(mii_status
& MII_STATUS_LS
))
1259 printf("%s: link down\n", rep
->re_name
);
1260 if (mii_status
& MII_STATUS_JD
)
1261 printf("%s: jabber condition detected\n", rep
->re_name
);
1262 if (!(mii_status
& MII_STATUS_EC
))
1264 printf("%s: no extended register set\n", rep
->re_name
);
1267 if (!(mii_status
& MII_STATUS_ANC
))
1270 printf("%s: local cap.: ", rep
->re_name
);
1271 mii_print_techab(mii_ana
);
1274 if (mii_ane
& MII_ANE_PDF
)
1275 printf("%s: parallel detection fault\n", rep
->re_name
);
1276 if (!(mii_ane
& MII_ANE_LPANA
))
1278 printf("%s: link-partner does not support auto-negotiation\n",
1283 printf("%s: remote cap.: ", rep
->re_name
);
1284 mii_print_techab(mii_anlpa
);
1288 printf("%s: ", rep
->re_name
);
1289 printf("link up at %d Mbps, ", (msr
& RL_MSR_SPEED_10
) ? 10 : 100);
1290 printf("%s duplex\n", ((mii_ctrl
& MII_CTRL_DM
) ? "full" : "half"));
1294 static void mii_print_techab(u16_t techab
)
1297 if ((techab
& MII_ANA_SEL_M
) != MII_ANA_SEL_802_3
)
1299 printf("strange selector 0x%x, value 0x%x",
1300 techab
& MII_ANA_SEL_M
,
1301 (techab
& MII_ANA_TAF_M
) >> MII_ANA_TAF_S
);
1305 if (techab
& (MII_ANA_100T4
| MII_ANA_100TXFD
| MII_ANA_100TXHD
))
1307 printf("100 Mbps: ");
1310 if (techab
& MII_ANA_100T4
)
1315 if (techab
& (MII_ANA_100TXFD
| MII_ANA_100TXHD
))
1321 switch(techab
& (MII_ANA_100TXFD
|MII_ANA_100TXHD
))
1323 case MII_ANA_100TXFD
: printf("FD"); break;
1324 case MII_ANA_100TXHD
: printf("HD"); break;
1325 default: printf("FD/HD"); break;
1329 if (techab
& (MII_ANA_10TFD
| MII_ANA_10THD
))
1333 printf("10 Mbps: ");
1336 switch(techab
& (MII_ANA_10TFD
|MII_ANA_10THD
))
1338 case MII_ANA_10TFD
: printf("FD"); break;
1339 case MII_ANA_10THD
: printf("HD"); break;
1340 default: printf("FD/HD"); break;
1343 if (techab
& MII_ANA_PAUSE_SYM
)
1348 printf("pause(SYM)");
1350 if (techab
& MII_ANA_PAUSE_ASYM
)
1355 printf("pause(ASYM)");
1357 if (techab
& MII_ANA_TAF_RES
)
1362 printf("0x%x", (techab
& MII_ANA_TAF_RES
) >> MII_ANA_TAF_S
);
1366 static void mii_print_stat_speed(u16_t stat
, u16_t extstat
)
1370 if (stat
& MII_STATUS_EXT_STAT
)
1372 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
|
1373 MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
1375 printf("1000 Mbps: ");
1378 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
))
1383 (MII_ESTAT_1000XFD
|MII_ESTAT_1000XHD
))
1385 case MII_ESTAT_1000XFD
: printf("FD"); break;
1386 case MII_ESTAT_1000XHD
: printf("HD"); break;
1387 default: printf("FD/HD"); break;
1390 if (extstat
& (MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
1397 (MII_ESTAT_1000TFD
|MII_ESTAT_1000THD
))
1399 case MII_ESTAT_1000TFD
: printf("FD"); break;
1400 case MII_ESTAT_1000THD
: printf("HD"); break;
1401 default: printf("FD/HD"); break;
1406 if (stat
& (MII_STATUS_100T4
|
1407 MII_STATUS_100XFD
| MII_STATUS_100XHD
|
1408 MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
1413 printf("100 Mbps: ");
1415 if (stat
& MII_STATUS_100T4
)
1420 if (stat
& (MII_STATUS_100XFD
| MII_STATUS_100XHD
))
1426 switch(stat
& (MII_STATUS_100XFD
|MII_STATUS_100XHD
))
1428 case MII_STATUS_100XFD
: printf("FD"); break;
1429 case MII_STATUS_100XHD
: printf("HD"); break;
1430 default: printf("FD/HD"); break;
1433 if (stat
& (MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
1439 switch(stat
& (MII_STATUS_100T2FD
|MII_STATUS_100T2HD
))
1441 case MII_STATUS_100T2FD
: printf("FD"); break;
1442 case MII_STATUS_100T2HD
: printf("HD"); break;
1443 default: printf("FD/HD"); break;
1447 if (stat
& (MII_STATUS_10FD
| MII_STATUS_10HD
))
1451 printf("10 Mbps: ");
1454 switch(stat
& (MII_STATUS_10FD
|MII_STATUS_10HD
))
1456 case MII_STATUS_10FD
: printf("FD"); break;
1457 case MII_STATUS_10HD
: printf("HD"); break;
1458 default: printf("FD/HD"); break;
1463 /*===========================================================================*
1465 *===========================================================================*/
1466 static void rl_clear_rx(re_t
*rep
)
1471 rep
->re_clear_rx
= FALSE
;
1472 port
= rep
->re_base_port
;
1474 /* Reset the receiver */
1475 cr
= rl_inb(port
, RL_CR
);
1477 rl_outb(port
, RL_CR
, cr
);
1478 SPIN_UNTIL(!(rl_inb(port
, RL_CR
) & RL_CR_RE
), 1000000);
1479 if (rl_inb(port
, RL_CR
) & RL_CR_RE
)
1480 panic("cannot disable receiver");
1483 printf("RBSTART = 0x%08x\n", rl_inl(port
, RL_RBSTART
));
1484 printf("CAPR = 0x%04x\n", rl_inw(port
, RL_CAPR
));
1485 printf("CBR = 0x%04x\n", rl_inw(port
, RL_CBR
));
1486 printf("RCR = 0x%08x\n", rl_inl(port
, RL_RCR
));
1489 rl_outb(port
, RL_CR
, cr
| RL_CR_RE
);
1491 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
1495 rep
->re_stat
.ets_missedP
++;
1498 /*===========================================================================*
1500 *===========================================================================*/
1501 static void rl_do_reset(rep
)
1504 rep
->re_need_reset
= FALSE
;
1509 if (rep
->re_flags
& REF_SEND_AVAIL
)
1511 rep
->re_tx
[rep
->re_tx_head
].ret_busy
= FALSE
;
1512 rep
->re_send_int
= TRUE
;
1516 /*===========================================================================*
1518 *===========================================================================*/
1519 static void rl_getstat_s(mp
)
1528 assert(rep
->re_mode
== REM_ENABLED
);
1529 assert(rep
->re_flags
& REF_ENABLED
);
1531 stats
= rep
->re_stat
;
1533 r
= sys_safecopyto(mp
->m_source
, mp
->DL_GRANT
, 0,
1534 (vir_bytes
) &stats
, sizeof(stats
));
1536 panic("rl_getstat_s: sys_safecopyto failed: %d", r
);
1538 mp
->m_type
= DL_STAT_REPLY
;
1539 r
= send(mp
->m_source
, mp
);
1541 panic("rl_getstat_s: send failed: %d", r
);
1544 /*===========================================================================*
1546 *===========================================================================*/
1547 static void reply(rep
)
1555 if (rep
->re_flags
& REF_PACK_SENT
)
1556 flags
|= DL_PACK_SEND
;
1557 if (rep
->re_flags
& REF_PACK_RECV
)
1558 flags
|= DL_PACK_RECV
;
1560 reply
.m_type
= DL_TASK_REPLY
;
1561 reply
.DL_FLAGS
= flags
;
1562 reply
.DL_COUNT
= rep
->re_read_s
;
1564 r
= send(rep
->re_client
, &reply
);
1567 printf("RTL8139 tried sending to %d, type %d\n",
1568 rep
->re_client
, reply
.m_type
);
1569 panic("send failed: %d", r
);
1573 rep
->re_flags
&= ~(REF_PACK_SENT
| REF_PACK_RECV
);
1576 /*===========================================================================*
1578 *===========================================================================*/
1579 static void mess_reply(req
, reply_mess
)
1581 message
*reply_mess
;
1583 if (send(req
->m_source
, reply_mess
) != OK
)
1584 panic("unable to mess_reply");
1588 /*===========================================================================*
1590 *===========================================================================*/
1591 static void dump_phy(rep
)
1597 port
= rep
->re_base_port
;
1599 t
= rl_inb(port
, RL_MSR
);
1600 printf("MSR: 0x%02lx\n", t
);
1601 if (t
& RL_MSR_SPEED_10
)
1602 printf("\t10 Mbps\n");
1603 if (t
& RL_MSR_LINKB
)
1604 printf("\tLink failed\n");
1606 t
= rl_inb(port
, RL_CONFIG1
);
1607 printf("CONFIG1: 0x%02lx\n", t
);
1609 t
= rl_inb(port
, RL_CONFIG3
);
1610 printf("CONFIG3: 0x%02lx\n", t
);
1612 t
= rl_inb(port
, RL_CONFIG4
);
1613 printf("CONFIG4: 0x%02lx\n", t
);
1615 t
= rl_inw(port
, RL_BMCR
);
1616 printf("BMCR (MII_CTRL): 0x%04lx\n", t
);
1618 t
= rl_inw(port
, RL_BMSR
);
1620 if (t
& MII_STATUS_100T4
)
1621 printf(" 100Base-T4");
1622 if (t
& MII_STATUS_100XFD
)
1623 printf(" 100Base-X-FD");
1624 if (t
& MII_STATUS_100XHD
)
1625 printf(" 100Base-X-HD");
1626 if (t
& MII_STATUS_10FD
)
1627 printf(" 10Mbps-FD");
1628 if (t
& MII_STATUS_10HD
)
1629 printf(" 10Mbps-HD");
1630 if (t
& MII_STATUS_100T2FD
)
1631 printf(" 100Base-T2-FD");
1632 if (t
& MII_STATUS_100T2HD
)
1633 printf(" 100Base-T2-HD");
1634 if (t
& MII_STATUS_EXT_STAT
)
1635 printf(" Ext-stat");
1636 if (t
& MII_STATUS_RES
)
1637 printf(" res-0x%lx", t
& MII_STATUS_RES
);
1638 if (t
& MII_STATUS_MFPS
)
1640 if (t
& MII_STATUS_ANC
)
1642 if (t
& MII_STATUS_RF
)
1643 printf(" remote-fault");
1644 if (t
& MII_STATUS_ANA
)
1646 if (t
& MII_STATUS_LS
)
1648 if (t
& MII_STATUS_JD
)
1650 if (t
& MII_STATUS_EC
)
1651 printf(" Extended-capability");
1654 t
= rl_inw(port
, RL_ANAR
);
1655 printf("ANAR (MII_ANA): 0x%04lx\n", t
);
1657 t
= rl_inw(port
, RL_ANLPAR
);
1658 printf("ANLPAR: 0x%04lx\n", t
);
1660 t
= rl_inw(port
, RL_ANER
);
1661 printf("ANER (MII_ANE): ");
1662 if (t
& MII_ANE_RES
)
1663 printf(" res-0x%lx", t
& MII_ANE_RES
);
1664 if (t
& MII_ANE_PDF
)
1665 printf(" Par-Detect-Fault");
1666 if (t
& MII_ANE_LPNPA
)
1667 printf(" LP-Next-Page-Able");
1668 if (t
& MII_ANE_NPA
)
1669 printf(" Loc-Next-Page-Able");
1671 printf(" Page-Received");
1672 if (t
& MII_ANE_LPANA
)
1673 printf(" LP-Auto-Neg-Able");
1676 t
= rl_inw(port
, RL_NWAYTR
);
1677 printf("NWAYTR: 0x%04lx\n", t
);
1678 t
= rl_inw(port
, RL_CSCR
);
1679 printf("CSCR: 0x%04lx\n", t
);
1681 t
= rl_inb(port
, RL_CONFIG5
);
1682 printf("CONFIG5: 0x%02lx\n", t
);
1686 /*===========================================================================*
1688 *===========================================================================*/
1689 static void do_hard_int(void)
1693 /* Run interrupt handler at driver level. */
1694 rl_handler(&re_state
);
1696 /* Reenable interrupts for this hook. */
1697 if ((s
=sys_irqenable(&re_state
.re_hook_id
)) != OK
)
1698 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
1701 /*===========================================================================*
1703 *===========================================================================*/
1704 static int rl_handler(re_t
*rep
)
1706 int i
, port
, tx_head
, tx_tail
, link_up
;
1708 u32_t tsd
, tcr
, ertxth
;
1712 int_event_check
= FALSE
; /* disable check by default */
1714 port
= rep
->re_base_port
;
1717 isr
= rl_inw(port
, RL_ISR
);
1718 rl_outw(port
, RL_ISR
, isr
);
1720 if (isr
& RL_IMR_FOVW
)
1722 isr
&= ~RL_IMR_FOVW
;
1723 /* Should do anything? */
1725 rep
->re_stat
.ets_fifoOver
++;
1727 if (isr
& RL_IMR_PUN
)
1731 /* Either the link status changed or there was a TX fifo
1734 link_up
= !(rl_inb(port
, RL_MSR
) & RL_MSR_LINKB
);
1735 if (link_up
!= rep
->re_link_up
)
1737 rep
->re_report_link
= TRUE
;
1738 rep
->re_got_int
= TRUE
;
1739 int_event_check
= TRUE
;
1742 if (isr
& RL_IMR_RXOVW
)
1744 isr
&= ~RL_IMR_RXOVW
;
1746 /* Clear the receive buffer */
1747 rep
->re_clear_rx
= TRUE
;
1748 rep
->re_got_int
= TRUE
;
1749 int_event_check
= TRUE
;
1752 if (isr
& (RL_ISR_RER
| RL_ISR_ROK
))
1754 isr
&= ~(RL_ISR_RER
| RL_ISR_ROK
);
1756 if (!rep
->re_got_int
&& (rep
->re_flags
& REF_READING
))
1758 rep
->re_got_int
= TRUE
;
1759 int_event_check
= TRUE
;
1763 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) &&
1764 (rep
->re_flags
& REF_SEND_AVAIL
) &&
1765 (rep
->re_tx
[0].ret_busy
|| rep
->re_tx
[1].ret_busy
||
1766 rep
->re_tx
[2].ret_busy
|| rep
->re_tx
[3].ret_busy
))
1770 "rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
1771 rep
->re_tx_head
, rep
->re_tx_tail
,
1772 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1773 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1775 "rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
1776 rl_inw(port
, RL_TSAD
),
1777 rl_inl(port
, RL_TSD0
+0*4),
1778 rl_inl(port
, RL_TSD0
+1*4),
1779 rl_inl(port
, RL_TSD0
+2*4),
1780 rl_inl(port
, RL_TSD0
+3*4));
1783 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) || 1)
1785 isr
&= ~(RL_ISR_TER
| RL_ISR_TOK
);
1787 tsad
= rl_inw(port
, RL_TSAD
);
1788 if (tsad
& (RL_TSAD_TABT0
|RL_TSAD_TABT1
|
1789 RL_TSAD_TABT2
|RL_TSAD_TABT3
))
1792 /* Do we need a watch dog? */
1793 /* Just reset the whole chip */
1794 rep
->re_need_reset
= TRUE
;
1795 rep
->re_got_int
= TRUE
;
1796 int_event_check
= TRUE
;
1798 /* Reset transmitter */
1799 rep
->re_stat
.ets_transAb
++;
1801 cr
= rl_inb(port
, RL_CR
);
1803 rl_outb(port
, RL_CR
, cr
);
1804 SPIN_UNTIL(!(rl_inb(port
, RL_CR
) & RL_CR_TE
), 1000000);
1805 if (rl_inb(port
, RL_CR
) & RL_CR_TE
) {
1806 panic("cannot disable transmitter");
1808 rl_outb(port
, RL_CR
, cr
| RL_CR_TE
);
1810 tcr
= rl_inl(port
, RL_TCR
);
1811 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_IFG_STD
);
1813 printf("rl_handler: reset after abort\n");
1815 if (rep
->re_flags
& REF_SEND_AVAIL
)
1817 printf("rl_handler: REF_SEND_AVAIL\n");
1818 rep
->re_send_int
= TRUE
;
1819 rep
->re_got_int
= TRUE
;
1820 int_event_check
= TRUE
;
1822 for (i
= 0; i
< N_TX_BUF
; i
++)
1823 rep
->re_tx
[i
].ret_busy
= FALSE
;
1826 printf("rl_handler, TABT, tasd = 0x%04x\n",
1829 /* Find the aborted transmit request */
1830 for (i
= 0; i
< N_TX_BUF
; i
++)
1832 tsd
= rl_inl(port
, RL_TSD0
+i
*4);
1833 if (tsd
& RL_TSD_TABT
)
1839 "rl_handler: can't find aborted TX req.\n");
1843 printf("TSD%d = 0x%04x\n", i
, tsd
);
1845 /* Set head and tail to this buffer */
1846 rep
->re_tx_head
= rep
->re_tx_tail
= i
;
1849 /* Aborted transmission, just kick the device
1850 * and be done with it.
1852 rep
->re_stat
.ets_transAb
++;
1853 tcr
= rl_inl(port
, RL_TCR
);
1854 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
1858 /* Transmit completed */
1859 tx_head
= rep
->re_tx_head
;
1860 tx_tail
= rep
->re_tx_tail
;
1861 for (i
= 0; i
< 2*N_TX_BUF
; i
++)
1863 if (!rep
->re_tx
[tx_tail
].ret_busy
)
1865 /* Strange, this buffer is not in-use.
1866 * Increment tx_tail until tx_head is
1867 * reached (or until we find a buffer that
1870 if (tx_tail
== tx_head
)
1872 if (++tx_tail
>= N_TX_BUF
)
1874 assert(tx_tail
< RL_N_TX
);
1875 rep
->re_tx_tail
= tx_tail
;
1878 tsd
= rl_inl(port
, RL_TSD0
+tx_tail
*4);
1879 if (!(tsd
& RL_TSD_OWN
))
1881 /* Buffer is not yet ready */
1885 /* Should collect statistics */
1886 if (tsd
& RL_TSD_CRS
)
1887 rep
->re_stat
.ets_carrSense
++;
1888 if (tsd
& RL_TSD_TABT
)
1890 printf("rl_handler, TABT, TSD%d = 0x%04x\n",
1892 assert(0); /* CLRABT is not all that
1893 * effective, why not?
1895 rep
->re_stat
.ets_transAb
++;
1896 tcr
= rl_inl(port
, RL_TCR
);
1897 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
1899 if (tsd
& RL_TSD_OWC
)
1900 rep
->re_stat
.ets_OWC
++;
1901 if (tsd
& RL_TSD_CDH
)
1902 rep
->re_stat
.ets_CDheartbeat
++;
1904 /* What about collisions? */
1905 if (tsd
& RL_TSD_TOK
)
1906 rep
->re_stat
.ets_packetT
++;
1908 rep
->re_stat
.ets_sendErr
++;
1909 if (tsd
& RL_TSD_TUN
)
1911 rep
->re_stat
.ets_fifoUnder
++;
1913 /* Increase ERTXTH */
1914 ertxth
= tsd
+ (1 << RL_TSD_ERTXTH_S
);
1915 ertxth
&= RL_TSD_ERTXTH_M
;
1916 if (debug
&& ertxth
> rep
->re_ertxth
)
1918 printf("%s: new ertxth: %d bytes\n",
1920 (ertxth
>> RL_TSD_ERTXTH_S
) *
1922 rep
->re_ertxth
= ertxth
;
1925 rep
->re_tx
[tx_tail
].ret_busy
= FALSE
;
1928 if (rep
->re_flags
& REF_SEND_AVAIL
)
1930 printf("TSD%d: %08lx\n", tx_tail
, tsd
);
1932 "rl_handler: head %d, tail %d, busy: %d %d %d %d\n",
1934 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1935 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1939 if (++tx_tail
>= N_TX_BUF
)
1941 assert(tx_tail
< RL_N_TX
);
1942 rep
->re_tx_tail
= tx_tail
;
1944 if (rep
->re_flags
& REF_SEND_AVAIL
)
1947 printf("rl_handler: REF_SEND_AVAIL\n");
1949 rep
->re_send_int
= TRUE
;
1950 if (!rep
->re_got_int
)
1952 rep
->re_got_int
= TRUE
;
1953 int_event_check
= TRUE
;
1957 assert(i
< 2*N_TX_BUF
);
1961 printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
1968 /*===========================================================================*
1970 *===========================================================================*/
1971 static void rl_watchdog_f(tp
)
1975 /* Use a synchronous alarm instead of a watchdog timer. */
1976 sys_setalarm(system_hz
, 0);
1980 if (rep
->re_mode
!= REM_ENABLED
)
1982 if (!(rep
->re_flags
& REF_SEND_AVAIL
))
1984 /* Assume that an idle system is alive */
1985 rep
->re_tx_alive
= TRUE
;
1988 if (rep
->re_tx_alive
)
1990 rep
->re_tx_alive
= FALSE
;
1993 printf("rl_watchdog_f: resetting instance %d\n", re_instance
);
1994 printf("TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
1995 rl_inw(rep
->re_base_port
, RL_TSAD
),
1996 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
1997 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
1998 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
1999 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
2000 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
2001 rep
->re_tx_head
, rep
->re_tx_tail
,
2002 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2003 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2004 rep
->re_need_reset
= TRUE
;
2005 rep
->re_got_int
= TRUE
;
2012 static void rtl_init(struct dpeth
*dep
);
2013 static u16_t
get_ee_word(dpeth_t
*dep
, int a
);
2014 static void ee_wen(dpeth_t
*dep
);
2015 static void set_ee_word(dpeth_t
*dep
, int a
, u16_t w
);
2016 static void ee_wds(dpeth_t
*dep
);
2018 static void rtl_init(dep
)
2021 u8_t reg_a
, reg_b
, cr
, config0
, config2
, config3
;
2025 printf("rtl_init called\n");
2029 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2030 reg_a
= inb_reg0(dep
, DP_DUM1
);
2031 reg_b
= inb_reg0(dep
, DP_DUM2
);
2033 printf("rtl_init: '%c', '%c'\n", reg_a
, reg_b
);
2035 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2036 config0
= inb_reg3(dep
, 3);
2037 config2
= inb_reg3(dep
, 5);
2038 config3
= inb_reg3(dep
, 6);
2039 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2041 printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
2042 config0
, config2
, config3
);
2044 if (0 == sys_getkenv("RTL8029FD",9+1, val
, sizeof(val
)))
2046 printf("rtl_init: setting full-duplex mode\n");
2047 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2049 cr
= inb_reg3(dep
, 1);
2050 outb_reg3(dep
, 1, cr
| 0xc0);
2052 outb_reg3(dep
, 6, config3
| 0x40);
2053 config3
= inb_reg3(dep
, 6);
2055 config2
= inb_reg3(dep
, 5);
2056 outb_reg3(dep
, 5, config2
| 0x20);
2057 config2
= inb_reg3(dep
, 5);
2059 outb_reg3(dep
, 1, cr
);
2061 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2063 printf("rtl_init: config 2 = %x\n", config2
);
2064 printf("rtl_init: config 3 = %x\n", config3
);
2067 for (i
= 0; i
<64; i
++)
2068 printf("%x ", get_ee_word(dep
, i
));
2071 if (0 == sys_getkenv("RTL8029MN",9+1, val
, sizeof(val
)))
2075 set_ee_word(dep
, 0x78/2, 0x10ec);
2076 set_ee_word(dep
, 0x7A/2, 0x8029);
2077 set_ee_word(dep
, 0x7C/2, 0x10ec);
2078 set_ee_word(dep
, 0x7E/2, 0x8029);
2082 assert(get_ee_word(dep
, 0x78/2) == 0x10ec);
2083 assert(get_ee_word(dep
, 0x7A/2) == 0x8029);
2084 assert(get_ee_word(dep
, 0x7C/2) == 0x10ec);
2085 assert(get_ee_word(dep
, 0x7E/2) == 0x8029);
2088 if (0 == sys_getkenv("RTL8029XXX",10+1, val
, sizeof(val
)))
2092 set_ee_word(dep
, 0x76/2, 0x8029);
2096 assert(get_ee_word(dep
, 0x76/2) == 0x8029);
2100 static u16_t
get_ee_word(dep
, a
)
2107 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2109 /* Switch to 9346 mode and enable CS */
2110 outb_reg3(dep
, 1, 0x80 | 0x8);
2112 cmd
= 0x180 | (a
& 0x3f); /* 1 1 0 a5 a4 a3 a2 a1 a0 */
2113 for (i
= 8; i
>= 0; i
--)
2115 b
= (cmd
& (1 << i
));
2118 /* Cmd goes out on the rising edge of the clock */
2119 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2120 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2122 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2125 for (i
= 0; i
<16; i
++)
2129 /* Data is shifted out on the rising edge. Read at the
2132 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4);
2133 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2134 b
= inb_reg3(dep
, 1);
2138 outb_reg3(dep
, 1, 0x80); /* drop CS */
2139 outb_reg3(dep
, 1, 0x00); /* back to normal */
2140 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
2145 static void ee_wen(dep
)
2151 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2153 /* Switch to 9346 mode and enable CS */
2154 outb_reg3(dep
, 1, 0x80 | 0x8);
2156 cmd
= 0x130; /* 1 0 0 1 1 x x x x */
2157 for (i
= 8; i
>= 0; i
--)
2159 b
= (cmd
& (1 << i
));
2162 /* Cmd goes out on the rising edge of the clock */
2163 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2164 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2166 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2167 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2168 /* micro_delay(1); */ /* Is this required? */
2171 static void set_ee_word(dpeth_t
*dep
, int a
, u16_t w
)
2178 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
2180 cmd
= 0x140 | (a
& 0x3f); /* 1 0 1 a5 a4 a3 a2 a1 a0 */
2181 for (i
= 8; i
>= 0; i
--)
2183 b
= (cmd
& (1 << i
));
2186 /* Cmd goes out on the rising edge of the clock */
2187 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2188 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2190 for (i
= 15; i
>= 0; i
--)
2195 /* Cmd goes out on the rising edge of the clock */
2196 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2197 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2199 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of data */
2200 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2201 /* micro_delay(1); */ /* Is this required? */
2202 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
2203 SPIN_UNTIL(inb_reg3(dep
, 1) & 1, 10000);
2204 if (!(inb_reg3(dep
, 1) & 1))
2205 panic("device remains busy");
2208 static void ee_wds(dep
)
2214 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2216 /* Switch to 9346 mode and enable CS */
2217 outb_reg3(dep
, 1, 0x80 | 0x8);
2219 cmd
= 0x100; /* 1 0 0 0 0 x x x x */
2220 for (i
= 8; i
>= 0; i
--)
2222 b
= (cmd
& (1 << i
));
2225 /* Cmd goes out on the rising edge of the clock */
2226 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2227 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2229 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2230 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2231 outb_reg3(dep
, 1, 0x00); /* back to normal */
2232 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
2236 static void tell_dev(buf
, size
, pci_bus
, pci_dev
, pci_func
)
2247 r
= ds_retrieve_label_endpt("amddev", &dev_e
);
2252 "rtl8139`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n",
2258 m
.m_type
= IOMMU_MAP
;
2265 r
= sendrec(dev_e
, &m
);
2268 printf("rtl8139`tell_dev: sendrec to %d failed: %d\n",
2274 printf("rtl8139`tell_dev: dma map request failed: %d\n",
2281 * $PchId: rtl8139.c,v 1.3 2003/09/11 14:15:15 philip Exp $