4 * This file contains a ethernet device driver for Realtek rtl8139 based
7 * The valid messages and their parameters are:
9 * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
10 * |------------+----------+---------+----------+---------+---------+---------|
11 * | HARDINT | | | | | | |
12 * |------------|----------|---------|----------|---------|---------|---------|
13 * | DL_WRITE | port nr | proc nr | count | mode | address | |
14 * |------------|----------|---------|----------|---------|---------|---------|
15 * | DL_WRITEV | port nr | proc nr | count | mode | address | |
16 * |------------|----------|---------|----------|---------|---------|---------|
17 * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
18 * |------------|----------|---------|----------|---------|---------|---------|
19 * | DL_READ | port nr | proc nr | count | | address | |
20 * |------------|----------|---------|----------|---------|---------|---------|
21 * | DL_READV | port nr | proc nr | count | | address | |
22 * |------------|----------|---------|----------|---------|---------|---------|
23 * | DL_READV_S | port nr | proc nr | count | | | grant |
24 * |------------|----------|---------|----------|---------|---------|---------|
25 * | DL_CONF | port nr | proc nr | | mode | address | |
26 * |------------|----------|---------|----------|---------|---------|---------|
27 * | DL_GETSTAT | port nr | proc nr | | | address | |
28 * |------------|----------|---------|----------|---------|---------|---------|
29 * |DL_GETSTAT_S| port nr | proc nr | | | | grant |
30 * |------------|----------|---------|----------|---------|---------|---------|
31 * | DL_STOP | port_nr | | | | | |
32 * |------------|----------|---------|----------|---------|---------|---------|
34 * The messages sent are:
36 * m-type DL_POR T DL_PROC DL_COUNT DL_STAT DL_CLCK
37 * |------------|----------|---------|----------|---------|---------|
38 * |DL_TASK_REPL| port nr | proc nr | rd-count | err|stat| clock |
39 * |------------|----------|---------|----------|---------|---------|
41 * m_type m3_i1 m3_i2 m3_ca1
42 * |------------+---------+-----------+---------------|
43 * |DL_CONF_REPL| port nr | last port | ethernet addr |
44 * |------------|---------|-----------|---------------|
46 * Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
48 * Aug 15, 2004 sync alarms replace watchdogs timers (Jorrit N. Herder)
49 * May 02, 2004 flag alarms replace micro_elapsed() (Jorrit N. Herder)
53 #include "../drivers.h"
59 #include <minix/com.h>
60 #include <minix/keymap.h>
61 #include <minix/syslib.h>
62 #include <minix/type.h>
63 #include <minix/sysutil.h>
66 #include <net/gen/ether.h>
67 #include <net/gen/eth_io.h>
70 #include <sys/types.h>
74 #include <sys/ioc_memory.h>
75 #include "../../kernel/const.h"
76 #include "../../kernel/config.h"
77 #include "../../kernel/type.h"
79 #define tmra_ut timer_t
80 #define tmra_inittimer(tp) tmr_inittimer(tp)
81 #define Proc_number(p) proc_number(p)
83 #define printW() ((void)0)
84 #define vm_1phys2bus(p) (p)
86 #define VERBOSE 1 /* display message during init */
90 #define RX_BUFSIZE RL_RCR_RBLEN_64K_SIZE
91 #define RX_BUFBITS RL_RCR_RBLEN_64K
92 #define N_TX_BUF RL_N_TX
94 #define RE_PORT_NR 1 /* Minix */
96 /* I/O vectors are handled IOVEC_NR entries at a time. */
100 #define RL_ENVVAR "RTLETH"
102 PRIVATE
struct pcitab
109 { 0x10ec, 0x8139, 0 }, /* Realtek RTL8139 */
111 /* Alternative IDs */
112 { 0x02ac, 0x1012, 0 }, /* SpeedStream 1012 PCMCIA 10/100 */
113 { 0x1065, 0x8139, 0 }, /* Texas Microsystems 8139C Network Card */
114 { 0x1113, 0x1211, 0 }, /* Accton MPX5030 or SMC1211TX EZCard 10/100 */
115 { 0x1186, 0x1300, 0 }, /* D-Link DFE530TX+/DFE538TX */
116 { 0x1186, 0x1340, 0 }, /* D-Link DFE690TXD */
117 { 0x11db, 0x1234, 0 }, /* Sega Dreamcast HIT-400 */
118 { 0x1259, 0xa117, 0 }, /* Allied Telesyn 8139 */
119 { 0x1259, 0xa11e, 0 }, /* Allied Telesyn 8139 */
120 { 0x126c, 0x1211, 0 }, /* Northern Telecom 10/100BaseTX*/
121 { 0x13d1, 0xab06, 0 }, /* AboCom FE2000VX */
122 { 0x1432, 0x9130, 0 }, /* Edimax Computer Co. RTL81xx */
123 { 0x14ea, 0xab06, 0 }, /* Planex FNW-3603-TX */
124 { 0x14ea, 0xab07, 0 }, /* Planex FNW-3800-TX */
125 { 0x1500, 0x1360, 0 }, /* Delta Electronics RealTek Ethernet */
126 { 0x1743, 0x8139, 0 }, /* Peppercon AG 8139 ROL/F-100 */
127 { 0x4033, 0x1360, 0 }, /* Addtron Technology 8139 */
129 { 0x0000, 0x0000, 0 }
149 phys_bytes re_rx_buf
;
162 u32_t re_ertxth
; /* Early Tx Threshold */
165 int re_seen
; /* TRUE iff device available */
171 int re_hook_id
; /* IRQ hook id at kernel */
173 ether_addr_t re_address
;
176 char re_name
[sizeof("rtl8139#n")];
177 iovec_t re_iovec
[IOVEC_NR
];
178 iovec_s_t re_iovec_s
[IOVEC_NR
];
182 #define REM_DISABLED 0x0
183 #define REM_ENABLED 0x1
185 #define REF_PACK_SENT 0x001
186 #define REF_PACK_RECV 0x002
187 #define REF_SEND_AVAIL 0x004
188 #define REF_READING 0x010
189 #define REF_EMPTY 0x000
190 #define REF_PROMISC 0x040
191 #define REF_MULTI 0x080
192 #define REF_BROAD 0x100
193 #define REF_ENABLED 0x200
195 static re_t re_table
[RE_PORT_NR
];
197 static u16_t eth_ign_proto
;
198 static tmra_ut rl_watchdog
;
200 FORWARD
_PROTOTYPE( unsigned my_inb
, (U16_t port
) );
201 FORWARD
_PROTOTYPE( unsigned my_inw
, (U16_t port
) );
202 FORWARD
_PROTOTYPE( unsigned my_inl
, (U16_t port
) );
203 static unsigned my_inb(U16_t port
) {
206 if ((s
=sys_inb(port
, &value
)) !=OK
)
207 printf("RTL8139: warning, sys_inb failed: %d\n", s
);
210 static unsigned my_inw(U16_t port
) {
213 if ((s
=sys_inw(port
, &value
)) !=OK
)
214 printf("RTL8139: warning, sys_inw failed: %d\n", s
);
217 static unsigned my_inl(U16_t port
) {
220 if ((s
=sys_inl(port
, &value
)) !=OK
)
221 printf("RTL8139: warning, sys_inl failed: %d\n", s
);
224 #define rl_inb(port, offset) (my_inb((port) + (offset)))
225 #define rl_inw(port, offset) (my_inw((port) + (offset)))
226 #define rl_inl(port, offset) (my_inl((port) + (offset)))
228 FORWARD
_PROTOTYPE( void my_outb
, (U16_t port
, U8_t value
) );
229 FORWARD
_PROTOTYPE( void my_outw
, (U16_t port
, U16_t value
) );
230 FORWARD
_PROTOTYPE( void my_outl
, (U16_t port
, U32_t value
) );
231 static void my_outb(U16_t port
, U8_t value
) {
233 if ((s
=sys_outb(port
, value
)) !=OK
)
234 printf("RTL8139: warning, sys_outb failed: %d\n", s
);
236 static void my_outw(U16_t port
, U16_t value
) {
238 if ((s
=sys_outw(port
, value
)) !=OK
)
239 printf("RTL8139: warning, sys_outw failed: %d\n", s
);
241 static void my_outl(U16_t port
, U32_t value
) {
243 if ((s
=sys_outl(port
, value
)) !=OK
)
244 printf("RTL8139: warning, sys_outl failed: %d\n", s
);
246 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value)))
247 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
248 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
250 _PROTOTYPE( static void sig_handler
, (void) );
251 _PROTOTYPE( static void rl_init
, (message
*mp
) );
252 _PROTOTYPE( static void rl_pci_conf
, (void) );
253 _PROTOTYPE( static int rl_probe
, (re_t
*rep
) );
254 _PROTOTYPE( static void rl_conf_hw
, (re_t
*rep
) );
255 _PROTOTYPE( static void rl_init_buf
, (re_t
*rep
) );
256 _PROTOTYPE( static void rl_init_hw
, (re_t
*rep
) );
257 _PROTOTYPE( static void rl_reset_hw
, (re_t
*rep
) );
258 _PROTOTYPE( static void rl_confaddr
, (re_t
*rep
) );
259 _PROTOTYPE( static void rl_rec_mode
, (re_t
*rep
) );
260 _PROTOTYPE( static void rl_readv
, (message
*mp
, int from_int
,
262 _PROTOTYPE( static void rl_readv_s
, (message
*mp
, int from_int
) );
263 _PROTOTYPE( static void rl_writev
, (message
*mp
, int from_int
,
265 _PROTOTYPE( static void rl_writev_s
, (message
*mp
, int from_int
) );
266 _PROTOTYPE( static void rl_check_ints
, (re_t
*rep
) );
267 _PROTOTYPE( static void rl_report_link
, (re_t
*rep
) );
268 _PROTOTYPE( static void mii_print_techab
, (U16_t techab
) );
269 _PROTOTYPE( static void mii_print_stat_speed
, (U16_t stat
,
271 _PROTOTYPE( static void rl_clear_rx
, (re_t
*rep
) );
272 _PROTOTYPE( static void rl_do_reset
, (re_t
*rep
) );
273 _PROTOTYPE( static void rl_getstat
, (message
*mp
) );
274 _PROTOTYPE( static void rl_getstat_s
, (message
*mp
) );
275 _PROTOTYPE( static void rl_getname
, (message
*mp
) );
276 _PROTOTYPE( static void reply
, (re_t
*rep
, int err
, int may_block
) );
277 _PROTOTYPE( static void mess_reply
, (message
*req
, message
*reply
) );
278 _PROTOTYPE( static void rtl8139_stop
, (void) );
279 _PROTOTYPE( static void check_int_events
, (void) );
280 _PROTOTYPE( static int do_hard_int
, (void) );
281 _PROTOTYPE( static void rtl8139_dump
, (message
*m
) );
283 _PROTOTYPE( static void dump_phy
, (re_t
*rep
) );
285 _PROTOTYPE( static int rl_handler
, (re_t
*rep
) );
286 _PROTOTYPE( static void rl_watchdog_f
, (timer_t
*tp
) );
288 /* The message used in the main loop is made global, so that rl_watchdog_f()
289 * can change its message type to fake a HARD_INT message.
292 PRIVATE
int int_event_check
; /* set to TRUE if events arrived */
294 static char *progname
;
297 /*===========================================================================*
299 *===========================================================================*/
300 int main(int argc
, char *argv
[])
308 env_setargs(argc
, argv
);
311 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v
, 0x0000L
, 0xFFFFL
);
312 eth_ign_proto
= htons((u16_t
) v
);
314 /* Observe some function key for debug dumps. */
315 fkeys
= sfkeys
= 0; bit_set(sfkeys
, 9);
316 if ((r
=fkey_map(&fkeys
, &sfkeys
)) != OK
)
317 printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r
);
319 /* Claim buffer memory now under Minix, before MM takes it all. */
320 for (rep
= &re_table
[0]; rep
< re_table
+RE_PORT_NR
; rep
++)
323 /* Try to notify INET that we are present (again). If INET cannot
324 * be found, assume this is the first time we started and INET is
327 (progname
=strrchr(argv
[0],'/')) ? progname
++ : (progname
=argv
[0]);
328 r
= _pm_findproc("inet", &inet_proc_nr
);
329 if (r
== OK
) notify(inet_proc_nr
);
334 if ((r
= receive(ANY
, &m
)) != OK
)
335 panic("rtl8139","receive failed", r
);
339 case DEV_PING
: notify(m
.m_source
); break;
340 case DL_WRITE
: rl_writev(&m
, FALSE
, FALSE
); break;
341 case DL_WRITEV
: rl_writev(&m
, FALSE
, TRUE
); break;
342 case DL_WRITEV_S
: rl_writev_s(&m
, FALSE
); break;
343 case DL_READ
: rl_readv(&m
, FALSE
, FALSE
); break;
344 case DL_READV
: rl_readv(&m
, FALSE
, TRUE
); break;
345 case DL_READV_S
: rl_readv_s(&m
, FALSE
); break;
346 case DL_CONF
: rl_init(&m
); break;
347 case DL_GETSTAT
: rl_getstat(&m
); break;
348 case DL_GETSTAT_S
: rl_getstat_s(&m
); break;
349 case DL_GETNAME
: rl_getname(&m
); break;
351 case DL_STOP
: do_stop(&m
); break;
354 /* Under MINIX, synchronous alarms are used instead of
355 * watchdog functions. The approach is very different:
356 * MINIX VMD timeouts are handled within the kernel
357 * (the watchdog is executed by CLOCK), and notify()
358 * the driver in some cases.
359 * MINIX timeouts result in a SYN_ALARM message to the
360 * driver and thus are handled where they should be
361 * handled. Locally, watchdog functions are used again.
370 case FKEY_PRESSED
: rtl8139_dump(&m
); break;
375 panic("rtl8139","illegal message", m
.m_type
);
380 /*===========================================================================*
382 *===========================================================================*/
383 PRIVATE
void sig_handler()
388 /* Try to obtain signal set from PM. */
389 if (getsigset(&sigset
) != 0) return;
391 /* Check for known signals. */
392 if (sigismember(&sigset
, SIGTERM
)) {
397 /*===========================================================================*
399 *===========================================================================*/
400 static void check_int_events(void)
404 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
406 if (rep
->re_mode
!= REM_ENABLED
)
408 if (!rep
->re_got_int
)
411 assert(rep
->re_flags
& REF_ENABLED
);
416 /*===========================================================================*
418 *===========================================================================*/
419 static void rtl8139_stop()
424 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
426 if (rep
->re_mode
!= REM_ENABLED
)
428 rl_outb(rep
->re_base_port
, RL_CR
, 0);
433 /*===========================================================================*
435 *===========================================================================*/
436 static void rtl8139_dump(m
)
437 message
*m
; /* pointer to request message */
443 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
445 if (rep
->re_mode
== REM_DISABLED
)
446 printf("Realtek RTL 8139 port %d is disabled\n", i
);
448 if (rep
->re_mode
!= REM_ENABLED
)
451 printf("Realtek RTL 8139 statistics of port %d:\n", i
);
453 printf("recvErr :%8ld\t", rep
->re_stat
.ets_recvErr
);
454 printf("sendErr :%8ld\t", rep
->re_stat
.ets_sendErr
);
455 printf("OVW :%8ld\n", rep
->re_stat
.ets_OVW
);
457 printf("CRCerr :%8ld\t", rep
->re_stat
.ets_CRCerr
);
458 printf("frameAll :%8ld\t", rep
->re_stat
.ets_frameAll
);
459 printf("missedP :%8ld\n", rep
->re_stat
.ets_missedP
);
461 printf("packetR :%8ld\t", rep
->re_stat
.ets_packetR
);
462 printf("packetT :%8ld\t", rep
->re_stat
.ets_packetT
);
463 printf("transDef :%8ld\n", rep
->re_stat
.ets_transDef
);
465 printf("collision :%8ld\t", rep
->re_stat
.ets_collision
);
466 printf("transAb :%8ld\t", rep
->re_stat
.ets_transAb
);
467 printf("carrSense :%8ld\n", rep
->re_stat
.ets_carrSense
);
469 printf("fifoUnder :%8ld\t", rep
->re_stat
.ets_fifoUnder
);
470 printf("fifoOver :%8ld\t", rep
->re_stat
.ets_fifoOver
);
471 printf("CDheartbeat:%8ld\n", rep
->re_stat
.ets_CDheartbeat
);
473 printf("OWC :%8ld\t", rep
->re_stat
.ets_OWC
);
475 printf("re_flags = 0x%x\n", rep
->re_flags
);
478 "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
479 rl_inw(rep
->re_base_port
, RL_TSAD
),
480 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
481 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
482 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
483 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
484 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
485 rep
->re_tx_head
, rep
->re_tx_tail
,
486 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
487 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
491 /*===========================================================================*
493 *===========================================================================*/
494 static void rl_init(mp
)
497 static int first_time
= 1;
506 rl_pci_conf(); /* Configure PCI devices. */
508 tmra_inittimer(&rl_watchdog
);
509 /* Use a synchronous alarm instead of a watchdog timer. */
514 if (port
< 0 || port
>= RE_PORT_NR
)
516 reply_mess
.m_type
= DL_CONF_REPLY
;
517 reply_mess
.m3_i1
= ENXIO
;
518 mess_reply(mp
, &reply_mess
);
521 rep
= &re_table
[port
];
522 if (rep
->re_mode
== REM_DISABLED
)
524 /* This is the default, try to (re)locate the device. */
526 if (rep
->re_mode
== REM_DISABLED
)
528 /* Probe failed, or the device is configured off. */
529 reply_mess
.m_type
= DL_CONF_REPLY
;
530 reply_mess
.m3_i1
= ENXIO
;
531 mess_reply(mp
, &reply_mess
);
534 if (rep
->re_mode
== REM_ENABLED
)
536 #if VERBOSE /* load silently ... can always check status later */
541 assert(rep
->re_mode
== REM_ENABLED
);
542 assert(rep
->re_flags
& REF_ENABLED
);
544 rep
->re_flags
&= ~(REF_PROMISC
| REF_MULTI
| REF_BROAD
);
546 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
547 rep
->re_flags
|= REF_PROMISC
;
548 if (mp
->DL_MODE
& DL_MULTI_REQ
)
549 rep
->re_flags
|= REF_MULTI
;
550 if (mp
->DL_MODE
& DL_BROAD_REQ
)
551 rep
->re_flags
|= REF_BROAD
;
553 rep
->re_client
= mp
->m_source
;
556 reply_mess
.m_type
= DL_CONF_REPLY
;
557 reply_mess
.m3_i1
= mp
->DL_PORT
;
558 reply_mess
.m3_i2
= RE_PORT_NR
;
559 *(ether_addr_t
*) reply_mess
.m3_ca1
= rep
->re_address
;
561 mess_reply(mp
, &reply_mess
);
564 /*===========================================================================*
566 *===========================================================================*/
567 static void rl_pci_conf()
571 static char envvar
[] = RL_ENVVAR
"#";
572 static char envfmt
[] = "*:d.d.d";
573 static char val
[128];
576 for (i
= 0, rep
= re_table
; i
<RE_PORT_NR
; i
++, rep
++)
578 strcpy(rep
->re_name
, "rtl8139#0");
579 rep
->re_name
[8] += i
;
581 envvar
[sizeof(RL_ENVVAR
)-1]= '0'+i
;
582 if (0 == env_get_param(envvar
, val
, sizeof(val
)) &&
583 ! env_prefix(envvar
, "pci")) {
587 (void) env_parse(envvar
, envfmt
, 1, &v
, 0, 255);
590 (void) env_parse(envvar
, envfmt
, 2, &v
, 0, 255);
593 (void) env_parse(envvar
, envfmt
, 3, &v
, 0, 255);
599 for (h
= 1; h
>= 0; h
--) {
600 for (i
= 0, rep
= re_table
; i
<RE_PORT_NR
; i
++, rep
++)
602 if (((rep
->re_pcibus
| rep
->re_pcidev
|
603 rep
->re_pcifunc
) != 0) != h
)
613 /*===========================================================================*
615 *===========================================================================*/
616 static int rl_probe(rep
)
619 int i
, r
, devind
, just_one
;
625 if ((rep
->re_pcibus
| rep
->re_pcidev
| rep
->re_pcifunc
) != 0)
627 /* Look for specific PCI device */
628 r
= pci_find_dev(rep
->re_pcibus
, rep
->re_pcidev
,
629 rep
->re_pcifunc
, &devind
);
632 printf("%s: no PCI found at %d.%d.%d\n",
633 rep
->re_name
, rep
->re_pcibus
,
634 rep
->re_pcidev
, rep
->re_pcifunc
);
637 pci_ids(devind
, &vid
, &did
);
642 r
= pci_first_dev(&devind
, &vid
, &did
);
650 for (i
= 0; pcitab
[i
].vid
!= 0; i
++)
652 if (pcitab
[i
].vid
!= vid
)
654 if (pcitab
[i
].did
!= did
)
656 if (pcitab
[i
].checkclass
)
659 "class check not implemented", NO_NUM
);
663 if (pcitab
[i
].vid
!= 0)
669 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
670 rep
->re_name
, vid
, did
,
672 rep
->re_pcidev
, rep
->re_pcifunc
);
676 r
= pci_next_dev(&devind
, &vid
, &did
);
681 #if VERBOSE /* stay silent at startup, can always get status later */
682 dname
= pci_dev_name(vid
, did
);
684 dname
= "unknown device";
685 printf("%s: ", rep
->re_name
);
686 printf("%s (%x/%x) at %s\n", dname
, vid
, did
, pci_slot_name(devind
));
689 /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
690 bar
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
694 "base address is not properly configured", NO_NUM
);
696 rep
->re_base_port
= bar
;
698 ilr
= pci_attr_r8(devind
, PCI_ILR
);
702 printf("%s: using I/O address 0x%lx, IRQ %d\n",
703 rep
->re_name
, (unsigned long)bar
, ilr
);
709 /*===========================================================================*
711 *===========================================================================*/
712 static void rl_conf_hw(rep
)
715 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
717 rep
->re_mode
= REM_DISABLED
; /* Superfluous */
721 /* PCI device is present */
722 rep
->re_mode
= REM_ENABLED
;
724 if (rep
->re_mode
!= REM_ENABLED
)
727 rep
->re_flags
= REF_EMPTY
;
728 rep
->re_link_up
= -1; /* Unknown */
731 rep
->re_report_link
= 0;
733 rep
->re_need_reset
= 0;
738 rep
->re_ertxth
= RL_TSD_ERTXTH_8
;
739 rep
->re_stat
= empty_stat
;
742 /*===========================================================================*
744 *===========================================================================*/
745 static void rl_init_buf(rep
)
748 size_t rx_bufsize
, tx_bufsize
, tot_bufsize
;
751 static struct memory chunk
;
754 /* Allocate receive and transmit buffers */
755 tx_bufsize
= ETH_MAX_PACK_SIZE_TAGGED
;
757 tx_bufsize
+= 4-(tx_bufsize
% 4); /* Align */
758 rx_bufsize
= RX_BUFSIZE
;
759 tot_bufsize
= N_TX_BUF
*tx_bufsize
+ rx_bufsize
;
761 /* Now try to allocate a kernel memory buffer. */
762 chunk
.size
= tot_bufsize
;
764 #define BUF_ALIGNMENT (64*1024)
766 if(!(mallocbuf
= malloc(BUF_ALIGNMENT
+ tot_bufsize
))) {
767 panic("RTL8139","Couldn't allocate kernel buffer",i
);
770 if(OK
!= (i
= sys_umap(SELF
, D
, (vir_bytes
) mallocbuf
, tot_bufsize
, &buf
))) {
771 panic("RTL8139","Couldn't re-map malloced buffer",i
);
774 /* click-align mallocced buffer. this is what we used to get
775 * from kmalloc() too.
777 if((off
= buf
% BUF_ALIGNMENT
)) {
778 mallocbuf
+= BUF_ALIGNMENT
- off
;
779 buf
+= BUF_ALIGNMENT
- off
;
782 for (i
= 0; i
<N_TX_BUF
; i
++)
784 rep
->re_tx
[i
].ret_buf
= buf
;
785 rep
->re_tx
[i
].v_ret_buf
= mallocbuf
;
787 mallocbuf
+= tx_bufsize
;
790 rep
->v_re_rx_buf
= mallocbuf
;
793 /*===========================================================================*
795 *===========================================================================*/
796 static void rl_init_hw(rep
)
801 rep
->re_flags
= REF_EMPTY
;
802 rep
->re_flags
|= REF_ENABLED
;
804 /* Set the interrupt handler. The policy is to only send HARD_INT
805 * notifications. Don't reenable interrupts automatically. The id
806 * that is passed back is the interrupt line number.
808 rep
->re_hook_id
= rep
->re_irq
;
809 if ((s
=sys_irqsetpolicy(rep
->re_irq
, 0, &rep
->re_hook_id
)) != OK
)
810 printf("RTL8139: error, couldn't set IRQ policy: %d\n", s
);
814 if ((s
=sys_irqenable(&rep
->re_hook_id
)) != OK
)
815 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
817 #if VERBOSE /* stay silent during startup, can always get status later */
819 printf("%s: model %s\n", rep
->re_name
, rep
->re_model
);
822 printf("%s: unknown model 0x%08x\n",
824 rl_inl(rep
->re_base_port
, RL_TCR
) &
825 (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
));
832 printf("%s: Ethernet address ", rep
->re_name
);
833 for (i
= 0; i
< 6; i
++)
835 printf("%x%c", rep
->re_address
.ea_addr
[i
],
841 /*===========================================================================*
843 *===========================================================================*/
844 static void rl_reset_hw(rep
)
853 port
= rep
->re_base_port
;
857 rl_outb(port
, RL_BMCR
, MII_CTRL_RST
);
860 if (!(rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
))
862 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < HZ
);
863 if (rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
)
864 panic("rtl8139","reset PHY failed to complete", NO_NUM
);
867 /* Reset the device */
868 printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
869 port
, rl_inb(port
, RL_CR
));
870 rl_outb(port
, RL_CR
, RL_CR_RST
);
873 if (!(rl_inb(port
, RL_CR
) & RL_CR_RST
))
875 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < HZ
);
876 printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
877 port
, rl_inb(port
, RL_CR
));
878 if (rl_inb(port
, RL_CR
) & RL_CR_RST
)
879 printf("rtl8139: reset failed to complete");
881 t
= rl_inl(port
, RL_TCR
);
882 switch(t
& (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
))
884 case RL_TCR_HWVER_RTL8139
: rep
->re_model
= "RTL8139"; break;
885 case RL_TCR_HWVER_RTL8139A
: rep
->re_model
= "RTL8139A"; break;
886 case RL_TCR_HWVER_RTL8139AG
:
887 rep
->re_model
= "RTL8139A-G / RTL8139C";
889 case RL_TCR_HWVER_RTL8139B
:
890 rep
->re_model
= "RTL8139B / RTL8130";
892 case RL_TCR_HWVER_RTL8100
: rep
->re_model
= "RTL8100"; break;
893 case RL_TCR_HWVER_RTL8100B
:
894 rep
->re_model
= "RTL8100B/RTL8139D";
896 case RL_TCR_HWVER_RTL8139CP
: rep
->re_model
= "RTL8139C+"; break;
897 case RL_TCR_HWVER_RTL8101
: rep
->re_model
= "RTL8101"; break;
904 printf("REVID: 0x%02x\n", rl_inb(port
, RL_REVID
));
909 /* Should init multicast mask */
911 08-0f R
/W MAR
[0-7] multicast
913 bus_buf
= vm_1phys2bus(rep
->re_rx_buf
);
914 rl_outl(port
, RL_RBSTART
, bus_buf
);
917 for (i
= 0; i
<N_TX_BUF
; i
++)
919 rep
->re_tx
[i
].ret_busy
= FALSE
;
920 bus_buf
= vm_1phys2bus(rep
->re_tx
[i
].ret_buf
);
921 rl_outl(port
, RL_TSAD0
+i
*4, bus_buf
);
922 t
= rl_inl(port
, RL_TSD0
+i
*4);
923 assert(t
& RL_TSD_OWN
);
930 t
= rl_inw(port
, RL_IMR
);
931 rl_outw(port
, RL_IMR
, t
| (RL_IMR_SERR
| RL_IMR_TIMEOUT
|
934 t
= rl_inw(port
, RL_IMR
);
935 rl_outw(port
, RL_IMR
, t
| (RL_IMR_FOVW
| RL_IMR_PUN
|
936 RL_IMR_RXOVW
| RL_IMR_RER
| RL_IMR_ROK
));
938 t
= rl_inw(port
, RL_IMR
);
939 rl_outw(port
, RL_IMR
, t
| (RL_IMR_TER
| RL_IMR_TOK
));
941 t
= rl_inb(port
, RL_CR
);
942 rl_outb(port
, RL_CR
, t
| RL_CR_RE
);
944 t
= rl_inb(port
, RL_CR
);
945 rl_outb(port
, RL_CR
, t
| RL_CR_TE
);
947 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
949 t
= rl_inl(port
, RL_TCR
);
950 rl_outl(port
, RL_TCR
, t
| RL_TCR_IFG_STD
);
953 /*===========================================================================*
955 *===========================================================================*/
956 static void rl_confaddr(rep
)
959 static char eakey
[]= RL_ENVVAR
"#_EA";
960 static char eafmt
[]= "x:x:x:x:x:x";
967 /* User defined ethernet address? */
968 eakey
[sizeof(RL_ENVVAR
)-1]= '0' + (rep
-re_table
);
970 port
= rep
->re_base_port
;
972 for (i
= 0; i
< 6; i
++)
974 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
976 rep
->re_address
.ea_addr
[i
]= v
;
979 if (i
!= 0 && i
!= 6) env_panic(eakey
); /* It's all or nothing */
981 /* Should update ethernet address in hardware */
984 port
= rep
->re_base_port
;
985 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_CONFIG
);
988 w
|= (rep
->re_address
.ea_addr
[i
] << (i
*8));
989 rl_outl(port
, RL_IDR
, w
);
992 w
|= (rep
->re_address
.ea_addr
[i
] << ((i
-4)*8));
993 rl_outl(port
, RL_IDR
+4, w
);
994 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_NORMAL
);
997 /* Get ethernet address */
999 rep
->re_address
.ea_addr
[i
]= rl_inb(port
, RL_IDR
+i
);
1002 /*===========================================================================*
1004 *===========================================================================*/
1005 static void rl_rec_mode(rep
)
1011 port
= rep
->re_base_port
;
1012 rcr
= rl_inl(port
, RL_RCR
);
1013 rcr
&= ~(RL_RCR_AB
|RL_RCR_AM
|RL_RCR_APM
|RL_RCR_AAP
);
1014 if (rep
->re_flags
& REF_PROMISC
)
1015 rcr
|= RL_RCR_AB
| RL_RCR_AM
| RL_RCR_AAP
;
1016 if (rep
->re_flags
& REF_BROAD
)
1018 if (rep
->re_flags
& REF_MULTI
)
1022 rl_outl(port
, RL_RCR
, rcr
);
1025 /*===========================================================================*
1027 *===========================================================================*/
1028 static void rl_readv(mp
, from_int
, vectored
)
1033 int i
, j
, n
, o
, s
, s1
, dl_port
, re_client
, count
, size
;
1035 unsigned amount
, totlen
, packlen
;
1036 phys_bytes src_phys
, dst_phys
, iov_src
;
1037 u16_t d_start
, d_end
;
1038 u32_t l
, rxstat
= 0x12345678;
1043 dl_port
= mp
->DL_PORT
;
1044 count
= mp
->DL_COUNT
;
1045 if (dl_port
< 0 || dl_port
>= RE_PORT_NR
)
1046 panic("rtl8139"," illegal port", dl_port
);
1047 rep
= &re_table
[dl_port
];
1048 re_client
= mp
->DL_PROC
;
1049 rep
->re_client
= re_client
;
1051 if (rep
->re_clear_rx
)
1052 goto suspend
; /* Buffer overflow */
1054 assert(rep
->re_mode
== REM_ENABLED
);
1055 assert(rep
->re_flags
& REF_ENABLED
);
1057 port
= rep
->re_base_port
;
1059 /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1061 if (!from_int
&& (rl_inb(port
, RL_CR
) & RL_CR_BUFE
))
1063 /* Receive buffer is empty, suspend */
1067 d_start
= rl_inw(port
, RL_CAPR
) + RL_CAPR_DATA_OFF
;
1068 d_end
= rl_inw(port
, RL_CBR
) % RX_BUFSIZE
;
1070 if (d_start
>= RX_BUFSIZE
)
1072 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
1073 rl_inw(port
, RL_CAPR
));
1074 d_start
%= RX_BUFSIZE
;
1077 if (d_end
> d_start
)
1078 amount
= d_end
-d_start
;
1080 amount
= d_end
+RX_BUFSIZE
- d_start
;
1082 rxstat
= *(u32_t
*) (rep
->v_re_rx_buf
+ d_start
);
1084 if (rep
->re_clear_rx
)
1087 printf("rl_readv: late buffer overflow\n");
1089 goto suspend
; /* Buffer overflow */
1092 /* Should convert from little endian to host byte order */
1094 if (!(rxstat
& RL_RXS_ROK
))
1096 printf("rxstat = 0x%08lx\n", rxstat
);
1097 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
1098 d_start
, d_end
, rxstat
);
1099 panic("rtl8139","received packet not OK", NO_NUM
);
1101 totlen
= (rxstat
>> RL_RXS_LEN_S
);
1102 if (totlen
< 8 || totlen
> 2*ETH_MAX_PACK_SIZE
)
1104 /* Someting went wrong */
1106 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
1107 totlen
, rxstat
, d_start
);
1109 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
1110 d_start
, d_end
, totlen
, rxstat
);
1111 panic(NULL
, NULL
, NO_NUM
);
1115 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
1116 d_start
, d_end
, totlen
, rxstat
);
1119 if (totlen
+4 > amount
)
1121 printf("rl_readv: packet not yet ready\n");
1125 /* Should subtract the CRC */
1126 packlen
= totlen
- ETH_CRC_SIZE
;
1134 src_phys
= rep
->re_rx_buf
;
1135 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1136 iov_src
+= IOVEC_NR
* sizeof(rep
->re_iovec
[0]),
1137 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec
[0]))
1143 cps
= sys_vircopy(re_client
, D
,
1144 (vir_bytes
) mp
->DL_ADDR
+ iov_offset
,
1145 SELF
, D
, (vir_bytes
) rep
->re_iovec
,
1146 n
* sizeof(rep
->re_iovec
[0]));
1149 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1152 for (j
= 0, iovp
= rep
->re_iovec
; j
<n
; j
++, iovp
++)
1155 if (size
+ s
> packlen
)
1157 assert(packlen
> size
);
1161 if (o
>= RX_BUFSIZE
)
1164 assert(o
< RX_BUFSIZE
);
1167 if (o
+s
> RX_BUFSIZE
)
1169 assert(o
<RX_BUFSIZE
);
1172 cps
= sys_vircopy(SELF
, D
,
1173 (vir_bytes
) rep
->v_re_rx_buf
+o
,
1174 re_client
, D
, iovp
->iov_addr
,
1178 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1180 cps
= sys_vircopy(SELF
, D
,
1181 (vir_bytes
) rep
->v_re_rx_buf
,
1183 iovp
->iov_addr
+s1
, s
-s1
);
1186 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1191 cps
= sys_vircopy(SELF
, D
,
1192 (vir_bytes
) rep
->v_re_rx_buf
+o
,
1193 re_client
, D
, iovp
->iov_addr
,
1197 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1202 if (size
== packlen
)
1206 if (size
== packlen
)
1219 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE_TAGGED
)
1220 panic("rtl8139","invalid packet size", size
);
1221 if (OK
!= sys_umap(re_client
, D
, (vir_bytes
)mp
->DL_ADDR
, size
, &phys_user
))
1222 panic("rtl8139","umap_local failed", NO_NUM
);
1224 p
= rep
->re_tx
[tx_head
].ret_buf
;
1225 cps
= sys_abscopy(phys_user
, p
, size
);
1226 if (cps
!= OK
) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps
);
1230 if (rep
->re_clear_rx
)
1232 /* For some reason the receiver FIFO is not stopped when
1233 * the buffer is full.
1236 printf("rl_readv: later buffer overflow\n");
1238 goto suspend
; /* Buffer overflow */
1241 rep
->re_stat
.ets_packetR
++;
1242 rep
->re_read_s
= packlen
;
1243 rep
->re_flags
= (rep
->re_flags
& ~REF_READING
) | REF_PACK_RECV
;
1245 /* Avoid overflow in 16-bit computations */
1248 l
= (l
+3) & ~3; /* align */
1249 if (l
>= RX_BUFSIZE
)
1252 assert(l
< RX_BUFSIZE
);
1254 rl_outw(port
, RL_CAPR
, l
-RL_CAPR_DATA_OFF
);
1257 reply(rep
, OK
, FALSE
);
1264 assert(rep
->re_flags
& REF_READING
);
1266 /* No need to store any state */
1270 rep
->re_rx_mess
= *mp
;
1271 assert(!(rep
->re_flags
& REF_READING
));
1272 rep
->re_flags
|= REF_READING
;
1274 reply(rep
, OK
, FALSE
);
1277 /*===========================================================================*
1279 *===========================================================================*/
1280 static void rl_readv_s(mp
, from_int
)
1284 int i
, j
, n
, o
, s
, s1
, dl_port
, re_client
, count
, size
;
1286 unsigned amount
, totlen
, packlen
;
1287 phys_bytes src_phys
, dst_phys
, iov_src
;
1288 u16_t d_start
, d_end
;
1289 u32_t l
, rxstat
= 0x12345678;
1295 dl_port
= mp
->DL_PORT
;
1296 count
= mp
->DL_COUNT
;
1297 if (dl_port
< 0 || dl_port
>= RE_PORT_NR
)
1298 panic("rtl8139"," illegal port", dl_port
);
1299 rep
= &re_table
[dl_port
];
1300 re_client
= mp
->DL_PROC
;
1301 rep
->re_client
= re_client
;
1303 if (rep
->re_clear_rx
)
1304 goto suspend
; /* Buffer overflow */
1306 assert(rep
->re_mode
== REM_ENABLED
);
1307 assert(rep
->re_flags
& REF_ENABLED
);
1309 port
= rep
->re_base_port
;
1311 /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1313 if (!from_int
&& (rl_inb(port
, RL_CR
) & RL_CR_BUFE
))
1315 /* Receive buffer is empty, suspend */
1319 d_start
= rl_inw(port
, RL_CAPR
) + RL_CAPR_DATA_OFF
;
1320 d_end
= rl_inw(port
, RL_CBR
) % RX_BUFSIZE
;
1322 if (d_start
>= RX_BUFSIZE
)
1324 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
1325 rl_inw(port
, RL_CAPR
));
1326 d_start
%= RX_BUFSIZE
;
1329 if (d_end
> d_start
)
1330 amount
= d_end
-d_start
;
1332 amount
= d_end
+RX_BUFSIZE
- d_start
;
1334 rxstat
= *(u32_t
*) (rep
->v_re_rx_buf
+ d_start
);
1336 if (rep
->re_clear_rx
)
1339 printf("rl_readv: late buffer overflow\n");
1341 goto suspend
; /* Buffer overflow */
1344 /* Should convert from little endian to host byte order */
1346 if (!(rxstat
& RL_RXS_ROK
))
1348 printf("rxstat = 0x%08lx\n", rxstat
);
1349 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
1350 d_start
, d_end
, rxstat
);
1351 panic("rtl8139","received packet not OK", NO_NUM
);
1353 totlen
= (rxstat
>> RL_RXS_LEN_S
);
1354 if (totlen
< 8 || totlen
> 2*ETH_MAX_PACK_SIZE
)
1356 /* Someting went wrong */
1358 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
1359 totlen
, rxstat
, d_start
);
1361 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
1362 d_start
, d_end
, totlen
, rxstat
);
1363 panic(NULL
, NULL
, NO_NUM
);
1367 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
1368 d_start
, d_end
, totlen
, rxstat
);
1371 if (totlen
+4 > amount
)
1373 printf("rl_readv: packet not yet ready\n");
1377 /* Should subtract the CRC */
1378 packlen
= totlen
- ETH_CRC_SIZE
;
1382 src_phys
= rep
->re_rx_buf
;
1383 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1384 iov_src
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]),
1385 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1391 cps
= sys_safecopyfrom(re_client
, mp
->DL_GRANT
, iov_offset
,
1392 (vir_bytes
) rep
->re_iovec_s
,
1393 n
* sizeof(rep
->re_iovec_s
[0]), D
);
1396 panic(__FILE__
, "rl_readv_s: sys_safecopyfrom failed",
1400 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
1403 if (size
+ s
> packlen
)
1405 assert(packlen
> size
);
1410 if (sys_umap(re_client
, D
, iovp
->iov_addr
, s
, &dst_phys
) != OK
)
1411 panic("rtl8139","umap_local failed\n", NO_NUM
);
1414 if (o
>= RX_BUFSIZE
)
1417 assert(o
< RX_BUFSIZE
);
1420 if (o
+s
> RX_BUFSIZE
)
1422 assert(o
<RX_BUFSIZE
);
1425 cps
= sys_safecopyto(re_client
,
1427 (vir_bytes
) rep
->v_re_rx_buf
+o
, s1
, D
);
1431 "rl_readv_s: sys_safecopyto failed",
1434 cps
= sys_safecopyto(re_client
,
1435 iovp
->iov_grant
, s1
,
1436 (vir_bytes
) rep
->v_re_rx_buf
, s
-s1
, S
);
1440 "rl_readv_s: sys_safecopyto failed",
1446 cps
= sys_safecopyto(re_client
,
1448 (vir_bytes
) rep
->v_re_rx_buf
+o
, s
, D
);
1451 "rl_readv_s: sys_vircopy failed",
1456 if (size
== packlen
)
1460 if (size
== packlen
)
1468 if (rep
->re_clear_rx
)
1470 /* For some reason the receiver FIFO is not stopped when
1471 * the buffer is full.
1474 printf("rl_readv: later buffer overflow\n");
1476 goto suspend
; /* Buffer overflow */
1479 rep
->re_stat
.ets_packetR
++;
1480 rep
->re_read_s
= packlen
;
1481 rep
->re_flags
= (rep
->re_flags
& ~REF_READING
) | REF_PACK_RECV
;
1483 /* Avoid overflow in 16-bit computations */
1486 l
= (l
+3) & ~3; /* align */
1487 if (l
>= RX_BUFSIZE
)
1490 assert(l
< RX_BUFSIZE
);
1492 rl_outw(port
, RL_CAPR
, l
-RL_CAPR_DATA_OFF
);
1495 reply(rep
, OK
, FALSE
);
1502 assert(rep
->re_flags
& REF_READING
);
1504 /* No need to store any state */
1508 rep
->re_rx_mess
= *mp
;
1509 assert(!(rep
->re_flags
& REF_READING
));
1510 rep
->re_flags
|= REF_READING
;
1512 reply(rep
, OK
, FALSE
);
1515 /*===========================================================================*
1517 *===========================================================================*/
1518 static void rl_writev(mp
, from_int
, vectored
)
1523 phys_bytes iov_src
, phys_user
;
1524 int i
, j
, n
, s
, port
, count
, size
;
1525 int tx_head
, re_client
;
1532 count
= mp
->DL_COUNT
;
1533 if (port
< 0 || port
>= RE_PORT_NR
)
1534 panic("rtl8139","illegal port", port
);
1535 rep
= &re_table
[port
];
1536 re_client
= mp
->DL_PROC
;
1537 rep
->re_client
= re_client
;
1539 assert(rep
->re_mode
== REM_ENABLED
);
1540 assert(rep
->re_flags
& REF_ENABLED
);
1544 assert(rep
->re_flags
& REF_SEND_AVAIL
);
1545 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1546 rep
->re_send_int
= FALSE
;
1547 rep
->re_tx_alive
= TRUE
;
1550 tx_head
= rep
->re_tx_head
;
1551 if (rep
->re_tx
[tx_head
].ret_busy
)
1553 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1554 rep
->re_flags
|= REF_SEND_AVAIL
;
1555 if (rep
->re_tx
[tx_head
].ret_busy
)
1558 /* Race condition, the interrupt handler may clear re_busy
1559 * before we got a chance to set REF_SEND_AVAIL. Checking
1560 * ret_busy twice should be sufficient.
1563 printf("rl_writev: race detected\n");
1565 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1566 rep
->re_send_int
= FALSE
;
1569 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1570 assert(!(rep
->re_flags
& REF_PACK_SENT
));
1577 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1578 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1579 iov_src
+= IOVEC_NR
* sizeof(rep
->re_iovec
[0]),
1580 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec
[0]))
1585 cps
= sys_vircopy(re_client
, D
, ((vir_bytes
) mp
->DL_ADDR
) + iov_offset
,
1586 SELF
, D
, (vir_bytes
) rep
->re_iovec
,
1587 n
* sizeof(rep
->re_iovec
[0]));
1588 if (cps
!= OK
) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps
);
1590 for (j
= 0, iovp
= rep
->re_iovec
; j
<n
; j
++, iovp
++)
1593 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
)
1595 panic("rtl8139","invalid packet size",
1599 if (OK
!= sys_umap(re_client
, D
, iovp
->iov_addr
, s
, &phys_user
))
1600 panic("rtl8139","umap_local failed\n", NO_NUM
);
1602 cps
= sys_vircopy(re_client
, D
, iovp
->iov_addr
,
1603 SELF
, D
, (vir_bytes
) ret
, s
);
1604 if (cps
!= OK
) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps
);
1609 if (size
< ETH_MIN_PACK_SIZE
)
1610 panic("rtl8139","invalid packet size", size
);
1615 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE_TAGGED
)
1616 panic("rtl8139","invalid packet size", size
);
1617 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1618 cps
= sys_vircopy(re_client
, D
, (vir_bytes
)mp
->DL_ADDR
,
1619 SELF
, D
, (vir_bytes
) ret
, size
);
1620 if (cps
!= OK
) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps
);
1623 rl_outl(rep
->re_base_port
, RL_TSD0
+tx_head
*4,
1624 rep
->re_ertxth
| size
);
1625 rep
->re_tx
[tx_head
].ret_busy
= TRUE
;
1627 if (++tx_head
== N_TX_BUF
)
1629 assert(tx_head
< RL_N_TX
);
1630 rep
->re_tx_head
= tx_head
;
1632 rep
->re_flags
|= REF_PACK_SENT
;
1634 /* If the interrupt handler called, don't send a reply. The reply
1635 * will be sent after all interrupts are handled.
1639 reply(rep
, OK
, FALSE
);
1644 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
1645 tx_head
, rep
->re_tx_tail
,
1646 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1647 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1648 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
1649 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
1650 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
1651 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
1652 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
1656 panic("rtl8139","should not be sending\n", NO_NUM
);
1658 rep
->re_tx_mess
= *mp
;
1659 reply(rep
, OK
, FALSE
);
1662 /*===========================================================================*
1664 *===========================================================================*/
1665 static void rl_writev_s(mp
, from_int
)
1670 int i
, j
, n
, s
, port
, count
, size
;
1671 int tx_head
, re_client
;
1679 count
= mp
->DL_COUNT
;
1680 if (port
< 0 || port
>= RE_PORT_NR
)
1681 panic("rtl8139","illegal port", port
);
1682 rep
= &re_table
[port
];
1683 re_client
= mp
->DL_PROC
;
1684 rep
->re_client
= re_client
;
1686 assert(rep
->re_mode
== REM_ENABLED
);
1687 assert(rep
->re_flags
& REF_ENABLED
);
1691 assert(rep
->re_flags
& REF_SEND_AVAIL
);
1692 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1693 rep
->re_send_int
= FALSE
;
1694 rep
->re_tx_alive
= TRUE
;
1697 tx_head
= rep
->re_tx_head
;
1698 if (rep
->re_tx
[tx_head
].ret_busy
)
1700 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1701 rep
->re_flags
|= REF_SEND_AVAIL
;
1702 if (rep
->re_tx
[tx_head
].ret_busy
)
1705 /* Race condition, the interrupt handler may clear re_busy
1706 * before we got a chance to set REF_SEND_AVAIL. Checking
1707 * ret_busy twice should be sufficient.
1710 printf("rl_writev: race detected\n");
1712 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1713 rep
->re_send_int
= FALSE
;
1716 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1717 assert(!(rep
->re_flags
& REF_PACK_SENT
));
1720 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1721 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1722 iov_src
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]),
1723 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1728 cps
= sys_safecopyfrom(re_client
, mp
->DL_GRANT
, iov_offset
,
1729 (vir_bytes
) rep
->re_iovec_s
,
1730 n
* sizeof(rep
->re_iovec_s
[0]), D
);
1733 panic(__FILE__
, "rl_writev_s: sys_safecopyfrom failed",
1737 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
1740 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
)
1742 panic("rtl8139","invalid packet size",
1745 cps
= sys_safecopyfrom(re_client
, iovp
->iov_grant
, 0,
1746 (vir_bytes
) ret
, s
, D
);
1750 "rl_writev_s: sys_safecopyfrom failed",
1757 if (size
< ETH_MIN_PACK_SIZE
)
1758 panic("rtl8139","invalid packet size", size
);
1760 rl_outl(rep
->re_base_port
, RL_TSD0
+tx_head
*4,
1761 rep
->re_ertxth
| size
);
1762 rep
->re_tx
[tx_head
].ret_busy
= TRUE
;
1764 if (++tx_head
== N_TX_BUF
)
1766 assert(tx_head
< RL_N_TX
);
1767 rep
->re_tx_head
= tx_head
;
1769 rep
->re_flags
|= REF_PACK_SENT
;
1771 /* If the interrupt handler called, don't send a reply. The reply
1772 * will be sent after all interrupts are handled.
1776 reply(rep
, OK
, FALSE
);
1781 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
1782 tx_head
, rep
->re_tx_tail
,
1783 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1784 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1785 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
1786 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
1787 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
1788 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
1789 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
1793 panic("rtl8139","should not be sending\n", NO_NUM
);
1795 rep
->re_tx_mess
= *mp
;
1796 reply(rep
, OK
, FALSE
);
1799 /*===========================================================================*
1801 *===========================================================================*/
1802 static void rl_check_ints(rep
)
1806 10-1f R
/W TSD
[0-3] Transmit Status of Descriptor
[0-3]
1807 31 R CRS Carrier Sense Lost
1808 30 R TABT Transmit Abort
1809 29 R OWC Out of Window Collision
1810 27-24 R NCC
[3-0] Number of Collision Count
1812 21-16 R
/W ERTXH
[5-0] Early Tx Threshold
1813 15 R TOK Transmit OK
1814 14 R TUN Transmit FIFO Underrun
1816 12-0 R
/W SIZE Descriptor Size
1817 3e-3f R
/W ISR Interrupt Status Register
1818 6 R
/W FOVW Fx FIFO Overflow Interrupt
1819 5 R
/W PUN
/LinkChg Packet Underrun
/ Link Change Interrupt
1820 3 R
/W TER Transmit Error Interrupt
1821 2 R
/W TOK Transmit OK Interrupt
1822 3e-3f R
/W ISR Interrupt Status Register
1823 15 R
/W SERR System Error Interrupt
1824 14 R
/W TimeOut Time Out Interrupt
1825 13 R
/W LenChg Cable Length Change Interrupt
1826 3e-3f R
/W ISR Interrupt Status Register
1827 4 R
/W RXOVW Rx Buffer Overflow Interrupt
1828 1 R
/W RER Receive Error Interrupt
1829 0 R
/W ROK Receive OK Interrupt
1830 4c
-4f R
/W MPC Missed Packet Counter
1831 60-61 R TSAD Transmit Status of All Descriptors
1832 15-12 R TOK
[3-0] TOK bit of Descriptor
[3-0]
1833 11-8 R TUN
[3-0] TUN bit of Descriptor
[3-0]
1834 7-4 R TABT
[3-0] TABT bit of Descriptor
[3-0]
1835 3-0 R OWN
[3-0] OWN bit of Descriptor
[3-0]
1836 6c
-6d R DIS Disconnect Counter
1837 15-0 R DCNT Disconnect Counter
1838 6e-6f R FCSC False Carrier Sense Counter
1839 15-0 R FCSCNT False Carrier event counter
1840 72-73 R REC RX_ER Counter
1841 15-0 R RXERCNT Received packet counter
1846 re_flags
= rep
->re_flags
;
1848 if ((re_flags
& REF_READING
) &&
1849 !(rl_inb(rep
->re_base_port
, RL_CR
) & RL_CR_BUFE
))
1851 if (rep
->re_rx_mess
.m_type
== DL_READV
)
1853 rl_readv(&rep
->re_rx_mess
, TRUE
/* from int */,
1854 TRUE
/* vectored */);
1856 else if (rep
->re_rx_mess
.m_type
== DL_READV_S
)
1858 rl_readv_s(&rep
->re_rx_mess
, TRUE
/* from int */);
1862 assert(rep
->re_rx_mess
.m_type
== DL_READ
);
1863 rl_readv(&rep
->re_rx_mess
, TRUE
/* from int */,
1864 FALSE
/* !vectored */);
1867 if (rep
->re_clear_rx
)
1870 if (rep
->re_need_reset
)
1873 if (rep
->re_send_int
)
1875 if (rep
->re_tx_mess
.m_type
== DL_WRITEV
)
1877 rl_writev(&rep
->re_tx_mess
, TRUE
/* from int */,
1878 TRUE
/* vectored */);
1882 assert(rep
->re_tx_mess
.m_type
== DL_WRITE
);
1883 rl_writev(&rep
->re_tx_mess
, TRUE
/* from int */,
1884 FALSE
/* !vectored */);
1888 if (rep
->re_report_link
)
1889 rl_report_link(rep
);
1891 if (rep
->re_flags
& (REF_PACK_SENT
| REF_PACK_RECV
))
1892 reply(rep
, OK
, TRUE
);
1895 /*===========================================================================*
1897 *===========================================================================*/
1898 static void rl_report_link(rep
)
1902 u16_t mii_ctrl
, mii_status
, mii_ana
, mii_anlpa
, mii_ane
, mii_extstat
;
1906 rep
->re_report_link
= FALSE
;
1907 port
= rep
->re_base_port
;
1908 msr
= rl_inb(port
, RL_MSR
);
1909 link_up
= !(msr
& RL_MSR_LINKB
);
1910 rep
->re_link_up
= link_up
;
1913 printf("%s: link down\n", rep
->re_name
);
1917 mii_ctrl
= rl_inw(port
, RL_BMCR
);
1918 mii_status
= rl_inw(port
, RL_BMSR
);
1919 mii_ana
= rl_inw(port
, RL_ANAR
);
1920 mii_anlpa
= rl_inw(port
, RL_ANLPAR
);
1921 mii_ane
= rl_inw(port
, RL_ANER
);
1924 if (mii_ctrl
& (MII_CTRL_LB
|MII_CTRL_PD
|MII_CTRL_ISO
))
1926 printf("%s: PHY: ", rep
->re_name
);
1928 if (mii_ctrl
& MII_CTRL_LB
)
1930 printf("loopback mode");
1933 if (mii_ctrl
& MII_CTRL_PD
)
1935 if (!f
) printf(", ");
1937 printf("powered down");
1939 if (mii_ctrl
& MII_CTRL_ISO
)
1941 if (!f
) printf(", ");
1948 if (!(mii_ctrl
& MII_CTRL_ANE
))
1950 printf("%s: manual config: ", rep
->re_name
);
1951 switch(mii_ctrl
& (MII_CTRL_SP_LSB
|MII_CTRL_SP_MSB
))
1953 case MII_CTRL_SP_10
: printf("10 Mbps"); break;
1954 case MII_CTRL_SP_100
: printf("100 Mbps"); break;
1955 case MII_CTRL_SP_1000
: printf("1000 Mbps"); break;
1956 case MII_CTRL_SP_RES
: printf("reserved speed"); break;
1958 if (mii_ctrl
& MII_CTRL_DM
)
1959 printf(", full duplex");
1961 printf(", half duplex");
1966 if (!debug
) goto resspeed
;
1968 printf("%s: ", rep
->re_name
);
1969 mii_print_stat_speed(mii_status
, mii_extstat
);
1972 if (!(mii_status
& MII_STATUS_ANC
))
1973 printf("%s: auto-negotiation not complete\n", rep
->re_name
);
1974 if (mii_status
& MII_STATUS_RF
)
1975 printf("%s: remote fault detected\n", rep
->re_name
);
1976 if (!(mii_status
& MII_STATUS_ANA
))
1978 printf("%s: local PHY has no auto-negotiation ability\n",
1981 if (!(mii_status
& MII_STATUS_LS
))
1982 printf("%s: link down\n", rep
->re_name
);
1983 if (mii_status
& MII_STATUS_JD
)
1984 printf("%s: jabber condition detected\n", rep
->re_name
);
1985 if (!(mii_status
& MII_STATUS_EC
))
1987 printf("%s: no extended register set\n", rep
->re_name
);
1990 if (!(mii_status
& MII_STATUS_ANC
))
1993 printf("%s: local cap.: ", rep
->re_name
);
1994 mii_print_techab(mii_ana
);
1997 if (mii_ane
& MII_ANE_PDF
)
1998 printf("%s: parallel detection fault\n", rep
->re_name
);
1999 if (!(mii_ane
& MII_ANE_LPANA
))
2001 printf("%s: link-partner does not support auto-negotiation\n",
2006 printf("%s: remote cap.: ", rep
->re_name
);
2007 mii_print_techab(mii_anlpa
);
2011 printf("%s: ", rep
->re_name
);
2012 printf("link up at %d Mbps, ", (msr
& RL_MSR_SPEED_10
) ? 10 : 100);
2013 printf("%s duplex\n", ((mii_ctrl
& MII_CTRL_DM
) ? "full" : "half"));
2017 static void mii_print_techab(techab
)
2021 if ((techab
& MII_ANA_SEL_M
) != MII_ANA_SEL_802_3
)
2023 printf("strange selector 0x%x, value 0x%x",
2024 techab
& MII_ANA_SEL_M
,
2025 (techab
& MII_ANA_TAF_M
) >> MII_ANA_TAF_S
);
2029 if (techab
& (MII_ANA_100T4
| MII_ANA_100TXFD
| MII_ANA_100TXHD
))
2031 printf("100 Mbps: ");
2034 if (techab
& MII_ANA_100T4
)
2039 if (techab
& (MII_ANA_100TXFD
| MII_ANA_100TXHD
))
2045 switch(techab
& (MII_ANA_100TXFD
|MII_ANA_100TXHD
))
2047 case MII_ANA_100TXFD
: printf("FD"); break;
2048 case MII_ANA_100TXHD
: printf("HD"); break;
2049 default: printf("FD/HD"); break;
2053 if (techab
& (MII_ANA_10TFD
| MII_ANA_10THD
))
2057 printf("10 Mbps: ");
2060 switch(techab
& (MII_ANA_10TFD
|MII_ANA_10THD
))
2062 case MII_ANA_10TFD
: printf("FD"); break;
2063 case MII_ANA_10THD
: printf("HD"); break;
2064 default: printf("FD/HD"); break;
2067 if (techab
& MII_ANA_PAUSE_SYM
)
2072 printf("pause(SYM)");
2074 if (techab
& MII_ANA_PAUSE_ASYM
)
2079 printf("pause(ASYM)");
2081 if (techab
& MII_ANA_TAF_RES
)
2086 printf("0x%x", (techab
& MII_ANA_TAF_RES
) >> MII_ANA_TAF_S
);
2090 static void mii_print_stat_speed(stat
, extstat
)
2096 if (stat
& MII_STATUS_EXT_STAT
)
2098 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
|
2099 MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
2101 printf("1000 Mbps: ");
2104 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
))
2109 (MII_ESTAT_1000XFD
|MII_ESTAT_1000XHD
))
2111 case MII_ESTAT_1000XFD
: printf("FD"); break;
2112 case MII_ESTAT_1000XHD
: printf("HD"); break;
2113 default: printf("FD/HD"); break;
2116 if (extstat
& (MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
2123 (MII_ESTAT_1000TFD
|MII_ESTAT_1000THD
))
2125 case MII_ESTAT_1000TFD
: printf("FD"); break;
2126 case MII_ESTAT_1000THD
: printf("HD"); break;
2127 default: printf("FD/HD"); break;
2132 if (stat
& (MII_STATUS_100T4
|
2133 MII_STATUS_100XFD
| MII_STATUS_100XHD
|
2134 MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
2139 printf("100 Mbps: ");
2141 if (stat
& MII_STATUS_100T4
)
2146 if (stat
& (MII_STATUS_100XFD
| MII_STATUS_100XHD
))
2152 switch(stat
& (MII_STATUS_100XFD
|MII_STATUS_100XHD
))
2154 case MII_STATUS_100XFD
: printf("FD"); break;
2155 case MII_STATUS_100XHD
: printf("HD"); break;
2156 default: printf("FD/HD"); break;
2159 if (stat
& (MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
2165 switch(stat
& (MII_STATUS_100T2FD
|MII_STATUS_100T2HD
))
2167 case MII_STATUS_100T2FD
: printf("FD"); break;
2168 case MII_STATUS_100T2HD
: printf("HD"); break;
2169 default: printf("FD/HD"); break;
2173 if (stat
& (MII_STATUS_10FD
| MII_STATUS_10HD
))
2177 printf("10 Mbps: ");
2180 switch(stat
& (MII_STATUS_10FD
|MII_STATUS_10HD
))
2182 case MII_STATUS_10FD
: printf("FD"); break;
2183 case MII_STATUS_10HD
: printf("HD"); break;
2184 default: printf("FD/HD"); break;
2189 /*===========================================================================*
2191 *===========================================================================*/
2192 static void rl_clear_rx(rep
)
2200 rep
->re_clear_rx
= FALSE
;
2201 port
= rep
->re_base_port
;
2203 /* Reset the receiver */
2204 cr
= rl_inb(port
, RL_CR
);
2206 rl_outb(port
, RL_CR
, cr
);
2209 if (!(rl_inb(port
, RL_CR
) & RL_CR_RE
))
2211 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < HZ
);
2212 if (rl_inb(port
, RL_CR
) & RL_CR_RE
)
2213 panic("rtl8139","cannot disable receiver", NO_NUM
);
2216 printf("RBSTART = 0x%08x\n", rl_inl(port
, RL_RBSTART
));
2217 printf("CAPR = 0x%04x\n", rl_inw(port
, RL_CAPR
));
2218 printf("CBR = 0x%04x\n", rl_inw(port
, RL_CBR
));
2219 printf("RCR = 0x%08x\n", rl_inl(port
, RL_RCR
));
2222 rl_outb(port
, RL_CR
, cr
| RL_CR_RE
);
2224 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
2228 rep
->re_stat
.ets_missedP
++;
2231 /*===========================================================================*
2233 *===========================================================================*/
2234 static void rl_do_reset(rep
)
2237 rep
->re_need_reset
= FALSE
;
2242 if (rep
->re_flags
& REF_SEND_AVAIL
)
2244 rep
->re_tx
[rep
->re_tx_head
].ret_busy
= FALSE
;
2245 rep
->re_send_int
= TRUE
;
2249 /*===========================================================================*
2251 *===========================================================================*/
2252 static void rl_getstat(mp
)
2260 if (port
< 0 || port
>= RE_PORT_NR
)
2261 panic("rtl8139","illegal port", port
);
2262 rep
= &re_table
[port
];
2263 rep
->re_client
= mp
->DL_PROC
;
2265 assert(rep
->re_mode
== REM_ENABLED
);
2266 assert(rep
->re_flags
& REF_ENABLED
);
2268 stats
= rep
->re_stat
;
2270 r
= sys_datacopy(SELF
, (vir_bytes
) &stats
, mp
->DL_PROC
,
2271 (vir_bytes
) mp
->DL_ADDR
, sizeof(stats
));
2273 panic(__FILE__
, "rl_getstat: sys_datacopy failed", r
);
2274 reply(rep
, OK
, FALSE
);
2277 /*===========================================================================*
2279 *===========================================================================*/
2280 static void rl_getstat_s(mp
)
2288 if (port
< 0 || port
>= RE_PORT_NR
)
2289 panic("rtl8139","illegal port", port
);
2290 rep
= &re_table
[port
];
2291 rep
->re_client
= mp
->DL_PROC
;
2293 assert(rep
->re_mode
== REM_ENABLED
);
2294 assert(rep
->re_flags
& REF_ENABLED
);
2296 stats
= rep
->re_stat
;
2298 r
= sys_safecopyto(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
2299 (vir_bytes
) &stats
, sizeof(stats
), D
);
2301 panic(__FILE__
, "rl_getstat_s: sys_safecopyto failed", r
);
2302 reply(rep
, OK
, FALSE
);
2306 /*===========================================================================*
2308 *===========================================================================*/
2309 static void rl_getname(mp
)
2314 strncpy(mp
->DL_NAME
, progname
, sizeof(mp
->DL_NAME
));
2315 mp
->DL_NAME
[sizeof(mp
->DL_NAME
)-1]= '\0';
2316 mp
->m_type
= DL_NAME_REPLY
;
2317 r
= send(mp
->m_source
, mp
);
2319 panic("RTL8139", "rl_getname: send failed: %d\n", r
);
2323 /*===========================================================================*
2325 *===========================================================================*/
2326 static void reply(rep
, err
, may_block
)
2337 if (rep
->re_flags
& REF_PACK_SENT
)
2338 status
|= DL_PACK_SEND
;
2339 if (rep
->re_flags
& REF_PACK_RECV
)
2340 status
|= DL_PACK_RECV
;
2342 reply
.m_type
= DL_TASK_REPLY
;
2343 reply
.DL_PORT
= rep
- re_table
;
2344 reply
.DL_PROC
= rep
->re_client
;
2345 reply
.DL_STAT
= status
| ((u32_t
) err
<< 16);
2346 reply
.DL_COUNT
= rep
->re_read_s
;
2347 if (OK
!= (r
= getuptime(&now
)))
2348 panic("rtl8139","getuptime() failed:", r
);
2349 reply
.DL_CLCK
= now
;
2351 r
= send(rep
->re_client
, &reply
);
2353 if (r
== ELOCKED
&& may_block
)
2356 printW(); printf("send locked\n");
2362 printf("RTL8139 tried sending to %d, type %d\n", rep
->re_client
, reply
.m_type
);
2363 panic("rtl8139","send failed:", r
);
2367 rep
->re_flags
&= ~(REF_PACK_SENT
| REF_PACK_RECV
);
2370 /*===========================================================================*
2372 *===========================================================================*/
2373 static void mess_reply(req
, reply_mess
)
2375 message
*reply_mess
;
2377 if (send(req
->m_source
, reply_mess
) != OK
)
2378 panic("rtl8139","unable to mess_reply", NO_NUM
);
2382 static void dump_phy(rep
)
2388 port
= rep
->re_base_port
;
2390 t
= rl_inb(port
, RL_MSR
);
2391 printf("MSR: 0x%02lx\n", t
);
2392 if (t
& RL_MSR_SPEED_10
)
2393 printf("\t10 Mbps\n");
2394 if (t
& RL_MSR_LINKB
)
2395 printf("\tLink failed\n");
2397 t
= rl_inb(port
, RL_CONFIG1
);
2398 printf("CONFIG1: 0x%02lx\n", t
);
2400 t
= rl_inb(port
, RL_CONFIG3
);
2401 printf("CONFIG3: 0x%02lx\n", t
);
2403 t
= rl_inb(port
, RL_CONFIG4
);
2404 printf("CONFIG4: 0x%02lx\n", t
);
2406 t
= rl_inw(port
, RL_BMCR
);
2407 printf("BMCR (MII_CTRL): 0x%04lx\n", t
);
2409 t
= rl_inw(port
, RL_BMSR
);
2411 if (t
& MII_STATUS_100T4
)
2412 printf(" 100Base-T4");
2413 if (t
& MII_STATUS_100XFD
)
2414 printf(" 100Base-X-FD");
2415 if (t
& MII_STATUS_100XHD
)
2416 printf(" 100Base-X-HD");
2417 if (t
& MII_STATUS_10FD
)
2418 printf(" 10Mbps-FD");
2419 if (t
& MII_STATUS_10HD
)
2420 printf(" 10Mbps-HD");
2421 if (t
& MII_STATUS_100T2FD
)
2422 printf(" 100Base-T2-FD");
2423 if (t
& MII_STATUS_100T2HD
)
2424 printf(" 100Base-T2-HD");
2425 if (t
& MII_STATUS_EXT_STAT
)
2426 printf(" Ext-stat");
2427 if (t
& MII_STATUS_RES
)
2428 printf(" res-0x%lx", t
& MII_STATUS_RES
);
2429 if (t
& MII_STATUS_MFPS
)
2431 if (t
& MII_STATUS_ANC
)
2433 if (t
& MII_STATUS_RF
)
2434 printf(" remote-fault");
2435 if (t
& MII_STATUS_ANA
)
2437 if (t
& MII_STATUS_LS
)
2439 if (t
& MII_STATUS_JD
)
2441 if (t
& MII_STATUS_EC
)
2442 printf(" Extended-capability");
2445 t
= rl_inw(port
, RL_ANAR
);
2446 printf("ANAR (MII_ANA): 0x%04lx\n", t
);
2448 t
= rl_inw(port
, RL_ANLPAR
);
2449 printf("ANLPAR: 0x%04lx\n", t
);
2451 t
= rl_inw(port
, RL_ANER
);
2452 printf("ANER (MII_ANE): ");
2453 if (t
& MII_ANE_RES
)
2454 printf(" res-0x%lx", t
& MII_ANE_RES
);
2455 if (t
& MII_ANE_PDF
)
2456 printf(" Par-Detect-Fault");
2457 if (t
& MII_ANE_LPNPA
)
2458 printf(" LP-Next-Page-Able");
2459 if (t
& MII_ANE_NPA
)
2460 printf(" Loc-Next-Page-Able");
2462 printf(" Page-Received");
2463 if (t
& MII_ANE_LPANA
)
2464 printf(" LP-Auto-Neg-Able");
2467 t
= rl_inw(port
, RL_NWAYTR
);
2468 printf("NWAYTR: 0x%04lx\n", t
);
2469 t
= rl_inw(port
, RL_CSCR
);
2470 printf("CSCR: 0x%04lx\n", t
);
2472 t
= rl_inb(port
, RL_CONFIG5
);
2473 printf("CONFIG5: 0x%02lx\n", t
);
2477 static int do_hard_int(void)
2481 for (i
=0; i
< RE_PORT_NR
; i
++) {
2483 /* Run interrupt handler at driver level. */
2484 rl_handler( &re_table
[i
]);
2486 /* Reenable interrupts for this hook. */
2487 if ((s
=sys_irqenable(&re_table
[i
].re_hook_id
)) != OK
)
2488 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
2492 /*===========================================================================*
2494 *===========================================================================*/
2495 static int rl_handler(rep
)
2498 int i
, port
, tx_head
, tx_tail
, link_up
;
2500 u32_t tsd
, tcr
, ertxth
;
2505 int_event_check
= FALSE
; /* disable check by default */
2507 port
= rep
->re_base_port
;
2510 isr
= rl_inw(port
, RL_ISR
);
2511 rl_outw(port
, RL_ISR
, isr
);
2513 if (isr
& RL_IMR_FOVW
)
2515 isr
&= ~RL_IMR_FOVW
;
2516 /* Should do anything? */
2518 rep
->re_stat
.ets_fifoOver
++;
2520 if (isr
& RL_IMR_PUN
)
2524 /* Either the link status changed or there was a TX fifo
2527 link_up
= !(rl_inb(port
, RL_MSR
) & RL_MSR_LINKB
);
2528 if (link_up
!= rep
->re_link_up
)
2530 rep
->re_report_link
= TRUE
;
2531 rep
->re_got_int
= TRUE
;
2532 int_event_check
= TRUE
;
2535 if (isr
& RL_IMR_RXOVW
)
2537 isr
&= ~RL_IMR_RXOVW
;
2539 /* Clear the receive buffer */
2540 rep
->re_clear_rx
= TRUE
;
2541 rep
->re_got_int
= TRUE
;
2542 int_event_check
= TRUE
;
2545 if (isr
& (RL_ISR_RER
| RL_ISR_ROK
))
2547 isr
&= ~(RL_ISR_RER
| RL_ISR_ROK
);
2549 if (!rep
->re_got_int
&& (rep
->re_flags
& REF_READING
))
2551 rep
->re_got_int
= TRUE
;
2552 int_event_check
= TRUE
;
2556 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) &&
2557 (rep
->re_flags
& REF_SEND_AVAIL
) &&
2558 (rep
->re_tx
[0].ret_busy
|| rep
->re_tx
[1].ret_busy
||
2559 rep
->re_tx
[2].ret_busy
|| rep
->re_tx
[3].ret_busy
))
2563 "rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
2564 rep
->re_tx_head
, rep
->re_tx_tail
,
2565 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2566 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2568 "rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
2569 rl_inw(port
, RL_TSAD
),
2570 rl_inl(port
, RL_TSD0
+0*4),
2571 rl_inl(port
, RL_TSD0
+1*4),
2572 rl_inl(port
, RL_TSD0
+2*4),
2573 rl_inl(port
, RL_TSD0
+3*4));
2576 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) || 1)
2578 isr
&= ~(RL_ISR_TER
| RL_ISR_TOK
);
2580 tsad
= rl_inw(port
, RL_TSAD
);
2581 if (tsad
& (RL_TSAD_TABT0
|RL_TSAD_TABT1
|
2582 RL_TSAD_TABT2
|RL_TSAD_TABT3
))
2585 /* Do we need a watch dog? */
2586 /* Just reset the whole chip */
2587 rep
->re_need_reset
= TRUE
;
2588 rep
->re_got_int
= TRUE
;
2589 int_event_check
= TRUE
;
2591 /* Reset transmitter */
2592 rep
->re_stat
.ets_transAb
++;
2594 cr
= rl_inb(port
, RL_CR
);
2596 rl_outb(port
, RL_CR
, cr
);
2599 if (!(rl_inb(port
, RL_CR
) & RL_CR_TE
))
2601 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < HZ
);
2602 if (rl_inb(port
, RL_CR
) & RL_CR_TE
)
2604 panic("rtl8139","cannot disable transmitter",
2607 rl_outb(port
, RL_CR
, cr
| RL_CR_TE
);
2609 tcr
= rl_inl(port
, RL_TCR
);
2610 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_IFG_STD
);
2612 printf("rl_handler: reset after abort\n");
2614 if (rep
->re_flags
& REF_SEND_AVAIL
)
2616 printf("rl_handler: REF_SEND_AVAIL\n");
2617 rep
->re_send_int
= TRUE
;
2618 rep
->re_got_int
= TRUE
;
2619 int_event_check
= TRUE
;
2621 for (i
= 0; i
< N_TX_BUF
; i
++)
2622 rep
->re_tx
[i
].ret_busy
= FALSE
;
2625 printf("rl_handler, TABT, tasd = 0x%04x\n",
2628 /* Find the aborted transmit request */
2629 for (i
= 0; i
< N_TX_BUF
; i
++)
2631 tsd
= rl_inl(port
, RL_TSD0
+i
*4);
2632 if (tsd
& RL_TSD_TABT
)
2638 "rl_handler: can't find aborted TX req.\n");
2642 printf("TSD%d = 0x%04lx\n", i
, tsd
);
2644 /* Set head and tail to this buffer */
2645 rep
->re_tx_head
= rep
->re_tx_tail
= i
;
2648 /* Aborted transmission, just kick the device
2649 * and be done with it.
2651 rep
->re_stat
.ets_transAb
++;
2652 tcr
= rl_inl(port
, RL_TCR
);
2653 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
2657 /* Transmit completed */
2658 tx_head
= rep
->re_tx_head
;
2659 tx_tail
= rep
->re_tx_tail
;
2660 for (i
= 0; i
< 2*N_TX_BUF
; i
++)
2662 if (!rep
->re_tx
[tx_tail
].ret_busy
)
2664 /* Strange, this buffer is not in-use.
2665 * Increment tx_tail until tx_head is
2666 * reached (or until we find a buffer that
2669 if (tx_tail
== tx_head
)
2671 if (++tx_tail
>= N_TX_BUF
)
2673 assert(tx_tail
< RL_N_TX
);
2674 rep
->re_tx_tail
= tx_tail
;
2677 tsd
= rl_inl(port
, RL_TSD0
+tx_tail
*4);
2678 if (!(tsd
& RL_TSD_OWN
))
2680 /* Buffer is not yet ready */
2684 /* Should collect statistics */
2685 if (tsd
& RL_TSD_CRS
)
2686 rep
->re_stat
.ets_carrSense
++;
2687 if (tsd
& RL_TSD_TABT
)
2689 printf("rl_handler, TABT, TSD%d = 0x%04lx\n",
2691 assert(0); /* CLRABT is not all that
2692 * effective, why not?
2694 rep
->re_stat
.ets_transAb
++;
2695 tcr
= rl_inl(port
, RL_TCR
);
2696 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
2698 if (tsd
& RL_TSD_OWC
)
2699 rep
->re_stat
.ets_OWC
++;
2700 if (tsd
& RL_TSD_CDH
)
2701 rep
->re_stat
.ets_CDheartbeat
++;
2703 /* What about collisions? */
2704 if (tsd
& RL_TSD_TOK
)
2705 rep
->re_stat
.ets_packetT
++;
2707 rep
->re_stat
.ets_sendErr
++;
2708 if (tsd
& RL_TSD_TUN
)
2710 rep
->re_stat
.ets_fifoUnder
++;
2712 /* Increase ERTXTH */
2713 ertxth
= tsd
+ (1 << RL_TSD_ERTXTH_S
);
2714 ertxth
&= RL_TSD_ERTXTH_M
;
2715 if (debug
&& ertxth
> rep
->re_ertxth
)
2717 printf("%s: new ertxth: %ld bytes\n",
2719 (ertxth
>> RL_TSD_ERTXTH_S
) *
2721 rep
->re_ertxth
= ertxth
;
2724 rep
->re_tx
[tx_tail
].ret_busy
= FALSE
;
2727 if (rep
->re_flags
& REF_SEND_AVAIL
)
2729 printf("TSD%d: %08lx\n", tx_tail
, tsd
);
2731 "rl_handler: head %d, tail %d, busy: %d %d %d %d\n",
2733 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2734 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2738 if (++tx_tail
>= N_TX_BUF
)
2740 assert(tx_tail
< RL_N_TX
);
2741 rep
->re_tx_tail
= tx_tail
;
2743 if (rep
->re_flags
& REF_SEND_AVAIL
)
2746 printf("rl_handler: REF_SEND_AVAIL\n");
2748 rep
->re_send_int
= TRUE
;
2749 if (!rep
->re_got_int
)
2751 rep
->re_got_int
= TRUE
;
2752 int_event_check
= TRUE
;
2756 assert(i
< 2*N_TX_BUF
);
2760 printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
2767 /*===========================================================================*
2769 *===========================================================================*/
2770 static void rl_watchdog_f(tp
)
2775 /* Use a synchronous alarm instead of a watchdog timer. */
2776 sys_setalarm(HZ
, 0);
2778 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
2780 if (rep
->re_mode
!= REM_ENABLED
)
2782 if (!(rep
->re_flags
& REF_SEND_AVAIL
))
2784 /* Assume that an idle system is alive */
2785 rep
->re_tx_alive
= TRUE
;
2788 if (rep
->re_tx_alive
)
2790 rep
->re_tx_alive
= FALSE
;
2793 printf("rl_watchdog_f: resetting port %d\n", i
);
2795 "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
2796 rl_inw(rep
->re_base_port
, RL_TSAD
),
2797 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
2798 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
2799 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
2800 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
2801 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
2802 rep
->re_tx_head
, rep
->re_tx_tail
,
2803 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2804 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2805 rep
->re_need_reset
= TRUE
;
2806 rep
->re_got_int
= TRUE
;
2814 _PROTOTYPE( static void rtl_init
, (struct dpeth
*dep
) );
2815 _PROTOTYPE( static u16_t get_ee_word
, (dpeth_t
*dep
, int a
) );
2816 _PROTOTYPE( static void ee_wen
, (dpeth_t
*dep
) );
2817 _PROTOTYPE( static void set_ee_word
, (dpeth_t
*dep
, int a
, U16_t w
) );
2818 _PROTOTYPE( static void ee_wds
, (dpeth_t
*dep
) );
2820 static void rtl_init(dep
)
2823 u8_t reg_a
, reg_b
, cr
, config0
, config2
, config3
;
2827 printf("rtl_init called\n");
2831 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2832 reg_a
= inb_reg0(dep
, DP_DUM1
);
2833 reg_b
= inb_reg0(dep
, DP_DUM2
);
2835 printf("rtl_init: '%c', '%c'\n", reg_a
, reg_b
);
2837 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2838 config0
= inb_reg3(dep
, 3);
2839 config2
= inb_reg3(dep
, 5);
2840 config3
= inb_reg3(dep
, 6);
2841 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2843 printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
2844 config0
, config2
, config3
);
2846 if (0 == sys_getkenv("RTL8029FD",9+1, val
, sizeof(val
)))
2848 printf("rtl_init: setting full-duplex mode\n");
2849 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2851 cr
= inb_reg3(dep
, 1);
2852 outb_reg3(dep
, 1, cr
| 0xc0);
2854 outb_reg3(dep
, 6, config3
| 0x40);
2855 config3
= inb_reg3(dep
, 6);
2857 config2
= inb_reg3(dep
, 5);
2858 outb_reg3(dep
, 5, config2
| 0x20);
2859 config2
= inb_reg3(dep
, 5);
2861 outb_reg3(dep
, 1, cr
);
2863 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2865 printf("rtl_init: config 2 = %x\n", config2
);
2866 printf("rtl_init: config 3 = %x\n", config3
);
2869 for (i
= 0; i
<64; i
++)
2870 printf("%x ", get_ee_word(dep
, i
));
2873 if (0 == sys_getkenv("RTL8029MN",9+1, val
, sizeof(val
)))
2877 set_ee_word(dep
, 0x78/2, 0x10ec);
2878 set_ee_word(dep
, 0x7A/2, 0x8029);
2879 set_ee_word(dep
, 0x7C/2, 0x10ec);
2880 set_ee_word(dep
, 0x7E/2, 0x8029);
2884 assert(get_ee_word(dep
, 0x78/2) == 0x10ec);
2885 assert(get_ee_word(dep
, 0x7A/2) == 0x8029);
2886 assert(get_ee_word(dep
, 0x7C/2) == 0x10ec);
2887 assert(get_ee_word(dep
, 0x7E/2) == 0x8029);
2890 if (0 == sys_getkenv("RTL8029XXX",10+1, val
, sizeof(val
)))
2894 set_ee_word(dep
, 0x76/2, 0x8029);
2898 assert(get_ee_word(dep
, 0x76/2) == 0x8029);
2902 static u16_t
get_ee_word(dep
, a
)
2909 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2911 /* Switch to 9346 mode and enable CS */
2912 outb_reg3(dep
, 1, 0x80 | 0x8);
2914 cmd
= 0x180 | (a
& 0x3f); /* 1 1 0 a5 a4 a3 a2 a1 a0 */
2915 for (i
= 8; i
>= 0; i
--)
2917 b
= (cmd
& (1 << i
));
2920 /* Cmd goes out on the rising edge of the clock */
2921 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2922 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2924 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2927 for (i
= 0; i
<16; i
++)
2931 /* Data is shifted out on the rising edge. Read at the
2934 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4);
2935 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2936 b
= inb_reg3(dep
, 1);
2940 outb_reg3(dep
, 1, 0x80); /* drop CS */
2941 outb_reg3(dep
, 1, 0x00); /* back to normal */
2942 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
2947 static void ee_wen(dep
)
2953 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2955 /* Switch to 9346 mode and enable CS */
2956 outb_reg3(dep
, 1, 0x80 | 0x8);
2958 cmd
= 0x130; /* 1 0 0 1 1 x x x x */
2959 for (i
= 8; i
>= 0; i
--)
2961 b
= (cmd
& (1 << i
));
2964 /* Cmd goes out on the rising edge of the clock */
2965 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2966 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2968 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2969 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2970 /* micro_delay(1); */ /* Is this required? */
2973 static void set_ee_word(dep
, a
, w
)
2981 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
2983 cmd
= 0x140 | (a
& 0x3f); /* 1 0 1 a5 a4 a3 a2 a1 a0 */
2984 for (i
= 8; i
>= 0; i
--)
2986 b
= (cmd
& (1 << i
));
2989 /* Cmd goes out on the rising edge of the clock */
2990 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2991 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2993 for (i
= 15; i
>= 0; i
--)
2998 /* Cmd goes out on the rising edge of the clock */
2999 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
3000 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
3002 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of data */
3003 outb_reg3(dep
, 1, 0x80); /* Drop CS */
3004 /* micro_delay(1); */ /* Is this required? */
3005 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
3008 if (inb_reg3(dep
, 1) & 1)
3010 } while (getuptime(&t1
) == OK
&& (t1
== t0
));
3011 if (!(inb_reg3(dep
, 1) & 1))
3012 panic("set_ee_word","device remains busy", NO_NUM
);
3015 static void ee_wds(dep
)
3021 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
3023 /* Switch to 9346 mode and enable CS */
3024 outb_reg3(dep
, 1, 0x80 | 0x8);
3026 cmd
= 0x100; /* 1 0 0 0 0 x x x x */
3027 for (i
= 8; i
>= 0; i
--)
3029 b
= (cmd
& (1 << i
));
3032 /* Cmd goes out on the rising edge of the clock */
3033 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
3034 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
3036 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
3037 outb_reg3(dep
, 1, 0x80); /* Drop CS */
3038 outb_reg3(dep
, 1, 0x00); /* back to normal */
3039 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
3044 * $PchId: rtl8139.c,v 1.3 2003/09/11 14:15:15 philip Exp $