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_PORT 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 * m_type DL_PORT DL_STAT
47 * |------------|---------|-----------|
48 * |DL_STAT_REPL| port nr | err |
49 * |------------|---------|-----------|
51 * Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
53 * Aug 15, 2004 sync alarms replace watchdogs timers (Jorrit N. Herder)
54 * May 02, 2004 flag alarms replace micro_elapsed() (Jorrit N. Herder)
58 #define RTL8139_FKEY 0 /* Use function key to dump RTL8139 status */
69 { 0x10ec, 0x8139, 0 }, /* Realtek RTL8139 */
72 { 0x02ac, 0x1012, 0 }, /* SpeedStream 1012 PCMCIA 10/100 */
73 { 0x1065, 0x8139, 0 }, /* Texas Microsystems 8139C Network Card */
74 { 0x1113, 0x1211, 0 }, /* Accton MPX5030 or SMC1211TX EZCard 10/100 */
75 { 0x1186, 0x1300, 0 }, /* D-Link DFE530TX+/DFE538TX */
76 { 0x1186, 0x1340, 0 }, /* D-Link DFE690TXD */
77 { 0x11db, 0x1234, 0 }, /* Sega Dreamcast HIT-400 */
78 { 0x1259, 0xa117, 0 }, /* Allied Telesyn 8139 */
79 { 0x1259, 0xa11e, 0 }, /* Allied Telesyn 8139 */
80 { 0x126c, 0x1211, 0 }, /* Northern Telecom 10/100BaseTX*/
81 { 0x13d1, 0xab06, 0 }, /* AboCom FE2000VX */
82 { 0x1432, 0x9130, 0 }, /* Edimax Computer Co. RTL81xx */
83 { 0x14ea, 0xab06, 0 }, /* Planex FNW-3603-TX */
84 { 0x14ea, 0xab07, 0 }, /* Planex FNW-3800-TX */
85 { 0x1500, 0x1360, 0 }, /* Delta Electronics RealTek Ethernet */
86 { 0x1743, 0x8139, 0 }, /* Peppercon AG 8139 ROL/F-100 */
87 { 0x4033, 0x1360, 0 }, /* Addtron Technology 8139 */
92 PUBLIC re_t re_table
[RE_PORT_NR
];
94 static u16_t eth_ign_proto
;
95 static tmra_ut rl_watchdog
;
97 FORWARD
_PROTOTYPE( unsigned my_inb
, (U16_t port
) );
98 FORWARD
_PROTOTYPE( unsigned my_inw
, (U16_t port
) );
99 FORWARD
_PROTOTYPE( unsigned my_inl
, (U16_t port
) );
100 static unsigned my_inb(U16_t port
) {
103 if ((s
=sys_inb(port
, &value
)) !=OK
)
104 printf("RTL8139: warning, sys_inb failed: %d\n", s
);
107 static unsigned my_inw(U16_t port
) {
110 if ((s
=sys_inw(port
, &value
)) !=OK
)
111 printf("RTL8139: warning, sys_inw failed: %d\n", s
);
114 static unsigned my_inl(U16_t port
) {
117 if ((s
=sys_inl(port
, &value
)) !=OK
)
118 printf("RTL8139: warning, sys_inl failed: %d\n", s
);
121 #define rl_inb(port, offset) (my_inb((port) + (offset)))
122 #define rl_inw(port, offset) (my_inw((port) + (offset)))
123 #define rl_inl(port, offset) (my_inl((port) + (offset)))
125 FORWARD
_PROTOTYPE( void my_outb
, (U16_t port
, U8_t value
) );
126 FORWARD
_PROTOTYPE( void my_outw
, (U16_t port
, U16_t value
) );
127 FORWARD
_PROTOTYPE( void my_outl
, (U16_t port
, U32_t value
) );
128 static void my_outb(U16_t port
, U8_t value
) {
130 if ((s
=sys_outb(port
, value
)) !=OK
)
131 printf("RTL8139: warning, sys_outb failed: %d\n", s
);
133 static void my_outw(U16_t port
, U16_t value
) {
135 if ((s
=sys_outw(port
, value
)) !=OK
)
136 printf("RTL8139: warning, sys_outw failed: %d\n", s
);
138 static void my_outl(U16_t port
, U32_t value
) {
140 if ((s
=sys_outl(port
, value
)) !=OK
)
141 printf("RTL8139: warning, sys_outl failed: %d\n", s
);
143 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value)))
144 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
145 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
147 _PROTOTYPE( static void rl_init
, (message
*mp
) );
148 _PROTOTYPE( static void rl_pci_conf
, (void) );
149 _PROTOTYPE( static int rl_probe
, (re_t
*rep
) );
150 _PROTOTYPE( static void rl_conf_hw
, (re_t
*rep
) );
151 _PROTOTYPE( static void rl_init_buf
, (re_t
*rep
) );
152 _PROTOTYPE( static void rl_init_hw
, (re_t
*rep
) );
153 _PROTOTYPE( static void rl_reset_hw
, (re_t
*rep
) );
154 _PROTOTYPE( static void rl_confaddr
, (re_t
*rep
) );
155 _PROTOTYPE( static void rl_rec_mode
, (re_t
*rep
) );
156 _PROTOTYPE( static void rl_readv
, (message
*mp
, int from_int
,
158 _PROTOTYPE( static void rl_readv_s
, (message
*mp
, int from_int
) );
159 _PROTOTYPE( static void rl_writev
, (message
*mp
, int from_int
,
161 _PROTOTYPE( static void rl_writev_s
, (message
*mp
, int from_int
) );
162 _PROTOTYPE( static void rl_check_ints
, (re_t
*rep
) );
163 _PROTOTYPE( static void rl_report_link
, (re_t
*rep
) );
164 _PROTOTYPE( static void mii_print_techab
, (U16_t techab
) );
165 _PROTOTYPE( static void mii_print_stat_speed
, (U16_t stat
,
167 _PROTOTYPE( static void rl_clear_rx
, (re_t
*rep
) );
168 _PROTOTYPE( static void rl_do_reset
, (re_t
*rep
) );
169 _PROTOTYPE( static void rl_getstat
, (message
*mp
) );
170 _PROTOTYPE( static void rl_getstat_s
, (message
*mp
) );
171 _PROTOTYPE( static void rl_getname
, (message
*mp
) );
172 _PROTOTYPE( static void reply
, (re_t
*rep
, int err
, int may_block
) );
173 _PROTOTYPE( static void mess_reply
, (message
*req
, message
*reply
) );
174 _PROTOTYPE( static void rtl8139_stop
, (void) );
175 _PROTOTYPE( static void check_int_events
, (void) );
176 _PROTOTYPE( static int do_hard_int
, (void) );
177 _PROTOTYPE( static void rtl8139_dump
, (message
*m
) );
179 _PROTOTYPE( static void dump_phy
, (re_t
*rep
) );
181 _PROTOTYPE( static int rl_handler
, (re_t
*rep
) );
182 _PROTOTYPE( static void rl_watchdog_f
, (timer_t
*tp
) );
183 _PROTOTYPE( static void tell_dev
, (vir_bytes start
, size_t size
,
184 int pci_bus
, int pci_dev
, int pci_func
) );
186 /* The message used in the main loop is made global, so that rl_watchdog_f()
187 * can change its message type to fake an interrupt message.
190 PRIVATE
int int_event_check
; /* set to TRUE if events arrived */
192 static char *progname
;
196 /* SEF functions and variables. */
197 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
198 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
199 EXTERN
_PROTOTYPE( void sef_cb_lu_prepare
, (int state
) );
200 EXTERN
_PROTOTYPE( int sef_cb_lu_state_isvalid
, (int state
) );
201 EXTERN
_PROTOTYPE( void sef_cb_lu_state_dump
, (int state
) );
203 EXTERN
char **env_argv
;
205 /*===========================================================================*
207 *===========================================================================*/
208 int main(int argc
, char *argv
[])
212 /* SEF local startup. */
213 env_setargs(argc
, argv
);
218 if ((r
= sef_receive(ANY
, &m
)) != OK
)
219 panic("rtl8139","sef_receive failed", r
);
221 if (is_notify(m
.m_type
)) {
222 switch (_ENDPOINT_P(m
.m_source
)) {
225 * Under MINIX, synchronous alarms are
226 * used instead of watchdog functions.
227 * The approach is very different: MINIX
228 * VMD timeouts are handled within the
229 * kernel (the watchdog is executed by
230 * CLOCK), and notify() the driver in
231 * some cases. MINIX timeouts result in
232 * a SYN_ALARM message to the driver and
233 * thus are handled where they should be
234 * handled. Locally, watchdog functions
251 if (getsigset(&set
) != 0) break;
253 if (sigismember(&set
, SIGTERM
))
259 panic("rtl8139","illegal notify from",
263 /* done, get nwe message */
269 case DL_WRITE
: rl_writev(&m
, FALSE
, FALSE
); break;
270 case DL_WRITEV
: rl_writev(&m
, FALSE
, TRUE
); break;
271 case DL_WRITEV_S
: rl_writev_s(&m
, FALSE
); break;
272 case DL_READ
: rl_readv(&m
, FALSE
, FALSE
); break;
273 case DL_READV
: rl_readv(&m
, FALSE
, TRUE
); break;
274 case DL_READV_S
: rl_readv_s(&m
, FALSE
); break;
275 case DL_CONF
: rl_init(&m
); break;
276 case DL_GETSTAT
: rl_getstat(&m
); break;
277 case DL_GETSTAT_S
: rl_getstat_s(&m
); break;
278 case DL_GETNAME
: rl_getname(&m
); break;
280 case DL_STOP
: do_stop(&m
); break;
283 panic("rtl8139","illegal message", m
.m_type
);
288 /*===========================================================================*
289 * sef_local_startup *
290 *===========================================================================*/
291 PRIVATE
void sef_local_startup()
293 /* Register init callbacks. */
294 sef_setcb_init_fresh(sef_cb_init_fresh
);
295 sef_setcb_init_lu(sef_cb_init_fresh
);
296 sef_setcb_init_restart(sef_cb_init_fresh
);
298 /* Register live update callbacks. */
299 sef_setcb_lu_prepare(sef_cb_lu_prepare
);
300 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid
);
301 sef_setcb_lu_state_dump(sef_cb_lu_state_dump
);
303 /* Let SEF perform startup. */
307 /*===========================================================================*
308 * sef_cb_init_fresh *
309 *===========================================================================*/
310 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*info
)
312 /* Initialize the rtl8139 driver. */
321 system_hz
= sys_hz();
323 (progname
=strrchr(env_argv
[0],'/')) ? progname
++
324 : (progname
=env_argv
[0]);
327 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v
, 0x0000L
, 0xFFFFL
);
328 eth_ign_proto
= htons((u16_t
) v
);
331 /* Observe some function key for debug dumps. */
332 fkeys
= sfkeys
= 0; bit_set(sfkeys
, 9);
333 if ((r
=fkey_map(&fkeys
, &sfkeys
)) != OK
)
334 printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r
);
337 /* Claim buffer memory now under Minix, before MM takes it all. */
338 for (rep
= &re_table
[0]; rep
< re_table
+RE_PORT_NR
; rep
++)
341 /* Try to notify INET that we are present (again). If INET cannot
342 * be found, assume this is the first time we started and INET is
345 r
= ds_retrieve_label_num("inet", &inet_proc_nr
);
347 notify(inet_proc_nr
);
349 printf("rtl8139: ds_retrieve_label_num failed for 'inet': %d\n",
355 /*===========================================================================*
357 *===========================================================================*/
358 static void check_int_events(void)
362 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
364 if (rep
->re_mode
!= REM_ENABLED
)
366 if (!rep
->re_got_int
)
369 assert(rep
->re_flags
& REF_ENABLED
);
374 /*===========================================================================*
376 *===========================================================================*/
377 static void rtl8139_stop()
382 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
384 if (rep
->re_mode
!= REM_ENABLED
)
386 rl_outb(rep
->re_base_port
, RL_CR
, 0);
391 /*===========================================================================*
393 *===========================================================================*/
394 static void rtl8139_dump(m
)
395 message
*m
; /* pointer to request message */
401 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
403 if (rep
->re_mode
== REM_DISABLED
)
404 printf("Realtek RTL 8139 port %d is disabled\n", i
);
406 if (rep
->re_mode
!= REM_ENABLED
)
409 printf("Realtek RTL 8139 statistics of port %d:\n", i
);
411 printf("recvErr :%8ld\t", rep
->re_stat
.ets_recvErr
);
412 printf("sendErr :%8ld\t", rep
->re_stat
.ets_sendErr
);
413 printf("OVW :%8ld\n", rep
->re_stat
.ets_OVW
);
415 printf("CRCerr :%8ld\t", rep
->re_stat
.ets_CRCerr
);
416 printf("frameAll :%8ld\t", rep
->re_stat
.ets_frameAll
);
417 printf("missedP :%8ld\n", rep
->re_stat
.ets_missedP
);
419 printf("packetR :%8ld\t", rep
->re_stat
.ets_packetR
);
420 printf("packetT :%8ld\t", rep
->re_stat
.ets_packetT
);
421 printf("transDef :%8ld\n", rep
->re_stat
.ets_transDef
);
423 printf("collision :%8ld\t", rep
->re_stat
.ets_collision
);
424 printf("transAb :%8ld\t", rep
->re_stat
.ets_transAb
);
425 printf("carrSense :%8ld\n", rep
->re_stat
.ets_carrSense
);
427 printf("fifoUnder :%8ld\t", rep
->re_stat
.ets_fifoUnder
);
428 printf("fifoOver :%8ld\t", rep
->re_stat
.ets_fifoOver
);
429 printf("CDheartbeat:%8ld\n", rep
->re_stat
.ets_CDheartbeat
);
431 printf("OWC :%8ld\t", rep
->re_stat
.ets_OWC
);
433 printf("re_flags = 0x%x\n", rep
->re_flags
);
436 "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
437 rl_inw(rep
->re_base_port
, RL_TSAD
),
438 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
439 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
440 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
441 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
442 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
443 rep
->re_tx_head
, rep
->re_tx_tail
,
444 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
445 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
449 /*===========================================================================*
451 *===========================================================================*/
452 static void rl_init(mp
)
455 static int first_time
= 1;
464 rl_pci_conf(); /* Configure PCI devices. */
466 tmra_inittimer(&rl_watchdog
);
467 /* Use a synchronous alarm instead of a watchdog timer. */
468 sys_setalarm(system_hz
, 0);
472 if (port
< 0 || port
>= RE_PORT_NR
)
474 reply_mess
.m_type
= DL_CONF_REPLY
;
475 reply_mess
.m3_i1
= ENXIO
;
476 mess_reply(mp
, &reply_mess
);
479 rep
= &re_table
[port
];
480 if (rep
->re_mode
== REM_DISABLED
)
482 /* This is the default, try to (re)locate the device. */
484 if (rep
->re_mode
== REM_DISABLED
)
486 /* Probe failed, or the device is configured off. */
487 reply_mess
.m_type
= DL_CONF_REPLY
;
488 reply_mess
.m3_i1
= ENXIO
;
489 mess_reply(mp
, &reply_mess
);
492 if (rep
->re_mode
== REM_ENABLED
)
494 #if VERBOSE /* load silently ... can always check status later */
499 assert(rep
->re_mode
== REM_ENABLED
);
500 assert(rep
->re_flags
& REF_ENABLED
);
502 rep
->re_flags
&= ~(REF_PROMISC
| REF_MULTI
| REF_BROAD
);
504 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
505 rep
->re_flags
|= REF_PROMISC
;
506 if (mp
->DL_MODE
& DL_MULTI_REQ
)
507 rep
->re_flags
|= REF_MULTI
;
508 if (mp
->DL_MODE
& DL_BROAD_REQ
)
509 rep
->re_flags
|= REF_BROAD
;
511 rep
->re_client
= mp
->m_source
;
514 reply_mess
.m_type
= DL_CONF_REPLY
;
515 reply_mess
.m3_i1
= mp
->DL_PORT
;
516 reply_mess
.m3_i2
= RE_PORT_NR
;
517 *(ether_addr_t
*) reply_mess
.m3_ca1
= rep
->re_address
;
519 mess_reply(mp
, &reply_mess
);
522 /*===========================================================================*
524 *===========================================================================*/
525 static void rl_pci_conf()
529 static char envvar
[] = RL_ENVVAR
"#";
530 static char envfmt
[] = "*:d.d.d";
531 static char val
[128];
534 for (i
= 0, rep
= re_table
; i
<RE_PORT_NR
; i
++, rep
++)
536 strcpy(rep
->re_name
, "rtl8139#0");
537 rep
->re_name
[8] += i
;
539 envvar
[sizeof(RL_ENVVAR
)-1]= '0'+i
;
540 if (0 == env_get_param(envvar
, val
, sizeof(val
)) &&
541 ! env_prefix(envvar
, "pci")) {
545 (void) env_parse(envvar
, envfmt
, 1, &v
, 0, 255);
548 (void) env_parse(envvar
, envfmt
, 2, &v
, 0, 255);
551 (void) env_parse(envvar
, envfmt
, 3, &v
, 0, 255);
557 for (h
= 1; h
>= 0; h
--) {
558 for (i
= 0, rep
= re_table
; i
<RE_PORT_NR
; i
++, rep
++)
560 if (((rep
->re_pcibus
| rep
->re_pcidev
|
561 rep
->re_pcifunc
) != 0) != h
)
571 /*===========================================================================*
573 *===========================================================================*/
574 static int rl_probe(rep
)
577 int i
, r
, devind
, just_one
;
583 if ((rep
->re_pcibus
| rep
->re_pcidev
| rep
->re_pcifunc
) != 0)
585 /* Look for specific PCI device */
586 r
= pci_find_dev(rep
->re_pcibus
, rep
->re_pcidev
,
587 rep
->re_pcifunc
, &devind
);
590 printf("%s: no PCI found at %d.%d.%d\n",
591 rep
->re_name
, rep
->re_pcibus
,
592 rep
->re_pcidev
, rep
->re_pcifunc
);
595 pci_ids(devind
, &vid
, &did
);
600 r
= pci_first_dev(&devind
, &vid
, &did
);
608 for (i
= 0; pcitab
[i
].vid
!= 0; i
++)
610 if (pcitab
[i
].vid
!= vid
)
612 if (pcitab
[i
].did
!= did
)
614 if (pcitab
[i
].checkclass
)
617 "class check not implemented", NO_NUM
);
621 if (pcitab
[i
].vid
!= 0)
627 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
628 rep
->re_name
, vid
, did
,
630 rep
->re_pcidev
, rep
->re_pcifunc
);
634 r
= pci_next_dev(&devind
, &vid
, &did
);
639 #if VERBOSE /* stay silent at startup, can always get status later */
640 dname
= pci_dev_name(vid
, did
);
642 dname
= "unknown device";
643 printf("%s: ", rep
->re_name
);
644 printf("%s (%x/%x) at %s\n", dname
, vid
, did
, pci_slot_name(devind
));
647 /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
648 bar
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
652 "base address is not properly configured", NO_NUM
);
654 rep
->re_base_port
= bar
;
656 ilr
= pci_attr_r8(devind
, PCI_ILR
);
660 printf("%s: using I/O address 0x%lx, IRQ %d\n",
661 rep
->re_name
, (unsigned long)bar
, ilr
);
667 /*===========================================================================*
669 *===========================================================================*/
670 static void rl_conf_hw(rep
)
673 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
675 rep
->re_mode
= REM_DISABLED
; /* Superfluous */
679 /* PCI device is present */
680 rep
->re_mode
= REM_ENABLED
;
682 if (rep
->re_mode
!= REM_ENABLED
)
685 rep
->re_flags
= REF_EMPTY
;
686 rep
->re_link_up
= -1; /* Unknown */
689 rep
->re_report_link
= 0;
691 rep
->re_need_reset
= 0;
696 rep
->re_ertxth
= RL_TSD_ERTXTH_8
;
697 rep
->re_stat
= empty_stat
;
700 /*===========================================================================*
702 *===========================================================================*/
703 static void rl_init_buf(rep
)
706 size_t rx_bufsize
, tx_bufsize
, tot_bufsize
;
711 /* Allocate receive and transmit buffers */
712 tx_bufsize
= ETH_MAX_PACK_SIZE_TAGGED
;
714 tx_bufsize
+= 4-(tx_bufsize
% 4); /* Align */
715 rx_bufsize
= RX_BUFSIZE
;
716 tot_bufsize
= N_TX_BUF
*tx_bufsize
+ rx_bufsize
;
718 if (tot_bufsize
% 4096)
719 tot_bufsize
+= 4096-(tot_bufsize
% 4096);
721 #define BUF_ALIGNMENT (64*1024)
723 if(!(mallocbuf
= alloc_contig(BUF_ALIGNMENT
+ tot_bufsize
, 0, &buf
))) {
724 panic("RTL8139","Couldn't allocate kernel buffer",i
);
727 /* click-align mallocced buffer. this is what we used to get
728 * from kmalloc() too.
730 if((off
= buf
% BUF_ALIGNMENT
)) {
731 mallocbuf
+= BUF_ALIGNMENT
- off
;
732 buf
+= BUF_ALIGNMENT
- off
;
735 tell_dev((vir_bytes
)mallocbuf
, tot_bufsize
, rep
->re_pcibus
,
736 rep
->re_pcidev
, rep
->re_pcifunc
);
738 for (i
= 0; i
<N_TX_BUF
; i
++)
740 rep
->re_tx
[i
].ret_buf
= buf
;
741 rep
->re_tx
[i
].v_ret_buf
= mallocbuf
;
743 mallocbuf
+= tx_bufsize
;
746 rep
->v_re_rx_buf
= mallocbuf
;
749 /*===========================================================================*
751 *===========================================================================*/
752 static void rl_init_hw(rep
)
757 rep
->re_flags
= REF_EMPTY
;
758 rep
->re_flags
|= REF_ENABLED
;
760 /* Set the interrupt handler. The policy is to only send HARD_INT
761 * notifications. Don't reenable interrupts automatically. The id
762 * that is passed back is the interrupt line number.
764 rep
->re_hook_id
= rep
->re_irq
;
765 if ((s
=sys_irqsetpolicy(rep
->re_irq
, 0, &rep
->re_hook_id
)) != OK
)
766 printf("RTL8139: error, couldn't set IRQ policy: %d\n", s
);
770 if ((s
=sys_irqenable(&rep
->re_hook_id
)) != OK
)
771 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
773 #if VERBOSE /* stay silent during startup, can always get status later */
775 printf("%s: model %s\n", rep
->re_name
, rep
->re_model
);
778 printf("%s: unknown model 0x%08x\n",
780 rl_inl(rep
->re_base_port
, RL_TCR
) &
781 (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
));
788 printf("%s: Ethernet address ", rep
->re_name
);
789 for (i
= 0; i
< 6; i
++)
791 printf("%x%c", rep
->re_address
.ea_addr
[i
],
797 /*===========================================================================*
799 *===========================================================================*/
800 static void rl_reset_hw(rep
)
809 port
= rep
->re_base_port
;
813 rl_outb(port
, RL_BMCR
, MII_CTRL_RST
);
816 if (!(rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
))
818 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
819 if (rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
)
820 panic("rtl8139","reset PHY failed to complete", NO_NUM
);
823 /* Reset the device */
824 printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
825 port
, rl_inb(port
, RL_CR
));
826 rl_outb(port
, RL_CR
, RL_CR_RST
);
829 if (!(rl_inb(port
, RL_CR
) & RL_CR_RST
))
831 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
832 printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
833 port
, rl_inb(port
, RL_CR
));
834 if (rl_inb(port
, RL_CR
) & RL_CR_RST
)
835 printf("rtl8139: reset failed to complete");
837 t
= rl_inl(port
, RL_TCR
);
838 switch(t
& (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
))
840 case RL_TCR_HWVER_RTL8139
: rep
->re_model
= "RTL8139"; break;
841 case RL_TCR_HWVER_RTL8139A
: rep
->re_model
= "RTL8139A"; break;
842 case RL_TCR_HWVER_RTL8139AG
:
843 rep
->re_model
= "RTL8139A-G / RTL8139C";
845 case RL_TCR_HWVER_RTL8139B
:
846 rep
->re_model
= "RTL8139B / RTL8130";
848 case RL_TCR_HWVER_RTL8100
: rep
->re_model
= "RTL8100"; break;
849 case RL_TCR_HWVER_RTL8100B
:
850 rep
->re_model
= "RTL8100B/RTL8139D";
852 case RL_TCR_HWVER_RTL8139CP
: rep
->re_model
= "RTL8139C+"; break;
853 case RL_TCR_HWVER_RTL8101
: rep
->re_model
= "RTL8101"; break;
860 printf("REVID: 0x%02x\n", rl_inb(port
, RL_REVID
));
865 /* Should init multicast mask */
867 08-0f R
/W MAR
[0-7] multicast
869 bus_buf
= vm_1phys2bus(rep
->re_rx_buf
);
870 rl_outl(port
, RL_RBSTART
, bus_buf
);
873 for (i
= 0; i
<N_TX_BUF
; i
++)
875 rep
->re_tx
[i
].ret_busy
= FALSE
;
876 bus_buf
= vm_1phys2bus(rep
->re_tx
[i
].ret_buf
);
877 rl_outl(port
, RL_TSAD0
+i
*4, bus_buf
);
878 t
= rl_inl(port
, RL_TSD0
+i
*4);
879 assert(t
& RL_TSD_OWN
);
886 t
= rl_inw(port
, RL_IMR
);
887 rl_outw(port
, RL_IMR
, t
| (RL_IMR_SERR
| RL_IMR_TIMEOUT
|
890 t
= rl_inw(port
, RL_IMR
);
891 rl_outw(port
, RL_IMR
, t
| (RL_IMR_FOVW
| RL_IMR_PUN
|
892 RL_IMR_RXOVW
| RL_IMR_RER
| RL_IMR_ROK
));
894 t
= rl_inw(port
, RL_IMR
);
895 rl_outw(port
, RL_IMR
, t
| (RL_IMR_TER
| RL_IMR_TOK
));
897 t
= rl_inb(port
, RL_CR
);
898 rl_outb(port
, RL_CR
, t
| RL_CR_RE
);
900 t
= rl_inb(port
, RL_CR
);
901 rl_outb(port
, RL_CR
, t
| RL_CR_TE
);
903 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
905 t
= rl_inl(port
, RL_TCR
);
906 rl_outl(port
, RL_TCR
, t
| RL_TCR_IFG_STD
);
909 /*===========================================================================*
911 *===========================================================================*/
912 static void rl_confaddr(rep
)
915 static char eakey
[]= RL_ENVVAR
"#_EA";
916 static char eafmt
[]= "x:x:x:x:x:x";
923 /* User defined ethernet address? */
924 eakey
[sizeof(RL_ENVVAR
)-1]= '0' + (rep
-re_table
);
926 port
= rep
->re_base_port
;
928 for (i
= 0; i
< 6; i
++)
930 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
932 rep
->re_address
.ea_addr
[i
]= v
;
935 if (i
!= 0 && i
!= 6) env_panic(eakey
); /* It's all or nothing */
937 /* Should update ethernet address in hardware */
940 port
= rep
->re_base_port
;
941 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_CONFIG
);
944 w
|= (rep
->re_address
.ea_addr
[i
] << (i
*8));
945 rl_outl(port
, RL_IDR
, w
);
948 w
|= (rep
->re_address
.ea_addr
[i
] << ((i
-4)*8));
949 rl_outl(port
, RL_IDR
+4, w
);
950 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_NORMAL
);
953 /* Get ethernet address */
955 rep
->re_address
.ea_addr
[i
]= rl_inb(port
, RL_IDR
+i
);
958 /*===========================================================================*
960 *===========================================================================*/
961 static void rl_rec_mode(rep
)
967 port
= rep
->re_base_port
;
968 rcr
= rl_inl(port
, RL_RCR
);
969 rcr
&= ~(RL_RCR_AB
|RL_RCR_AM
|RL_RCR_APM
|RL_RCR_AAP
);
970 if (rep
->re_flags
& REF_PROMISC
)
971 rcr
|= RL_RCR_AB
| RL_RCR_AM
| RL_RCR_AAP
;
972 if (rep
->re_flags
& REF_BROAD
)
974 if (rep
->re_flags
& REF_MULTI
)
978 rl_outl(port
, RL_RCR
, rcr
);
981 /*===========================================================================*
983 *===========================================================================*/
984 static void rl_readv(message
*mp
, int from_int
, int vectored
)
986 int i
, j
, n
, o
, s
, s1
, dl_port
, re_client
, count
, size
;
988 unsigned amount
, totlen
, packlen
;
989 phys_bytes src_phys
, dst_phys
;
990 u16_t d_start
, d_end
;
991 u32_t l
, rxstat
= 0x12345678;
996 dl_port
= mp
->DL_PORT
;
997 count
= mp
->DL_COUNT
;
998 if (dl_port
< 0 || dl_port
>= RE_PORT_NR
)
999 panic("rtl8139"," illegal port", dl_port
);
1000 rep
= &re_table
[dl_port
];
1001 re_client
= mp
->DL_PROC
;
1002 rep
->re_client
= re_client
;
1004 if (rep
->re_clear_rx
)
1005 goto suspend
; /* Buffer overflow */
1007 assert(rep
->re_mode
== REM_ENABLED
);
1008 assert(rep
->re_flags
& REF_ENABLED
);
1010 port
= rep
->re_base_port
;
1012 /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1014 if (!from_int
&& (rl_inb(port
, RL_CR
) & RL_CR_BUFE
))
1016 /* Receive buffer is empty, suspend */
1020 d_start
= rl_inw(port
, RL_CAPR
) + RL_CAPR_DATA_OFF
;
1021 d_end
= rl_inw(port
, RL_CBR
) % RX_BUFSIZE
;
1023 if (d_start
>= RX_BUFSIZE
)
1025 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
1026 rl_inw(port
, RL_CAPR
));
1027 d_start
%= RX_BUFSIZE
;
1030 if (d_end
> d_start
)
1031 amount
= d_end
-d_start
;
1033 amount
= d_end
+RX_BUFSIZE
- d_start
;
1035 rxstat
= *(u32_t
*) (rep
->v_re_rx_buf
+ d_start
);
1037 if (rep
->re_clear_rx
)
1040 printf("rl_readv: late buffer overflow\n");
1042 goto suspend
; /* Buffer overflow */
1045 /* Should convert from little endian to host byte order */
1047 if (!(rxstat
& RL_RXS_ROK
))
1049 printf("rxstat = 0x%08lx\n", rxstat
);
1050 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
1051 d_start
, d_end
, rxstat
);
1052 panic("rtl8139","received packet not OK", NO_NUM
);
1054 totlen
= (rxstat
>> RL_RXS_LEN_S
);
1055 if (totlen
< 8 || totlen
> 2*ETH_MAX_PACK_SIZE
)
1057 /* Someting went wrong */
1059 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
1060 totlen
, rxstat
, d_start
);
1062 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
1063 d_start
, d_end
, totlen
, rxstat
);
1064 panic(NULL
, NULL
, NO_NUM
);
1068 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
1069 d_start
, d_end
, totlen
, rxstat
);
1072 if (totlen
+4 > amount
)
1074 printf("rl_readv: packet not yet ready\n");
1078 /* Should subtract the CRC */
1079 packlen
= totlen
- ETH_CRC_SIZE
;
1087 src_phys
= rep
->re_rx_buf
;
1088 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1089 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec
[0]))
1095 cps
= sys_vircopy(re_client
, D
,
1096 (vir_bytes
) mp
->DL_ADDR
+ iov_offset
,
1097 SELF
, D
, (vir_bytes
) rep
->re_iovec
,
1098 n
* sizeof(rep
->re_iovec
[0]));
1101 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1104 for (j
= 0, iovp
= rep
->re_iovec
; j
<n
; j
++, iovp
++)
1107 if (size
+ s
> packlen
)
1109 assert(packlen
> size
);
1113 if (o
>= RX_BUFSIZE
)
1116 assert(o
< RX_BUFSIZE
);
1119 if (o
+s
> RX_BUFSIZE
)
1121 assert(o
<RX_BUFSIZE
);
1124 cps
= sys_vircopy(SELF
, D
,
1125 (vir_bytes
) rep
->v_re_rx_buf
+o
,
1126 re_client
, D
, iovp
->iov_addr
,
1130 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1132 cps
= sys_vircopy(SELF
, D
,
1133 (vir_bytes
) rep
->v_re_rx_buf
,
1135 iovp
->iov_addr
+s1
, s
-s1
);
1138 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1143 cps
= sys_vircopy(SELF
, D
,
1144 (vir_bytes
) rep
->v_re_rx_buf
+o
,
1145 re_client
, D
, iovp
->iov_addr
,
1149 "RTL8139: warning, sys_vircopy failed: %d (%d)\n",
1154 if (size
== packlen
)
1158 if (size
== packlen
)
1171 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE_TAGGED
)
1172 panic("rtl8139","invalid packet size", size
);
1173 if (OK
!= sys_umap(re_client
, D
, (vir_bytes
)mp
->DL_ADDR
, size
, &phys_user
))
1174 panic("rtl8139","umap_local failed", NO_NUM
);
1176 p
= rep
->re_tx
[tx_head
].ret_buf
;
1177 cps
= sys_abscopy(phys_user
, p
, size
);
1178 if (cps
!= OK
) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps
);
1182 if (rep
->re_clear_rx
)
1184 /* For some reason the receiver FIFO is not stopped when
1185 * the buffer is full.
1188 printf("rl_readv: later buffer overflow\n");
1190 goto suspend
; /* Buffer overflow */
1193 rep
->re_stat
.ets_packetR
++;
1194 rep
->re_read_s
= packlen
;
1195 rep
->re_flags
= (rep
->re_flags
& ~REF_READING
) | REF_PACK_RECV
;
1197 /* Avoid overflow in 16-bit computations */
1200 l
= (l
+3) & ~3; /* align */
1201 if (l
>= RX_BUFSIZE
)
1204 assert(l
< RX_BUFSIZE
);
1206 rl_outw(port
, RL_CAPR
, l
-RL_CAPR_DATA_OFF
);
1209 reply(rep
, OK
, FALSE
);
1216 assert(rep
->re_flags
& REF_READING
);
1218 /* No need to store any state */
1222 rep
->re_rx_mess
= *mp
;
1223 assert(!(rep
->re_flags
& REF_READING
));
1224 rep
->re_flags
|= REF_READING
;
1226 reply(rep
, OK
, FALSE
);
1229 /*===========================================================================*
1231 *===========================================================================*/
1232 static void rl_readv_s(message
*mp
, int from_int
)
1234 int i
, j
, n
, o
, s
, s1
, dl_port
, re_client
, count
, size
;
1236 unsigned amount
, totlen
, packlen
;
1237 phys_bytes src_phys
, dst_phys
;
1238 u16_t d_start
, d_end
;
1239 u32_t l
, rxstat
= 0x12345678;
1245 dl_port
= mp
->DL_PORT
;
1246 count
= mp
->DL_COUNT
;
1247 if (dl_port
< 0 || dl_port
>= RE_PORT_NR
)
1248 panic("rtl8139"," illegal port", dl_port
);
1249 rep
= &re_table
[dl_port
];
1250 re_client
= mp
->DL_PROC
;
1251 rep
->re_client
= re_client
;
1253 if (rep
->re_clear_rx
)
1254 goto suspend
; /* Buffer overflow */
1256 assert(rep
->re_mode
== REM_ENABLED
);
1257 assert(rep
->re_flags
& REF_ENABLED
);
1259 port
= rep
->re_base_port
;
1261 /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
1263 if (!from_int
&& (rl_inb(port
, RL_CR
) & RL_CR_BUFE
))
1265 /* Receive buffer is empty, suspend */
1269 d_start
= rl_inw(port
, RL_CAPR
) + RL_CAPR_DATA_OFF
;
1270 d_end
= rl_inw(port
, RL_CBR
) % RX_BUFSIZE
;
1272 if (d_start
>= RX_BUFSIZE
)
1274 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
1275 rl_inw(port
, RL_CAPR
));
1276 d_start
%= RX_BUFSIZE
;
1279 if (d_end
> d_start
)
1280 amount
= d_end
-d_start
;
1282 amount
= d_end
+RX_BUFSIZE
- d_start
;
1284 rxstat
= *(u32_t
*) (rep
->v_re_rx_buf
+ d_start
);
1286 if (rep
->re_clear_rx
)
1289 printf("rl_readv: late buffer overflow\n");
1291 goto suspend
; /* Buffer overflow */
1294 /* Should convert from little endian to host byte order */
1296 if (!(rxstat
& RL_RXS_ROK
))
1298 printf("rxstat = 0x%08lx\n", rxstat
);
1299 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
1300 d_start
, d_end
, rxstat
);
1301 panic("rtl8139","received packet not OK", NO_NUM
);
1303 totlen
= (rxstat
>> RL_RXS_LEN_S
);
1304 if (totlen
< 8 || totlen
> 2*ETH_MAX_PACK_SIZE
)
1306 /* Someting went wrong */
1308 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
1309 totlen
, rxstat
, d_start
);
1311 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
1312 d_start
, d_end
, totlen
, rxstat
);
1313 panic(NULL
, NULL
, NO_NUM
);
1317 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
1318 d_start
, d_end
, totlen
, rxstat
);
1321 if (totlen
+4 > amount
)
1323 printf("rl_readv: packet not yet ready\n");
1327 /* Should subtract the CRC */
1328 packlen
= totlen
- ETH_CRC_SIZE
;
1332 src_phys
= rep
->re_rx_buf
;
1333 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1334 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1340 cps
= sys_safecopyfrom(re_client
, mp
->DL_GRANT
, iov_offset
,
1341 (vir_bytes
) rep
->re_iovec_s
,
1342 n
* sizeof(rep
->re_iovec_s
[0]), D
);
1345 panic(__FILE__
, "rl_readv_s: sys_safecopyfrom failed",
1349 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
1352 if (size
+ s
> packlen
)
1354 assert(packlen
> size
);
1359 if (sys_umap(re_client
, D
, iovp
->iov_addr
, s
, &dst_phys
) != OK
)
1360 panic("rtl8139","umap_local failed\n", NO_NUM
);
1363 if (o
>= RX_BUFSIZE
)
1366 assert(o
< RX_BUFSIZE
);
1369 if (o
+s
> RX_BUFSIZE
)
1371 assert(o
<RX_BUFSIZE
);
1374 cps
= sys_safecopyto(re_client
,
1376 (vir_bytes
) rep
->v_re_rx_buf
+o
, s1
, D
);
1380 "rl_readv_s: sys_safecopyto failed",
1383 cps
= sys_safecopyto(re_client
,
1384 iovp
->iov_grant
, s1
,
1385 (vir_bytes
) rep
->v_re_rx_buf
, s
-s1
, S
);
1389 "rl_readv_s: sys_safecopyto failed",
1395 cps
= sys_safecopyto(re_client
,
1397 (vir_bytes
) rep
->v_re_rx_buf
+o
, s
, D
);
1400 "rl_readv_s: sys_safecopyto failed",
1405 if (size
== packlen
)
1409 if (size
== packlen
)
1417 if (rep
->re_clear_rx
)
1419 /* For some reason the receiver FIFO is not stopped when
1420 * the buffer is full.
1423 printf("rl_readv: later buffer overflow\n");
1425 goto suspend
; /* Buffer overflow */
1428 rep
->re_stat
.ets_packetR
++;
1429 rep
->re_read_s
= packlen
;
1430 rep
->re_flags
= (rep
->re_flags
& ~REF_READING
) | REF_PACK_RECV
;
1432 /* Avoid overflow in 16-bit computations */
1435 l
= (l
+3) & ~3; /* align */
1436 if (l
>= RX_BUFSIZE
)
1439 assert(l
< RX_BUFSIZE
);
1441 rl_outw(port
, RL_CAPR
, l
-RL_CAPR_DATA_OFF
);
1444 reply(rep
, OK
, FALSE
);
1451 assert(rep
->re_flags
& REF_READING
);
1453 /* No need to store any state */
1457 rep
->re_rx_mess
= *mp
;
1458 assert(!(rep
->re_flags
& REF_READING
));
1459 rep
->re_flags
|= REF_READING
;
1461 reply(rep
, OK
, FALSE
);
1464 /*===========================================================================*
1466 *===========================================================================*/
1467 static void rl_writev(message
*mp
, int from_int
, int vectored
)
1469 phys_bytes phys_user
;
1470 int i
, j
, n
, s
, port
, count
, size
;
1471 int tx_head
, re_client
;
1478 count
= mp
->DL_COUNT
;
1479 if (port
< 0 || port
>= RE_PORT_NR
)
1480 panic("rtl8139","illegal port", port
);
1481 rep
= &re_table
[port
];
1482 re_client
= mp
->DL_PROC
;
1483 rep
->re_client
= re_client
;
1485 assert(rep
->re_mode
== REM_ENABLED
);
1486 assert(rep
->re_flags
& REF_ENABLED
);
1490 assert(rep
->re_flags
& REF_SEND_AVAIL
);
1491 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1492 rep
->re_send_int
= FALSE
;
1493 rep
->re_tx_alive
= TRUE
;
1496 tx_head
= rep
->re_tx_head
;
1497 if (rep
->re_tx
[tx_head
].ret_busy
)
1499 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1500 rep
->re_flags
|= REF_SEND_AVAIL
;
1501 if (rep
->re_tx
[tx_head
].ret_busy
)
1504 /* Race condition, the interrupt handler may clear re_busy
1505 * before we got a chance to set REF_SEND_AVAIL. Checking
1506 * ret_busy twice should be sufficient.
1509 printf("rl_writev: race detected\n");
1511 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1512 rep
->re_send_int
= FALSE
;
1515 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1516 assert(!(rep
->re_flags
& REF_PACK_SENT
));
1523 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1524 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1525 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec
[0]))
1530 cps
= sys_vircopy(re_client
, D
, ((vir_bytes
) mp
->DL_ADDR
) + iov_offset
,
1531 SELF
, D
, (vir_bytes
) rep
->re_iovec
,
1532 n
* sizeof(rep
->re_iovec
[0]));
1533 if (cps
!= OK
) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps
);
1535 for (j
= 0, iovp
= rep
->re_iovec
; j
<n
; j
++, iovp
++)
1538 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
)
1540 panic("rtl8139","invalid packet size",
1544 if (OK
!= sys_umap(re_client
, D
, iovp
->iov_addr
, s
, &phys_user
))
1545 panic("rtl8139","umap_local failed\n", NO_NUM
);
1547 cps
= sys_vircopy(re_client
, D
, iovp
->iov_addr
,
1548 SELF
, D
, (vir_bytes
) ret
, s
);
1549 if (cps
!= OK
) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps
);
1554 if (size
< ETH_MIN_PACK_SIZE
)
1555 panic("rtl8139","invalid packet size", size
);
1560 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE_TAGGED
)
1561 panic("rtl8139","invalid packet size", size
);
1562 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1563 cps
= sys_vircopy(re_client
, D
, (vir_bytes
)mp
->DL_ADDR
,
1564 SELF
, D
, (vir_bytes
) ret
, size
);
1565 if (cps
!= OK
) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps
);
1568 rl_outl(rep
->re_base_port
, RL_TSD0
+tx_head
*4,
1569 rep
->re_ertxth
| size
);
1570 rep
->re_tx
[tx_head
].ret_busy
= TRUE
;
1572 if (++tx_head
== N_TX_BUF
)
1574 assert(tx_head
< RL_N_TX
);
1575 rep
->re_tx_head
= tx_head
;
1577 rep
->re_flags
|= REF_PACK_SENT
;
1579 /* If the interrupt handler called, don't send a reply. The reply
1580 * will be sent after all interrupts are handled.
1584 reply(rep
, OK
, FALSE
);
1589 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
1590 tx_head
, rep
->re_tx_tail
,
1591 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1592 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1593 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
1594 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
1595 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
1596 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
1597 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
1601 panic("rtl8139","should not be sending\n", NO_NUM
);
1603 rep
->re_tx_mess
= *mp
;
1604 reply(rep
, OK
, FALSE
);
1607 /*===========================================================================*
1609 *===========================================================================*/
1610 static void rl_writev_s(message
*mp
, int from_int
)
1612 int i
, j
, n
, s
, port
, count
, size
;
1613 int tx_head
, re_client
;
1621 count
= mp
->DL_COUNT
;
1622 if (port
< 0 || port
>= RE_PORT_NR
)
1623 panic("rtl8139","illegal port", port
);
1624 rep
= &re_table
[port
];
1625 re_client
= mp
->DL_PROC
;
1626 rep
->re_client
= re_client
;
1628 assert(rep
->re_mode
== REM_ENABLED
);
1629 assert(rep
->re_flags
& REF_ENABLED
);
1633 assert(rep
->re_flags
& REF_SEND_AVAIL
);
1634 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1635 rep
->re_send_int
= FALSE
;
1636 rep
->re_tx_alive
= TRUE
;
1639 tx_head
= rep
->re_tx_head
;
1640 if (rep
->re_tx
[tx_head
].ret_busy
)
1642 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1643 rep
->re_flags
|= REF_SEND_AVAIL
;
1644 if (rep
->re_tx
[tx_head
].ret_busy
)
1647 /* Race condition, the interrupt handler may clear re_busy
1648 * before we got a chance to set REF_SEND_AVAIL. Checking
1649 * ret_busy twice should be sufficient.
1652 printf("rl_writev: race detected\n");
1654 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1655 rep
->re_send_int
= FALSE
;
1658 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1659 assert(!(rep
->re_flags
& REF_PACK_SENT
));
1662 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1663 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1664 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1669 cps
= sys_safecopyfrom(re_client
, mp
->DL_GRANT
, iov_offset
,
1670 (vir_bytes
) rep
->re_iovec_s
,
1671 n
* sizeof(rep
->re_iovec_s
[0]), D
);
1674 panic(__FILE__
, "rl_writev_s: sys_safecopyfrom failed",
1678 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
1681 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
)
1683 panic("rtl8139","invalid packet size",
1686 cps
= sys_safecopyfrom(re_client
, iovp
->iov_grant
, 0,
1687 (vir_bytes
) ret
, s
, D
);
1691 "rl_writev_s: sys_safecopyfrom failed",
1698 if (size
< ETH_MIN_PACK_SIZE
)
1699 panic("rtl8139","invalid packet size", size
);
1701 rl_outl(rep
->re_base_port
, RL_TSD0
+tx_head
*4,
1702 rep
->re_ertxth
| size
);
1703 rep
->re_tx
[tx_head
].ret_busy
= TRUE
;
1705 if (++tx_head
== N_TX_BUF
)
1707 assert(tx_head
< RL_N_TX
);
1708 rep
->re_tx_head
= tx_head
;
1710 rep
->re_flags
|= REF_PACK_SENT
;
1712 /* If the interrupt handler called, don't send a reply. The reply
1713 * will be sent after all interrupts are handled.
1717 reply(rep
, OK
, FALSE
);
1722 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
1723 tx_head
, rep
->re_tx_tail
,
1724 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1725 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1726 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
1727 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
1728 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
1729 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
1730 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
1734 panic("rtl8139","should not be sending\n", NO_NUM
);
1736 rep
->re_tx_mess
= *mp
;
1737 reply(rep
, OK
, FALSE
);
1740 /*===========================================================================*
1742 *===========================================================================*/
1743 static void rl_check_ints(rep
)
1747 10-1f R
/W TSD
[0-3] Transmit Status of Descriptor
[0-3]
1748 31 R CRS Carrier Sense Lost
1749 30 R TABT Transmit Abort
1750 29 R OWC Out of Window Collision
1751 27-24 R NCC
[3-0] Number of Collision Count
1753 21-16 R
/W ERTXH
[5-0] Early Tx Threshold
1754 15 R TOK Transmit OK
1755 14 R TUN Transmit FIFO Underrun
1757 12-0 R
/W SIZE Descriptor Size
1758 3e-3f R
/W ISR Interrupt Status Register
1759 6 R
/W FOVW Fx FIFO Overflow Interrupt
1760 5 R
/W PUN
/LinkChg Packet Underrun
/ Link Change Interrupt
1761 3 R
/W TER Transmit Error Interrupt
1762 2 R
/W TOK Transmit OK Interrupt
1763 3e-3f R
/W ISR Interrupt Status Register
1764 15 R
/W SERR System Error Interrupt
1765 14 R
/W TimeOut Time Out Interrupt
1766 13 R
/W LenChg Cable Length Change Interrupt
1767 3e-3f R
/W ISR Interrupt Status Register
1768 4 R
/W RXOVW Rx Buffer Overflow Interrupt
1769 1 R
/W RER Receive Error Interrupt
1770 0 R
/W ROK Receive OK Interrupt
1771 4c
-4f R
/W MPC Missed Packet Counter
1772 60-61 R TSAD Transmit Status of All Descriptors
1773 15-12 R TOK
[3-0] TOK bit of Descriptor
[3-0]
1774 11-8 R TUN
[3-0] TUN bit of Descriptor
[3-0]
1775 7-4 R TABT
[3-0] TABT bit of Descriptor
[3-0]
1776 3-0 R OWN
[3-0] OWN bit of Descriptor
[3-0]
1777 6c
-6d R DIS Disconnect Counter
1778 15-0 R DCNT Disconnect Counter
1779 6e-6f R FCSC False Carrier Sense Counter
1780 15-0 R FCSCNT False Carrier event counter
1781 72-73 R REC RX_ER Counter
1782 15-0 R RXERCNT Received packet counter
1787 re_flags
= rep
->re_flags
;
1789 if ((re_flags
& REF_READING
) &&
1790 !(rl_inb(rep
->re_base_port
, RL_CR
) & RL_CR_BUFE
))
1792 if (rep
->re_rx_mess
.m_type
== DL_READV
)
1794 rl_readv(&rep
->re_rx_mess
, TRUE
/* from int */,
1795 TRUE
/* vectored */);
1797 else if (rep
->re_rx_mess
.m_type
== DL_READV_S
)
1799 rl_readv_s(&rep
->re_rx_mess
, TRUE
/* from int */);
1803 assert(rep
->re_rx_mess
.m_type
== DL_READ
);
1804 rl_readv(&rep
->re_rx_mess
, TRUE
/* from int */,
1805 FALSE
/* !vectored */);
1808 if (rep
->re_clear_rx
)
1811 if (rep
->re_need_reset
)
1814 if (rep
->re_send_int
)
1816 if (rep
->re_tx_mess
.m_type
== DL_WRITEV
)
1818 rl_writev(&rep
->re_tx_mess
, TRUE
/* from int */,
1819 TRUE
/* vectored */);
1821 else if (rep
->re_tx_mess
.m_type
== DL_WRITEV_S
)
1823 rl_writev_s(&rep
->re_tx_mess
, TRUE
/* from int */);
1827 assert(rep
->re_tx_mess
.m_type
== DL_WRITE
);
1828 rl_writev(&rep
->re_tx_mess
, TRUE
/* from int */,
1829 FALSE
/* !vectored */);
1833 if (rep
->re_report_link
)
1834 rl_report_link(rep
);
1836 if (rep
->re_flags
& (REF_PACK_SENT
| REF_PACK_RECV
))
1837 reply(rep
, OK
, TRUE
);
1840 /*===========================================================================*
1842 *===========================================================================*/
1843 static void rl_report_link(rep
)
1847 u16_t mii_ctrl
, mii_status
, mii_ana
, mii_anlpa
, mii_ane
, mii_extstat
;
1851 rep
->re_report_link
= FALSE
;
1852 port
= rep
->re_base_port
;
1853 msr
= rl_inb(port
, RL_MSR
);
1854 link_up
= !(msr
& RL_MSR_LINKB
);
1855 rep
->re_link_up
= link_up
;
1858 printf("%s: link down\n", rep
->re_name
);
1862 mii_ctrl
= rl_inw(port
, RL_BMCR
);
1863 mii_status
= rl_inw(port
, RL_BMSR
);
1864 mii_ana
= rl_inw(port
, RL_ANAR
);
1865 mii_anlpa
= rl_inw(port
, RL_ANLPAR
);
1866 mii_ane
= rl_inw(port
, RL_ANER
);
1869 if (mii_ctrl
& (MII_CTRL_LB
|MII_CTRL_PD
|MII_CTRL_ISO
))
1871 printf("%s: PHY: ", rep
->re_name
);
1873 if (mii_ctrl
& MII_CTRL_LB
)
1875 printf("loopback mode");
1878 if (mii_ctrl
& MII_CTRL_PD
)
1880 if (!f
) printf(", ");
1882 printf("powered down");
1884 if (mii_ctrl
& MII_CTRL_ISO
)
1886 if (!f
) printf(", ");
1893 if (!(mii_ctrl
& MII_CTRL_ANE
))
1895 printf("%s: manual config: ", rep
->re_name
);
1896 switch(mii_ctrl
& (MII_CTRL_SP_LSB
|MII_CTRL_SP_MSB
))
1898 case MII_CTRL_SP_10
: printf("10 Mbps"); break;
1899 case MII_CTRL_SP_100
: printf("100 Mbps"); break;
1900 case MII_CTRL_SP_1000
: printf("1000 Mbps"); break;
1901 case MII_CTRL_SP_RES
: printf("reserved speed"); break;
1903 if (mii_ctrl
& MII_CTRL_DM
)
1904 printf(", full duplex");
1906 printf(", half duplex");
1911 if (!debug
) goto resspeed
;
1913 printf("%s: ", rep
->re_name
);
1914 mii_print_stat_speed(mii_status
, mii_extstat
);
1917 if (!(mii_status
& MII_STATUS_ANC
))
1918 printf("%s: auto-negotiation not complete\n", rep
->re_name
);
1919 if (mii_status
& MII_STATUS_RF
)
1920 printf("%s: remote fault detected\n", rep
->re_name
);
1921 if (!(mii_status
& MII_STATUS_ANA
))
1923 printf("%s: local PHY has no auto-negotiation ability\n",
1926 if (!(mii_status
& MII_STATUS_LS
))
1927 printf("%s: link down\n", rep
->re_name
);
1928 if (mii_status
& MII_STATUS_JD
)
1929 printf("%s: jabber condition detected\n", rep
->re_name
);
1930 if (!(mii_status
& MII_STATUS_EC
))
1932 printf("%s: no extended register set\n", rep
->re_name
);
1935 if (!(mii_status
& MII_STATUS_ANC
))
1938 printf("%s: local cap.: ", rep
->re_name
);
1939 mii_print_techab(mii_ana
);
1942 if (mii_ane
& MII_ANE_PDF
)
1943 printf("%s: parallel detection fault\n", rep
->re_name
);
1944 if (!(mii_ane
& MII_ANE_LPANA
))
1946 printf("%s: link-partner does not support auto-negotiation\n",
1951 printf("%s: remote cap.: ", rep
->re_name
);
1952 mii_print_techab(mii_anlpa
);
1956 printf("%s: ", rep
->re_name
);
1957 printf("link up at %d Mbps, ", (msr
& RL_MSR_SPEED_10
) ? 10 : 100);
1958 printf("%s duplex\n", ((mii_ctrl
& MII_CTRL_DM
) ? "full" : "half"));
1962 static void mii_print_techab(techab
)
1966 if ((techab
& MII_ANA_SEL_M
) != MII_ANA_SEL_802_3
)
1968 printf("strange selector 0x%x, value 0x%x",
1969 techab
& MII_ANA_SEL_M
,
1970 (techab
& MII_ANA_TAF_M
) >> MII_ANA_TAF_S
);
1974 if (techab
& (MII_ANA_100T4
| MII_ANA_100TXFD
| MII_ANA_100TXHD
))
1976 printf("100 Mbps: ");
1979 if (techab
& MII_ANA_100T4
)
1984 if (techab
& (MII_ANA_100TXFD
| MII_ANA_100TXHD
))
1990 switch(techab
& (MII_ANA_100TXFD
|MII_ANA_100TXHD
))
1992 case MII_ANA_100TXFD
: printf("FD"); break;
1993 case MII_ANA_100TXHD
: printf("HD"); break;
1994 default: printf("FD/HD"); break;
1998 if (techab
& (MII_ANA_10TFD
| MII_ANA_10THD
))
2002 printf("10 Mbps: ");
2005 switch(techab
& (MII_ANA_10TFD
|MII_ANA_10THD
))
2007 case MII_ANA_10TFD
: printf("FD"); break;
2008 case MII_ANA_10THD
: printf("HD"); break;
2009 default: printf("FD/HD"); break;
2012 if (techab
& MII_ANA_PAUSE_SYM
)
2017 printf("pause(SYM)");
2019 if (techab
& MII_ANA_PAUSE_ASYM
)
2024 printf("pause(ASYM)");
2026 if (techab
& MII_ANA_TAF_RES
)
2031 printf("0x%x", (techab
& MII_ANA_TAF_RES
) >> MII_ANA_TAF_S
);
2035 static void mii_print_stat_speed(stat
, extstat
)
2041 if (stat
& MII_STATUS_EXT_STAT
)
2043 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
|
2044 MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
2046 printf("1000 Mbps: ");
2049 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
))
2054 (MII_ESTAT_1000XFD
|MII_ESTAT_1000XHD
))
2056 case MII_ESTAT_1000XFD
: printf("FD"); break;
2057 case MII_ESTAT_1000XHD
: printf("HD"); break;
2058 default: printf("FD/HD"); break;
2061 if (extstat
& (MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
2068 (MII_ESTAT_1000TFD
|MII_ESTAT_1000THD
))
2070 case MII_ESTAT_1000TFD
: printf("FD"); break;
2071 case MII_ESTAT_1000THD
: printf("HD"); break;
2072 default: printf("FD/HD"); break;
2077 if (stat
& (MII_STATUS_100T4
|
2078 MII_STATUS_100XFD
| MII_STATUS_100XHD
|
2079 MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
2084 printf("100 Mbps: ");
2086 if (stat
& MII_STATUS_100T4
)
2091 if (stat
& (MII_STATUS_100XFD
| MII_STATUS_100XHD
))
2097 switch(stat
& (MII_STATUS_100XFD
|MII_STATUS_100XHD
))
2099 case MII_STATUS_100XFD
: printf("FD"); break;
2100 case MII_STATUS_100XHD
: printf("HD"); break;
2101 default: printf("FD/HD"); break;
2104 if (stat
& (MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
2110 switch(stat
& (MII_STATUS_100T2FD
|MII_STATUS_100T2HD
))
2112 case MII_STATUS_100T2FD
: printf("FD"); break;
2113 case MII_STATUS_100T2HD
: printf("HD"); break;
2114 default: printf("FD/HD"); break;
2118 if (stat
& (MII_STATUS_10FD
| MII_STATUS_10HD
))
2122 printf("10 Mbps: ");
2125 switch(stat
& (MII_STATUS_10FD
|MII_STATUS_10HD
))
2127 case MII_STATUS_10FD
: printf("FD"); break;
2128 case MII_STATUS_10HD
: printf("HD"); break;
2129 default: printf("FD/HD"); break;
2134 /*===========================================================================*
2136 *===========================================================================*/
2137 static void rl_clear_rx(rep
)
2145 rep
->re_clear_rx
= FALSE
;
2146 port
= rep
->re_base_port
;
2148 /* Reset the receiver */
2149 cr
= rl_inb(port
, RL_CR
);
2151 rl_outb(port
, RL_CR
, cr
);
2154 if (!(rl_inb(port
, RL_CR
) & RL_CR_RE
))
2156 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
2157 if (rl_inb(port
, RL_CR
) & RL_CR_RE
)
2158 panic("rtl8139","cannot disable receiver", NO_NUM
);
2161 printf("RBSTART = 0x%08x\n", rl_inl(port
, RL_RBSTART
));
2162 printf("CAPR = 0x%04x\n", rl_inw(port
, RL_CAPR
));
2163 printf("CBR = 0x%04x\n", rl_inw(port
, RL_CBR
));
2164 printf("RCR = 0x%08x\n", rl_inl(port
, RL_RCR
));
2167 rl_outb(port
, RL_CR
, cr
| RL_CR_RE
);
2169 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
2173 rep
->re_stat
.ets_missedP
++;
2176 /*===========================================================================*
2178 *===========================================================================*/
2179 static void rl_do_reset(rep
)
2182 rep
->re_need_reset
= FALSE
;
2187 if (rep
->re_flags
& REF_SEND_AVAIL
)
2189 rep
->re_tx
[rep
->re_tx_head
].ret_busy
= FALSE
;
2190 rep
->re_send_int
= TRUE
;
2194 /*===========================================================================*
2196 *===========================================================================*/
2197 static void rl_getstat(mp
)
2205 if (port
< 0 || port
>= RE_PORT_NR
)
2206 panic("rtl8139","illegal port", port
);
2207 rep
= &re_table
[port
];
2208 rep
->re_client
= mp
->DL_PROC
;
2210 assert(rep
->re_mode
== REM_ENABLED
);
2211 assert(rep
->re_flags
& REF_ENABLED
);
2213 stats
= rep
->re_stat
;
2215 r
= sys_datacopy(SELF
, (vir_bytes
) &stats
, mp
->DL_PROC
,
2216 (vir_bytes
) mp
->DL_ADDR
, sizeof(stats
));
2218 panic(__FILE__
, "rl_getstat: sys_datacopy failed", r
);
2220 mp
->m_type
= DL_STAT_REPLY
;
2223 r
= send(mp
->m_source
, mp
);
2225 panic("RTL8139", "rl_getstat: send failed: %d\n", r
);
2228 /*===========================================================================*
2230 *===========================================================================*/
2231 static void rl_getstat_s(mp
)
2239 if (port
< 0 || port
>= RE_PORT_NR
)
2240 panic("rtl8139","illegal port", port
);
2241 rep
= &re_table
[port
];
2242 rep
->re_client
= mp
->DL_PROC
;
2244 assert(rep
->re_mode
== REM_ENABLED
);
2245 assert(rep
->re_flags
& REF_ENABLED
);
2247 stats
= rep
->re_stat
;
2249 r
= sys_safecopyto(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
2250 (vir_bytes
) &stats
, sizeof(stats
), D
);
2252 panic(__FILE__
, "rl_getstat_s: sys_safecopyto failed", r
);
2254 mp
->m_type
= DL_STAT_REPLY
;
2257 r
= send(mp
->m_source
, mp
);
2259 panic("RTL8139", "rl_getstat_s: send failed: %d\n", r
);
2263 /*===========================================================================*
2265 *===========================================================================*/
2266 static void rl_getname(mp
)
2271 strncpy(mp
->DL_NAME
, progname
, sizeof(mp
->DL_NAME
));
2272 mp
->DL_NAME
[sizeof(mp
->DL_NAME
)-1]= '\0';
2273 mp
->m_type
= DL_NAME_REPLY
;
2274 r
= send(mp
->m_source
, mp
);
2276 panic("RTL8139", "rl_getname: send failed: %d\n", r
);
2280 /*===========================================================================*
2282 *===========================================================================*/
2283 static void reply(rep
, err
, may_block
)
2294 if (rep
->re_flags
& REF_PACK_SENT
)
2295 status
|= DL_PACK_SEND
;
2296 if (rep
->re_flags
& REF_PACK_RECV
)
2297 status
|= DL_PACK_RECV
;
2299 reply
.m_type
= DL_TASK_REPLY
;
2300 reply
.DL_PORT
= rep
- re_table
;
2301 reply
.DL_PROC
= rep
->re_client
;
2302 reply
.DL_STAT
= status
| ((u32_t
) err
<< 16);
2303 reply
.DL_COUNT
= rep
->re_read_s
;
2304 if (OK
!= (r
= getuptime(&now
)))
2305 panic("rtl8139","getuptime() failed:", r
);
2306 reply
.DL_CLCK
= now
;
2308 r
= send(rep
->re_client
, &reply
);
2310 if (r
== ELOCKED
&& may_block
)
2313 printW(); printf("send locked\n");
2319 printf("RTL8139 tried sending to %d, type %d\n", rep
->re_client
, reply
.m_type
);
2320 panic("rtl8139","send failed:", r
);
2324 rep
->re_flags
&= ~(REF_PACK_SENT
| REF_PACK_RECV
);
2327 /*===========================================================================*
2329 *===========================================================================*/
2330 static void mess_reply(req
, reply_mess
)
2332 message
*reply_mess
;
2334 if (send(req
->m_source
, reply_mess
) != OK
)
2335 panic("rtl8139","unable to mess_reply", NO_NUM
);
2339 static void dump_phy(rep
)
2345 port
= rep
->re_base_port
;
2347 t
= rl_inb(port
, RL_MSR
);
2348 printf("MSR: 0x%02lx\n", t
);
2349 if (t
& RL_MSR_SPEED_10
)
2350 printf("\t10 Mbps\n");
2351 if (t
& RL_MSR_LINKB
)
2352 printf("\tLink failed\n");
2354 t
= rl_inb(port
, RL_CONFIG1
);
2355 printf("CONFIG1: 0x%02lx\n", t
);
2357 t
= rl_inb(port
, RL_CONFIG3
);
2358 printf("CONFIG3: 0x%02lx\n", t
);
2360 t
= rl_inb(port
, RL_CONFIG4
);
2361 printf("CONFIG4: 0x%02lx\n", t
);
2363 t
= rl_inw(port
, RL_BMCR
);
2364 printf("BMCR (MII_CTRL): 0x%04lx\n", t
);
2366 t
= rl_inw(port
, RL_BMSR
);
2368 if (t
& MII_STATUS_100T4
)
2369 printf(" 100Base-T4");
2370 if (t
& MII_STATUS_100XFD
)
2371 printf(" 100Base-X-FD");
2372 if (t
& MII_STATUS_100XHD
)
2373 printf(" 100Base-X-HD");
2374 if (t
& MII_STATUS_10FD
)
2375 printf(" 10Mbps-FD");
2376 if (t
& MII_STATUS_10HD
)
2377 printf(" 10Mbps-HD");
2378 if (t
& MII_STATUS_100T2FD
)
2379 printf(" 100Base-T2-FD");
2380 if (t
& MII_STATUS_100T2HD
)
2381 printf(" 100Base-T2-HD");
2382 if (t
& MII_STATUS_EXT_STAT
)
2383 printf(" Ext-stat");
2384 if (t
& MII_STATUS_RES
)
2385 printf(" res-0x%lx", t
& MII_STATUS_RES
);
2386 if (t
& MII_STATUS_MFPS
)
2388 if (t
& MII_STATUS_ANC
)
2390 if (t
& MII_STATUS_RF
)
2391 printf(" remote-fault");
2392 if (t
& MII_STATUS_ANA
)
2394 if (t
& MII_STATUS_LS
)
2396 if (t
& MII_STATUS_JD
)
2398 if (t
& MII_STATUS_EC
)
2399 printf(" Extended-capability");
2402 t
= rl_inw(port
, RL_ANAR
);
2403 printf("ANAR (MII_ANA): 0x%04lx\n", t
);
2405 t
= rl_inw(port
, RL_ANLPAR
);
2406 printf("ANLPAR: 0x%04lx\n", t
);
2408 t
= rl_inw(port
, RL_ANER
);
2409 printf("ANER (MII_ANE): ");
2410 if (t
& MII_ANE_RES
)
2411 printf(" res-0x%lx", t
& MII_ANE_RES
);
2412 if (t
& MII_ANE_PDF
)
2413 printf(" Par-Detect-Fault");
2414 if (t
& MII_ANE_LPNPA
)
2415 printf(" LP-Next-Page-Able");
2416 if (t
& MII_ANE_NPA
)
2417 printf(" Loc-Next-Page-Able");
2419 printf(" Page-Received");
2420 if (t
& MII_ANE_LPANA
)
2421 printf(" LP-Auto-Neg-Able");
2424 t
= rl_inw(port
, RL_NWAYTR
);
2425 printf("NWAYTR: 0x%04lx\n", t
);
2426 t
= rl_inw(port
, RL_CSCR
);
2427 printf("CSCR: 0x%04lx\n", t
);
2429 t
= rl_inb(port
, RL_CONFIG5
);
2430 printf("CONFIG5: 0x%02lx\n", t
);
2434 static int do_hard_int(void)
2438 for (i
=0; i
< RE_PORT_NR
; i
++) {
2440 /* Run interrupt handler at driver level. */
2441 rl_handler( &re_table
[i
]);
2443 /* Reenable interrupts for this hook. */
2444 if ((s
=sys_irqenable(&re_table
[i
].re_hook_id
)) != OK
)
2445 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
2449 /*===========================================================================*
2451 *===========================================================================*/
2452 static int rl_handler(rep
)
2455 int i
, port
, tx_head
, tx_tail
, link_up
;
2457 u32_t tsd
, tcr
, ertxth
;
2462 int_event_check
= FALSE
; /* disable check by default */
2464 port
= rep
->re_base_port
;
2467 isr
= rl_inw(port
, RL_ISR
);
2468 rl_outw(port
, RL_ISR
, isr
);
2470 if (isr
& RL_IMR_FOVW
)
2472 isr
&= ~RL_IMR_FOVW
;
2473 /* Should do anything? */
2475 rep
->re_stat
.ets_fifoOver
++;
2477 if (isr
& RL_IMR_PUN
)
2481 /* Either the link status changed or there was a TX fifo
2484 link_up
= !(rl_inb(port
, RL_MSR
) & RL_MSR_LINKB
);
2485 if (link_up
!= rep
->re_link_up
)
2487 rep
->re_report_link
= TRUE
;
2488 rep
->re_got_int
= TRUE
;
2489 int_event_check
= TRUE
;
2492 if (isr
& RL_IMR_RXOVW
)
2494 isr
&= ~RL_IMR_RXOVW
;
2496 /* Clear the receive buffer */
2497 rep
->re_clear_rx
= TRUE
;
2498 rep
->re_got_int
= TRUE
;
2499 int_event_check
= TRUE
;
2502 if (isr
& (RL_ISR_RER
| RL_ISR_ROK
))
2504 isr
&= ~(RL_ISR_RER
| RL_ISR_ROK
);
2506 if (!rep
->re_got_int
&& (rep
->re_flags
& REF_READING
))
2508 rep
->re_got_int
= TRUE
;
2509 int_event_check
= TRUE
;
2513 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) &&
2514 (rep
->re_flags
& REF_SEND_AVAIL
) &&
2515 (rep
->re_tx
[0].ret_busy
|| rep
->re_tx
[1].ret_busy
||
2516 rep
->re_tx
[2].ret_busy
|| rep
->re_tx
[3].ret_busy
))
2520 "rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
2521 rep
->re_tx_head
, rep
->re_tx_tail
,
2522 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2523 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2525 "rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
2526 rl_inw(port
, RL_TSAD
),
2527 rl_inl(port
, RL_TSD0
+0*4),
2528 rl_inl(port
, RL_TSD0
+1*4),
2529 rl_inl(port
, RL_TSD0
+2*4),
2530 rl_inl(port
, RL_TSD0
+3*4));
2533 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) || 1)
2535 isr
&= ~(RL_ISR_TER
| RL_ISR_TOK
);
2537 tsad
= rl_inw(port
, RL_TSAD
);
2538 if (tsad
& (RL_TSAD_TABT0
|RL_TSAD_TABT1
|
2539 RL_TSAD_TABT2
|RL_TSAD_TABT3
))
2542 /* Do we need a watch dog? */
2543 /* Just reset the whole chip */
2544 rep
->re_need_reset
= TRUE
;
2545 rep
->re_got_int
= TRUE
;
2546 int_event_check
= TRUE
;
2548 /* Reset transmitter */
2549 rep
->re_stat
.ets_transAb
++;
2551 cr
= rl_inb(port
, RL_CR
);
2553 rl_outb(port
, RL_CR
, cr
);
2556 if (!(rl_inb(port
, RL_CR
) & RL_CR_TE
))
2558 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
2559 if (rl_inb(port
, RL_CR
) & RL_CR_TE
)
2561 panic("rtl8139","cannot disable transmitter",
2564 rl_outb(port
, RL_CR
, cr
| RL_CR_TE
);
2566 tcr
= rl_inl(port
, RL_TCR
);
2567 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_IFG_STD
);
2569 printf("rl_handler: reset after abort\n");
2571 if (rep
->re_flags
& REF_SEND_AVAIL
)
2573 printf("rl_handler: REF_SEND_AVAIL\n");
2574 rep
->re_send_int
= TRUE
;
2575 rep
->re_got_int
= TRUE
;
2576 int_event_check
= TRUE
;
2578 for (i
= 0; i
< N_TX_BUF
; i
++)
2579 rep
->re_tx
[i
].ret_busy
= FALSE
;
2582 printf("rl_handler, TABT, tasd = 0x%04x\n",
2585 /* Find the aborted transmit request */
2586 for (i
= 0; i
< N_TX_BUF
; i
++)
2588 tsd
= rl_inl(port
, RL_TSD0
+i
*4);
2589 if (tsd
& RL_TSD_TABT
)
2595 "rl_handler: can't find aborted TX req.\n");
2599 printf("TSD%d = 0x%04lx\n", i
, tsd
);
2601 /* Set head and tail to this buffer */
2602 rep
->re_tx_head
= rep
->re_tx_tail
= i
;
2605 /* Aborted transmission, just kick the device
2606 * and be done with it.
2608 rep
->re_stat
.ets_transAb
++;
2609 tcr
= rl_inl(port
, RL_TCR
);
2610 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
2614 /* Transmit completed */
2615 tx_head
= rep
->re_tx_head
;
2616 tx_tail
= rep
->re_tx_tail
;
2617 for (i
= 0; i
< 2*N_TX_BUF
; i
++)
2619 if (!rep
->re_tx
[tx_tail
].ret_busy
)
2621 /* Strange, this buffer is not in-use.
2622 * Increment tx_tail until tx_head is
2623 * reached (or until we find a buffer that
2626 if (tx_tail
== tx_head
)
2628 if (++tx_tail
>= N_TX_BUF
)
2630 assert(tx_tail
< RL_N_TX
);
2631 rep
->re_tx_tail
= tx_tail
;
2634 tsd
= rl_inl(port
, RL_TSD0
+tx_tail
*4);
2635 if (!(tsd
& RL_TSD_OWN
))
2637 /* Buffer is not yet ready */
2641 /* Should collect statistics */
2642 if (tsd
& RL_TSD_CRS
)
2643 rep
->re_stat
.ets_carrSense
++;
2644 if (tsd
& RL_TSD_TABT
)
2646 printf("rl_handler, TABT, TSD%d = 0x%04lx\n",
2648 assert(0); /* CLRABT is not all that
2649 * effective, why not?
2651 rep
->re_stat
.ets_transAb
++;
2652 tcr
= rl_inl(port
, RL_TCR
);
2653 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
2655 if (tsd
& RL_TSD_OWC
)
2656 rep
->re_stat
.ets_OWC
++;
2657 if (tsd
& RL_TSD_CDH
)
2658 rep
->re_stat
.ets_CDheartbeat
++;
2660 /* What about collisions? */
2661 if (tsd
& RL_TSD_TOK
)
2662 rep
->re_stat
.ets_packetT
++;
2664 rep
->re_stat
.ets_sendErr
++;
2665 if (tsd
& RL_TSD_TUN
)
2667 rep
->re_stat
.ets_fifoUnder
++;
2669 /* Increase ERTXTH */
2670 ertxth
= tsd
+ (1 << RL_TSD_ERTXTH_S
);
2671 ertxth
&= RL_TSD_ERTXTH_M
;
2672 if (debug
&& ertxth
> rep
->re_ertxth
)
2674 printf("%s: new ertxth: %ld bytes\n",
2676 (ertxth
>> RL_TSD_ERTXTH_S
) *
2678 rep
->re_ertxth
= ertxth
;
2681 rep
->re_tx
[tx_tail
].ret_busy
= FALSE
;
2684 if (rep
->re_flags
& REF_SEND_AVAIL
)
2686 printf("TSD%d: %08lx\n", tx_tail
, tsd
);
2688 "rl_handler: head %d, tail %d, busy: %d %d %d %d\n",
2690 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2691 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2695 if (++tx_tail
>= N_TX_BUF
)
2697 assert(tx_tail
< RL_N_TX
);
2698 rep
->re_tx_tail
= tx_tail
;
2700 if (rep
->re_flags
& REF_SEND_AVAIL
)
2703 printf("rl_handler: REF_SEND_AVAIL\n");
2705 rep
->re_send_int
= TRUE
;
2706 if (!rep
->re_got_int
)
2708 rep
->re_got_int
= TRUE
;
2709 int_event_check
= TRUE
;
2713 assert(i
< 2*N_TX_BUF
);
2717 printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
2724 /*===========================================================================*
2726 *===========================================================================*/
2727 static void rl_watchdog_f(tp
)
2732 /* Use a synchronous alarm instead of a watchdog timer. */
2733 sys_setalarm(system_hz
, 0);
2735 for (i
= 0, rep
= &re_table
[0]; i
<RE_PORT_NR
; i
++, rep
++)
2737 if (rep
->re_mode
!= REM_ENABLED
)
2739 if (!(rep
->re_flags
& REF_SEND_AVAIL
))
2741 /* Assume that an idle system is alive */
2742 rep
->re_tx_alive
= TRUE
;
2745 if (rep
->re_tx_alive
)
2747 rep
->re_tx_alive
= FALSE
;
2750 printf("rl_watchdog_f: resetting port %d\n", i
);
2752 "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
2753 rl_inw(rep
->re_base_port
, RL_TSAD
),
2754 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
2755 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
2756 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
2757 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
2758 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
2759 rep
->re_tx_head
, rep
->re_tx_tail
,
2760 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2761 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2762 rep
->re_need_reset
= TRUE
;
2763 rep
->re_got_int
= TRUE
;
2771 _PROTOTYPE( static void rtl_init
, (struct dpeth
*dep
) );
2772 _PROTOTYPE( static u16_t get_ee_word
, (dpeth_t
*dep
, int a
) );
2773 _PROTOTYPE( static void ee_wen
, (dpeth_t
*dep
) );
2774 _PROTOTYPE( static void set_ee_word
, (dpeth_t
*dep
, int a
, U16_t w
) );
2775 _PROTOTYPE( static void ee_wds
, (dpeth_t
*dep
) );
2777 static void rtl_init(dep
)
2780 u8_t reg_a
, reg_b
, cr
, config0
, config2
, config3
;
2784 printf("rtl_init called\n");
2788 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2789 reg_a
= inb_reg0(dep
, DP_DUM1
);
2790 reg_b
= inb_reg0(dep
, DP_DUM2
);
2792 printf("rtl_init: '%c', '%c'\n", reg_a
, reg_b
);
2794 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2795 config0
= inb_reg3(dep
, 3);
2796 config2
= inb_reg3(dep
, 5);
2797 config3
= inb_reg3(dep
, 6);
2798 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2800 printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
2801 config0
, config2
, config3
);
2803 if (0 == sys_getkenv("RTL8029FD",9+1, val
, sizeof(val
)))
2805 printf("rtl_init: setting full-duplex mode\n");
2806 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2808 cr
= inb_reg3(dep
, 1);
2809 outb_reg3(dep
, 1, cr
| 0xc0);
2811 outb_reg3(dep
, 6, config3
| 0x40);
2812 config3
= inb_reg3(dep
, 6);
2814 config2
= inb_reg3(dep
, 5);
2815 outb_reg3(dep
, 5, config2
| 0x20);
2816 config2
= inb_reg3(dep
, 5);
2818 outb_reg3(dep
, 1, cr
);
2820 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2822 printf("rtl_init: config 2 = %x\n", config2
);
2823 printf("rtl_init: config 3 = %x\n", config3
);
2826 for (i
= 0; i
<64; i
++)
2827 printf("%x ", get_ee_word(dep
, i
));
2830 if (0 == sys_getkenv("RTL8029MN",9+1, val
, sizeof(val
)))
2834 set_ee_word(dep
, 0x78/2, 0x10ec);
2835 set_ee_word(dep
, 0x7A/2, 0x8029);
2836 set_ee_word(dep
, 0x7C/2, 0x10ec);
2837 set_ee_word(dep
, 0x7E/2, 0x8029);
2841 assert(get_ee_word(dep
, 0x78/2) == 0x10ec);
2842 assert(get_ee_word(dep
, 0x7A/2) == 0x8029);
2843 assert(get_ee_word(dep
, 0x7C/2) == 0x10ec);
2844 assert(get_ee_word(dep
, 0x7E/2) == 0x8029);
2847 if (0 == sys_getkenv("RTL8029XXX",10+1, val
, sizeof(val
)))
2851 set_ee_word(dep
, 0x76/2, 0x8029);
2855 assert(get_ee_word(dep
, 0x76/2) == 0x8029);
2859 static u16_t
get_ee_word(dep
, a
)
2866 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2868 /* Switch to 9346 mode and enable CS */
2869 outb_reg3(dep
, 1, 0x80 | 0x8);
2871 cmd
= 0x180 | (a
& 0x3f); /* 1 1 0 a5 a4 a3 a2 a1 a0 */
2872 for (i
= 8; i
>= 0; i
--)
2874 b
= (cmd
& (1 << i
));
2877 /* Cmd goes out on the rising edge of the clock */
2878 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2879 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2881 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2884 for (i
= 0; i
<16; i
++)
2888 /* Data is shifted out on the rising edge. Read at the
2891 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4);
2892 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2893 b
= inb_reg3(dep
, 1);
2897 outb_reg3(dep
, 1, 0x80); /* drop CS */
2898 outb_reg3(dep
, 1, 0x00); /* back to normal */
2899 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
2904 static void ee_wen(dep
)
2910 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2912 /* Switch to 9346 mode and enable CS */
2913 outb_reg3(dep
, 1, 0x80 | 0x8);
2915 cmd
= 0x130; /* 1 0 0 1 1 x x x x */
2916 for (i
= 8; i
>= 0; i
--)
2918 b
= (cmd
& (1 << i
));
2921 /* Cmd goes out on the rising edge of the clock */
2922 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2923 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2925 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2926 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2927 /* micro_delay(1); */ /* Is this required? */
2930 static void set_ee_word(dep
, a
, w
)
2938 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
2940 cmd
= 0x140 | (a
& 0x3f); /* 1 0 1 a5 a4 a3 a2 a1 a0 */
2941 for (i
= 8; i
>= 0; i
--)
2943 b
= (cmd
& (1 << i
));
2946 /* Cmd goes out on the rising edge of the clock */
2947 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2948 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2950 for (i
= 15; i
>= 0; i
--)
2955 /* Cmd goes out on the rising edge of the clock */
2956 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2957 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2959 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of data */
2960 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2961 /* micro_delay(1); */ /* Is this required? */
2962 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
2965 if (inb_reg3(dep
, 1) & 1)
2967 } while (getuptime(&t1
) == OK
&& (t1
== t0
));
2968 if (!(inb_reg3(dep
, 1) & 1))
2969 panic("set_ee_word","device remains busy", NO_NUM
);
2972 static void ee_wds(dep
)
2978 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2980 /* Switch to 9346 mode and enable CS */
2981 outb_reg3(dep
, 1, 0x80 | 0x8);
2983 cmd
= 0x100; /* 1 0 0 0 0 x x x x */
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 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2994 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2995 outb_reg3(dep
, 1, 0x00); /* back to normal */
2996 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
3000 PRIVATE
void tell_dev(buf
, size
, pci_bus
, pci_dev
, pci_func
)
3012 r
= ds_retrieve_label_num("amddev", &u32
);
3017 "rtl8139`tell_dev: ds_retrieve_label_num failed for 'amddev': %d\n",
3025 m
.m_type
= IOMMU_MAP
;
3032 r
= sendrec(dev_e
, &m
);
3035 printf("rtl8139`tell_dev: sendrec to %d failed: %d\n",
3041 printf("rtl8139`tell_dev: dma map request failed: %d\n",
3048 * $PchId: rtl8139.c,v 1.3 2003/09/11 14:15:15 philip Exp $