4 * This file contains a ethernet device driver for Realtek rtl8139 based
7 * Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
9 * Aug 15, 2004 sync alarms replace watchdogs timers (Jorrit N. Herder)
10 * May 02, 2004 flag alarms replace micro_elapsed() (Jorrit N. Herder)
14 #define VERBOSE 0 /* Verbose debugging output */
15 #define RTL8139_FKEY 0 /* Use function key to dump RTL8139 status */
26 { 0x10ec, 0x8139, 0 }, /* Realtek RTL8139 */
29 { 0x02ac, 0x1012, 0 }, /* SpeedStream 1012 PCMCIA 10/100 */
30 { 0x1065, 0x8139, 0 }, /* Texas Microsystems 8139C Network Card */
31 { 0x1113, 0x1211, 0 }, /* Accton MPX5030 or SMC1211TX EZCard 10/100 */
32 { 0x1186, 0x1300, 0 }, /* D-Link DFE530TX+/DFE538TX */
33 { 0x1186, 0x1340, 0 }, /* D-Link DFE690TXD */
34 { 0x11db, 0x1234, 0 }, /* Sega Dreamcast HIT-400 */
35 { 0x1259, 0xa117, 0 }, /* Allied Telesyn 8139 */
36 { 0x1259, 0xa11e, 0 }, /* Allied Telesyn 8139 */
37 { 0x126c, 0x1211, 0 }, /* Northern Telecom 10/100BaseTX*/
38 { 0x13d1, 0xab06, 0 }, /* AboCom FE2000VX */
39 { 0x1432, 0x9130, 0 }, /* Edimax Computer Co. RTL81xx */
40 { 0x14ea, 0xab06, 0 }, /* Planex FNW-3603-TX */
41 { 0x14ea, 0xab07, 0 }, /* Planex FNW-3800-TX */
42 { 0x1500, 0x1360, 0 }, /* Delta Electronics RealTek Ethernet */
43 { 0x1743, 0x8139, 0 }, /* Peppercon AG 8139 ROL/F-100 */
44 { 0x4033, 0x1360, 0 }, /* Addtron Technology 8139 */
51 static int re_instance
;
53 static tmra_ut rl_watchdog
;
55 static unsigned my_inb(u16_t port
) {
58 if ((s
=sys_inb(port
, &value
)) !=OK
)
59 printf("RTL8139: warning, sys_inb failed: %d\n", s
);
62 static unsigned my_inw(u16_t port
) {
65 if ((s
=sys_inw(port
, &value
)) !=OK
)
66 printf("RTL8139: warning, sys_inw failed: %d\n", s
);
69 static unsigned my_inl(u16_t port
) {
72 if ((s
=sys_inl(port
, &value
)) !=OK
)
73 printf("RTL8139: warning, sys_inl failed: %d\n", s
);
76 #define rl_inb(port, offset) (my_inb((port) + (offset)))
77 #define rl_inw(port, offset) (my_inw((port) + (offset)))
78 #define rl_inl(port, offset) (my_inl((port) + (offset)))
80 static void my_outb(u16_t port
, u8_t value
) {
82 if ((s
=sys_outb(port
, value
)) !=OK
)
83 printf("RTL8139: warning, sys_outb failed: %d\n", s
);
85 static void my_outw(u16_t port
, u16_t value
) {
87 if ((s
=sys_outw(port
, value
)) !=OK
)
88 printf("RTL8139: warning, sys_outw failed: %d\n", s
);
90 static void my_outl(u16_t port
, u32_t value
) {
92 if ((s
=sys_outl(port
, value
)) !=OK
)
93 printf("RTL8139: warning, sys_outl failed: %d\n", s
);
95 #define rl_outb(port, offset, value) (my_outb((port) + (offset), (value)))
96 #define rl_outw(port, offset, value) (my_outw((port) + (offset), (value)))
97 #define rl_outl(port, offset, value) (my_outl((port) + (offset), (value)))
99 _PROTOTYPE( static void rl_init
, (message
*mp
) );
100 _PROTOTYPE( static void rl_pci_conf
, (void) );
101 _PROTOTYPE( static int rl_probe
, (re_t
*rep
, int skip
) );
102 _PROTOTYPE( static void rl_conf_hw
, (re_t
*rep
) );
103 _PROTOTYPE( static void rl_init_buf
, (re_t
*rep
) );
104 _PROTOTYPE( static void rl_init_hw
, (re_t
*rep
) );
105 _PROTOTYPE( static void rl_reset_hw
, (re_t
*rep
) );
106 _PROTOTYPE( static void rl_confaddr
, (re_t
*rep
) );
107 _PROTOTYPE( static void rl_rec_mode
, (re_t
*rep
) );
108 _PROTOTYPE( static void rl_readv_s
, (const message
*mp
, int from_int
) );
109 _PROTOTYPE( static void rl_writev_s
, (const message
*mp
, int from_int
) );
110 _PROTOTYPE( static void rl_check_ints
, (re_t
*rep
) );
111 _PROTOTYPE( static void rl_report_link
, (re_t
*rep
) );
112 _PROTOTYPE( static void mii_print_techab
, (u16_t techab
) );
113 _PROTOTYPE( static void mii_print_stat_speed
, (u16_t stat
,
115 _PROTOTYPE( static void rl_clear_rx
, (re_t
*rep
) );
116 _PROTOTYPE( static void rl_do_reset
, (re_t
*rep
) );
117 _PROTOTYPE( static void rl_getstat_s
, (message
*mp
) );
118 _PROTOTYPE( static void reply
, (re_t
*rep
) );
119 _PROTOTYPE( static void mess_reply
, (message
*req
, message
*reply
) );
120 _PROTOTYPE( static void check_int_events
, (void) );
121 _PROTOTYPE( static void do_hard_int
, (void) );
122 _PROTOTYPE( static void rtl8139_dump
, (message
*m
) );
124 _PROTOTYPE( static void dump_phy
, (re_t
*rep
) );
126 _PROTOTYPE( static int rl_handler
, (re_t
*rep
) );
127 _PROTOTYPE( static void rl_watchdog_f
, (timer_t
*tp
) );
128 _PROTOTYPE( static void tell_dev
, (vir_bytes start
, size_t size
,
129 int pci_bus
, int pci_dev
, int pci_func
) );
131 /* The message used in the main loop is made global, so that rl_watchdog_f()
132 * can change its message type to fake an interrupt message.
135 PRIVATE
int int_event_check
; /* set to TRUE if events arrived */
137 PRIVATE u32_t system_hz
;
139 /* SEF functions and variables. */
140 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
141 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
142 FORWARD
_PROTOTYPE( void sef_cb_signal_handler
, (int signo
) );
143 EXTERN
_PROTOTYPE( int sef_cb_lu_prepare
, (int state
) );
144 EXTERN
_PROTOTYPE( int sef_cb_lu_state_isvalid
, (int state
) );
145 EXTERN
_PROTOTYPE( void sef_cb_lu_state_dump
, (int state
) );
147 EXTERN
char **env_argv
;
149 /*===========================================================================*
151 *===========================================================================*/
152 int main(int argc
, char *argv
[])
157 /* SEF local startup. */
158 env_setargs(argc
, argv
);
163 if ((r
= netdriver_receive(ANY
, &m
, &ipc_status
)) != OK
)
164 panic("netdriver_receive failed: %d", r
);
166 if (is_ipc_notify(ipc_status
)) {
167 switch (_ENDPOINT_P(m
.m_source
)) {
170 * Under MINIX, synchronous alarms are
171 * used instead of watchdog functions.
172 * The approach is very different: MINIX
173 * VMD timeouts are handled within the
174 * kernel (the watchdog is executed by
175 * CLOCK), and notify() the driver in
176 * some cases. MINIX timeouts result in
177 * a SYN_ALARM message to the driver and
178 * thus are handled where they should be
179 * handled. Locally, watchdog functions
193 panic("illegal notify from: %d",
197 /* done, get nwe message */
203 case DL_WRITEV_S
: rl_writev_s(&m
, FALSE
); break;
204 case DL_READV_S
: rl_readv_s(&m
, FALSE
); break;
205 case DL_CONF
: rl_init(&m
); break;
206 case DL_GETSTAT_S
: rl_getstat_s(&m
); break;
208 panic("illegal message: %d", m
.m_type
);
213 /*===========================================================================*
214 * sef_local_startup *
215 *===========================================================================*/
216 PRIVATE
void sef_local_startup()
218 /* Register init callbacks. */
219 sef_setcb_init_fresh(sef_cb_init_fresh
);
220 sef_setcb_init_lu(sef_cb_init_fresh
);
221 sef_setcb_init_restart(sef_cb_init_fresh
);
223 /* Register live update callbacks. */
224 sef_setcb_lu_prepare(sef_cb_lu_prepare
);
225 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid
);
226 sef_setcb_lu_state_dump(sef_cb_lu_state_dump
);
228 /* Register signal callbacks. */
229 sef_setcb_signal_handler(sef_cb_signal_handler
);
231 /* Let SEF perform startup. */
235 /*===========================================================================*
236 * sef_cb_init_fresh *
237 *===========================================================================*/
238 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*UNUSED(info
))
240 /* Initialize the rtl8139 driver. */
243 int r
, fkeys
, sfkeys
;
246 system_hz
= sys_hz();
249 (void) env_parse("instance", "d", 0, &v
, 0, 255);
250 re_instance
= (int) v
;
253 /* Observe some function key for debug dumps. */
254 fkeys
= sfkeys
= 0; bit_set(sfkeys
, 9);
255 if ((r
=fkey_map(&fkeys
, &sfkeys
)) != OK
)
256 printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r
);
259 /* Claim buffer memory now. */
260 rl_init_buf(&re_state
);
262 /* Announce we are up! */
263 netdriver_announce();
268 /*===========================================================================*
269 * sef_cb_signal_handler *
270 *===========================================================================*/
271 PRIVATE
void sef_cb_signal_handler(int signo
)
275 /* Only check for termination signal, ignore anything else. */
276 if (signo
!= SIGTERM
) return;
279 if (rep
->re_mode
== REM_ENABLED
)
280 rl_outb(rep
->re_base_port
, RL_CR
, 0);
285 /*===========================================================================*
287 *===========================================================================*/
288 static void check_int_events(void)
294 if (rep
->re_mode
!= REM_ENABLED
)
296 if (!rep
->re_got_int
)
299 assert(rep
->re_flags
& REF_ENABLED
);
303 /*===========================================================================*
305 *===========================================================================*/
306 static void rtl8139_dump(m
)
307 message
*m
; /* pointer to request message */
314 if (rep
->re_mode
== REM_DISABLED
)
315 printf("Realtek RTL 8139 instance %d is disabled\n",
318 if (rep
->re_mode
!= REM_ENABLED
)
321 printf("Realtek RTL 8139 statistics of instance %d:\n", re_instance
);
323 printf("recvErr :%8ld\t", rep
->re_stat
.ets_recvErr
);
324 printf("sendErr :%8ld\t", rep
->re_stat
.ets_sendErr
);
325 printf("OVW :%8ld\n", rep
->re_stat
.ets_OVW
);
327 printf("CRCerr :%8ld\t", rep
->re_stat
.ets_CRCerr
);
328 printf("frameAll :%8ld\t", rep
->re_stat
.ets_frameAll
);
329 printf("missedP :%8ld\n", rep
->re_stat
.ets_missedP
);
331 printf("packetR :%8ld\t", rep
->re_stat
.ets_packetR
);
332 printf("packetT :%8ld\t", rep
->re_stat
.ets_packetT
);
333 printf("transDef :%8ld\n", rep
->re_stat
.ets_transDef
);
335 printf("collision :%8ld\t", rep
->re_stat
.ets_collision
);
336 printf("transAb :%8ld\t", rep
->re_stat
.ets_transAb
);
337 printf("carrSense :%8ld\n", rep
->re_stat
.ets_carrSense
);
339 printf("fifoUnder :%8ld\t", rep
->re_stat
.ets_fifoUnder
);
340 printf("fifoOver :%8ld\t", rep
->re_stat
.ets_fifoOver
);
341 printf("CDheartbeat:%8ld\n", rep
->re_stat
.ets_CDheartbeat
);
343 printf("OWC :%8ld\t", rep
->re_stat
.ets_OWC
);
345 printf("re_flags = 0x%x\n", rep
->re_flags
);
347 printf("TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
348 rl_inw(rep
->re_base_port
, RL_TSAD
),
349 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
350 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
351 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
352 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
353 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
354 rep
->re_tx_head
, rep
->re_tx_tail
,
355 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
356 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
359 /*===========================================================================*
361 *===========================================================================*/
362 static void rl_init(mp
)
365 static int first_time
= 1;
373 rl_pci_conf(); /* Configure PCI devices. */
375 tmra_inittimer(&rl_watchdog
);
376 /* Use a synchronous alarm instead of a watchdog timer. */
377 sys_setalarm(system_hz
, 0);
381 if (rep
->re_mode
== REM_DISABLED
)
383 /* This is the default, try to (re)locate the device. */
385 if (rep
->re_mode
== REM_DISABLED
)
387 /* Probe failed, or the device is configured off. */
388 reply_mess
.m_type
= DL_CONF_REPLY
;
389 reply_mess
.DL_STAT
= ENXIO
;
390 mess_reply(mp
, &reply_mess
);
393 if (rep
->re_mode
== REM_ENABLED
)
395 #if VERBOSE /* load silently ... can always check status later */
400 assert(rep
->re_mode
== REM_ENABLED
);
401 assert(rep
->re_flags
& REF_ENABLED
);
403 rep
->re_flags
&= ~(REF_PROMISC
| REF_MULTI
| REF_BROAD
);
405 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
406 rep
->re_flags
|= REF_PROMISC
;
407 if (mp
->DL_MODE
& DL_MULTI_REQ
)
408 rep
->re_flags
|= REF_MULTI
;
409 if (mp
->DL_MODE
& DL_BROAD_REQ
)
410 rep
->re_flags
|= REF_BROAD
;
414 reply_mess
.m_type
= DL_CONF_REPLY
;
415 reply_mess
.DL_STAT
= OK
;
416 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= rep
->re_address
;
418 mess_reply(mp
, &reply_mess
);
421 /*===========================================================================*
423 *===========================================================================*/
424 static void rl_pci_conf()
427 static char envvar
[] = RL_ENVVAR
"#";
428 static char envfmt
[] = "*:d.d.d";
429 static char val
[128];
434 strcpy(rep
->re_name
, "rtl8139#0");
435 rep
->re_name
[8] += re_instance
;
437 envvar
[sizeof(RL_ENVVAR
)-1]= '0'+re_instance
;
438 if (0 == env_get_param(envvar
, val
, sizeof(val
)) &&
439 ! env_prefix(envvar
, "pci")) {
443 (void) env_parse(envvar
, envfmt
, 1, &v
, 0, 255);
446 (void) env_parse(envvar
, envfmt
, 2, &v
, 0, 255);
449 (void) env_parse(envvar
, envfmt
, 3, &v
, 0, 255);
454 if (rl_probe(rep
, re_instance
))
458 /*===========================================================================*
460 *===========================================================================*/
461 static int rl_probe(rep
, skip
)
465 int i
, r
, devind
, just_one
;
471 if ((rep
->re_pcibus
| rep
->re_pcidev
| rep
->re_pcifunc
) != 0)
473 /* Look for specific PCI device */
474 r
= pci_find_dev(rep
->re_pcibus
, rep
->re_pcidev
,
475 rep
->re_pcifunc
, &devind
);
478 printf("%s: no PCI found at %d.%d.%d\n",
479 rep
->re_name
, rep
->re_pcibus
,
480 rep
->re_pcidev
, rep
->re_pcifunc
);
483 pci_ids(devind
, &vid
, &did
);
488 r
= pci_first_dev(&devind
, &vid
, &did
);
496 for (i
= 0; pcitab
[i
].vid
!= 0; i
++)
498 if (pcitab
[i
].vid
!= vid
)
500 if (pcitab
[i
].did
!= did
)
502 if (pcitab
[i
].checkclass
) {
503 panic("class check not implemented");
507 if (pcitab
[i
].vid
!= 0)
509 if (just_one
|| !skip
)
517 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
518 rep
->re_name
, vid
, did
,
520 rep
->re_pcidev
, rep
->re_pcifunc
);
524 r
= pci_next_dev(&devind
, &vid
, &did
);
529 #if VERBOSE /* stay silent at startup, can always get status later */
530 dname
= pci_dev_name(vid
, did
);
532 dname
= "unknown device";
533 printf("%s: ", rep
->re_name
);
534 printf("%s (%x/%x) at %s\n", dname
, vid
, did
, pci_slot_name(devind
));
537 /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
538 bar
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
540 panic("base address is not properly configured");
542 rep
->re_base_port
= bar
;
544 ilr
= pci_attr_r8(devind
, PCI_ILR
);
548 printf("%s: using I/O address 0x%lx, IRQ %d\n",
549 rep
->re_name
, (unsigned long)bar
, ilr
);
555 /*===========================================================================*
557 *===========================================================================*/
558 static void rl_conf_hw(rep
)
561 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
563 rep
->re_mode
= REM_DISABLED
; /* Superfluous */
567 /* PCI device is present */
568 rep
->re_mode
= REM_ENABLED
;
570 if (rep
->re_mode
!= REM_ENABLED
)
573 rep
->re_flags
= REF_EMPTY
;
574 rep
->re_link_up
= -1; /* Unknown */
577 rep
->re_report_link
= 0;
579 rep
->re_need_reset
= 0;
584 rep
->re_ertxth
= RL_TSD_ERTXTH_8
;
585 rep
->re_stat
= empty_stat
;
588 /*===========================================================================*
590 *===========================================================================*/
591 static void rl_init_buf(rep
)
594 size_t rx_bufsize
, tx_bufsize
, tot_bufsize
;
599 /* Allocate receive and transmit buffers */
600 tx_bufsize
= ETH_MAX_PACK_SIZE_TAGGED
;
602 tx_bufsize
+= 4-(tx_bufsize
% 4); /* Align */
603 rx_bufsize
= RX_BUFSIZE
;
604 tot_bufsize
= N_TX_BUF
*tx_bufsize
+ rx_bufsize
;
606 if (tot_bufsize
% 4096)
607 tot_bufsize
+= 4096-(tot_bufsize
% 4096);
609 #define BUF_ALIGNMENT (64*1024)
611 if(!(mallocbuf
= alloc_contig(BUF_ALIGNMENT
+ tot_bufsize
, 0, &buf
))) {
612 panic("Couldn't allocate kernel buffer");
615 /* click-align mallocced buffer. this is what we used to get
616 * from kmalloc() too.
618 if((off
= buf
% BUF_ALIGNMENT
)) {
619 mallocbuf
+= BUF_ALIGNMENT
- off
;
620 buf
+= BUF_ALIGNMENT
- off
;
623 tell_dev((vir_bytes
)mallocbuf
, tot_bufsize
, rep
->re_pcibus
,
624 rep
->re_pcidev
, rep
->re_pcifunc
);
626 for (i
= 0; i
<N_TX_BUF
; i
++)
628 rep
->re_tx
[i
].ret_buf
= buf
;
629 rep
->re_tx
[i
].v_ret_buf
= mallocbuf
;
631 mallocbuf
+= tx_bufsize
;
634 rep
->v_re_rx_buf
= mallocbuf
;
637 /*===========================================================================*
639 *===========================================================================*/
640 static void rl_init_hw(rep
)
645 rep
->re_flags
= REF_EMPTY
;
646 rep
->re_flags
|= REF_ENABLED
;
648 /* Set the interrupt handler. The policy is to only send HARD_INT
649 * notifications. Don't reenable interrupts automatically. The id
650 * that is passed back is the interrupt line number.
652 rep
->re_hook_id
= rep
->re_irq
;
653 if ((s
=sys_irqsetpolicy(rep
->re_irq
, 0, &rep
->re_hook_id
)) != OK
)
654 printf("RTL8139: error, couldn't set IRQ policy: %d\n", s
);
658 if ((s
=sys_irqenable(&rep
->re_hook_id
)) != OK
)
659 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
661 #if VERBOSE /* stay silent during startup, can always get status later */
663 printf("%s: model %s\n", rep
->re_name
, rep
->re_model
);
666 printf("%s: unknown model 0x%08x\n",
668 rl_inl(rep
->re_base_port
, RL_TCR
) &
669 (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
));
676 printf("%s: Ethernet address ", rep
->re_name
);
677 for (i
= 0; i
< 6; i
++)
679 printf("%x%c", rep
->re_address
.ea_addr
[i
],
685 /*===========================================================================*
687 *===========================================================================*/
688 static void rl_reset_hw(rep
)
697 port
= rep
->re_base_port
;
701 rl_outb(port
, RL_BMCR
, MII_CTRL_RST
);
704 if (!(rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
))
706 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
707 if (rl_inb(port
, RL_BMCR
) & MII_CTRL_RST
)
708 panic("reset PHY failed to complete");
711 /* Reset the device */
713 printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
714 port
, rl_inb(port
, RL_CR
));
716 rl_outb(port
, RL_CR
, RL_CR_RST
);
719 if (!(rl_inb(port
, RL_CR
) & RL_CR_RST
))
721 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
723 printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
724 port
, rl_inb(port
, RL_CR
));
726 if (rl_inb(port
, RL_CR
) & RL_CR_RST
)
727 printf("rtl8139: reset failed to complete");
729 t
= rl_inl(port
, RL_TCR
);
730 switch(t
& (RL_TCR_HWVER_AM
| RL_TCR_HWVER_BM
))
732 case RL_TCR_HWVER_RTL8139
: rep
->re_model
= "RTL8139"; break;
733 case RL_TCR_HWVER_RTL8139A
: rep
->re_model
= "RTL8139A"; break;
734 case RL_TCR_HWVER_RTL8139AG
:
735 rep
->re_model
= "RTL8139A-G / RTL8139C";
737 case RL_TCR_HWVER_RTL8139B
:
738 rep
->re_model
= "RTL8139B / RTL8130";
740 case RL_TCR_HWVER_RTL8100
: rep
->re_model
= "RTL8100"; break;
741 case RL_TCR_HWVER_RTL8100B
:
742 rep
->re_model
= "RTL8100B/RTL8139D";
744 case RL_TCR_HWVER_RTL8139CP
: rep
->re_model
= "RTL8139C+"; break;
745 case RL_TCR_HWVER_RTL8101
: rep
->re_model
= "RTL8101"; break;
752 printf("REVID: 0x%02x\n", rl_inb(port
, RL_REVID
));
757 /* Should init multicast mask */
759 08-0f R
/W MAR
[0-7] multicast
761 bus_buf
= vm_1phys2bus(rep
->re_rx_buf
);
762 rl_outl(port
, RL_RBSTART
, bus_buf
);
765 for (i
= 0; i
<N_TX_BUF
; i
++)
767 rep
->re_tx
[i
].ret_busy
= FALSE
;
768 bus_buf
= vm_1phys2bus(rep
->re_tx
[i
].ret_buf
);
769 rl_outl(port
, RL_TSAD0
+i
*4, bus_buf
);
770 t
= rl_inl(port
, RL_TSD0
+i
*4);
771 assert(t
& RL_TSD_OWN
);
778 t
= rl_inw(port
, RL_IMR
);
779 rl_outw(port
, RL_IMR
, t
| (RL_IMR_SERR
| RL_IMR_TIMEOUT
|
782 t
= rl_inw(port
, RL_IMR
);
783 rl_outw(port
, RL_IMR
, t
| (RL_IMR_FOVW
| RL_IMR_PUN
|
784 RL_IMR_RXOVW
| RL_IMR_RER
| RL_IMR_ROK
));
786 t
= rl_inw(port
, RL_IMR
);
787 rl_outw(port
, RL_IMR
, t
| (RL_IMR_TER
| RL_IMR_TOK
));
789 t
= rl_inb(port
, RL_CR
);
790 rl_outb(port
, RL_CR
, t
| RL_CR_RE
);
792 t
= rl_inb(port
, RL_CR
);
793 rl_outb(port
, RL_CR
, t
| RL_CR_TE
);
795 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
797 t
= rl_inl(port
, RL_TCR
);
798 rl_outl(port
, RL_TCR
, t
| RL_TCR_IFG_STD
);
801 /*===========================================================================*
803 *===========================================================================*/
804 static void rl_confaddr(rep
)
807 static char eakey
[]= RL_ENVVAR
"#_EA";
808 static char eafmt
[]= "x:x:x:x:x:x";
815 /* User defined ethernet address? */
816 eakey
[sizeof(RL_ENVVAR
)-1]= '0' + re_instance
;
818 port
= rep
->re_base_port
;
820 for (i
= 0; i
< 6; i
++)
822 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
824 rep
->re_address
.ea_addr
[i
]= v
;
827 if (i
!= 0 && i
!= 6) env_panic(eakey
); /* It's all or nothing */
829 /* Should update ethernet address in hardware */
832 port
= rep
->re_base_port
;
833 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_CONFIG
);
836 w
|= (rep
->re_address
.ea_addr
[i
] << (i
*8));
837 rl_outl(port
, RL_IDR
, w
);
840 w
|= (rep
->re_address
.ea_addr
[i
] << ((i
-4)*8));
841 rl_outl(port
, RL_IDR
+4, w
);
842 rl_outb(port
, RL_9346CR
, RL_9346CR_EEM_NORMAL
);
845 /* Get ethernet address */
847 rep
->re_address
.ea_addr
[i
]= rl_inb(port
, RL_IDR
+i
);
850 /*===========================================================================*
852 *===========================================================================*/
853 static void rl_rec_mode(rep
)
859 port
= rep
->re_base_port
;
860 rcr
= rl_inl(port
, RL_RCR
);
861 rcr
&= ~(RL_RCR_AB
|RL_RCR_AM
|RL_RCR_APM
|RL_RCR_AAP
);
862 if (rep
->re_flags
& REF_PROMISC
)
863 rcr
|= RL_RCR_AB
| RL_RCR_AM
| RL_RCR_AAP
;
864 if (rep
->re_flags
& REF_BROAD
)
866 if (rep
->re_flags
& REF_MULTI
)
870 rl_outl(port
, RL_RCR
, rcr
);
873 /*===========================================================================*
875 *===========================================================================*/
876 static void rl_readv_s(const message
*mp
, int from_int
)
878 int i
, j
, n
, o
, s
, s1
, count
, size
;
880 unsigned amount
, totlen
, packlen
;
882 u16_t d_start
, d_end
;
883 u32_t l
, rxstat
= 0x12345678;
891 rep
->re_client
= mp
->m_source
;
892 count
= mp
->DL_COUNT
;
894 if (rep
->re_clear_rx
)
895 goto suspend
; /* Buffer overflow */
897 assert(rep
->re_mode
== REM_ENABLED
);
898 assert(rep
->re_flags
& REF_ENABLED
);
900 port
= rep
->re_base_port
;
902 /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
904 if (!from_int
&& (rl_inb(port
, RL_CR
) & RL_CR_BUFE
))
906 /* Receive buffer is empty, suspend */
910 d_start
= rl_inw(port
, RL_CAPR
) + RL_CAPR_DATA_OFF
;
911 d_end
= rl_inw(port
, RL_CBR
) % RX_BUFSIZE
;
913 if (d_start
>= RX_BUFSIZE
)
915 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
916 rl_inw(port
, RL_CAPR
));
917 d_start
%= RX_BUFSIZE
;
921 amount
= d_end
-d_start
;
923 amount
= d_end
+RX_BUFSIZE
- d_start
;
925 rxstat
= *(u32_t
*) (rep
->v_re_rx_buf
+ d_start
);
927 if (rep
->re_clear_rx
)
930 printf("rl_readv: late buffer overflow\n");
932 goto suspend
; /* Buffer overflow */
935 /* Should convert from little endian to host byte order */
937 if (!(rxstat
& RL_RXS_ROK
))
939 printf("rxstat = 0x%08lx\n", rxstat
);
940 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
941 d_start
, d_end
, rxstat
);
942 panic("received packet not OK");
944 totlen
= (rxstat
>> RL_RXS_LEN_S
);
945 if (totlen
< 8 || totlen
> 2*ETH_MAX_PACK_SIZE
)
947 /* Someting went wrong */
949 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
950 totlen
, rxstat
, d_start
);
952 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
953 d_start
, d_end
, totlen
, rxstat
);
958 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
959 d_start
, d_end
, totlen
, rxstat
);
962 if (totlen
+4 > amount
)
964 printf("rl_readv: packet not yet ready\n");
968 /* Should subtract the CRC */
969 packlen
= totlen
- ETH_CRC_SIZE
;
973 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
974 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
980 cps
= sys_safecopyfrom(mp
->DL_ENDPT
, mp
->DL_GRANT
, iov_offset
,
981 (vir_bytes
) rep
->re_iovec_s
,
982 n
* sizeof(rep
->re_iovec_s
[0]), D
);
984 panic("rl_readv_s: sys_safecopyfrom failed: %d",
988 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
991 if (size
+ s
> packlen
)
993 assert(packlen
> size
);
998 if (sys_umap(mp
->DL_ENDPT
, D
, iovp
->iov_addr
, s
, &dst_phys
) != OK
)
999 panic("umap_local failed");
1002 if (o
>= RX_BUFSIZE
)
1005 assert(o
< RX_BUFSIZE
);
1008 if (o
+s
> RX_BUFSIZE
)
1010 assert(o
<RX_BUFSIZE
);
1013 cps
= sys_safecopyto(mp
->DL_ENDPT
,
1015 (vir_bytes
) rep
->v_re_rx_buf
+o
, s1
, D
);
1017 panic("rl_readv_s: sys_safecopyto failed: %d",
1020 cps
= sys_safecopyto(mp
->DL_ENDPT
,
1021 iovp
->iov_grant
, s1
,
1022 (vir_bytes
) rep
->v_re_rx_buf
, s
-s1
, S
);
1024 panic("rl_readv_s: sys_safecopyto failed: %d", cps
);
1029 cps
= sys_safecopyto(mp
->DL_ENDPT
,
1031 (vir_bytes
) rep
->v_re_rx_buf
+o
, s
, D
);
1033 panic("rl_readv_s: sys_safecopyto failed: %d", cps
);
1037 if (size
== packlen
)
1041 if (size
== packlen
)
1049 if (rep
->re_clear_rx
)
1051 /* For some reason the receiver FIFO is not stopped when
1052 * the buffer is full.
1055 printf("rl_readv: later buffer overflow\n");
1057 goto suspend
; /* Buffer overflow */
1060 rep
->re_stat
.ets_packetR
++;
1061 rep
->re_read_s
= packlen
;
1062 rep
->re_flags
= (rep
->re_flags
& ~REF_READING
) | REF_PACK_RECV
;
1064 /* Avoid overflow in 16-bit computations */
1067 l
= (l
+3) & ~3; /* align */
1068 if (l
>= RX_BUFSIZE
)
1071 assert(l
< RX_BUFSIZE
);
1073 rl_outw(port
, RL_CAPR
, l
-RL_CAPR_DATA_OFF
);
1083 assert(rep
->re_flags
& REF_READING
);
1085 /* No need to store any state */
1089 rep
->re_rx_mess
= *mp
;
1090 assert(!(rep
->re_flags
& REF_READING
));
1091 rep
->re_flags
|= REF_READING
;
1096 /*===========================================================================*
1098 *===========================================================================*/
1099 static void rl_writev_s(const message
*mp
, int from_int
)
1101 int i
, j
, n
, s
, count
, size
;
1111 rep
->re_client
= mp
->m_source
;
1112 count
= mp
->DL_COUNT
;
1114 assert(rep
->re_mode
== REM_ENABLED
);
1115 assert(rep
->re_flags
& REF_ENABLED
);
1119 assert(rep
->re_flags
& REF_SEND_AVAIL
);
1120 rep
->re_flags
&= ~REF_SEND_AVAIL
;
1121 rep
->re_send_int
= FALSE
;
1122 rep
->re_tx_alive
= TRUE
;
1125 tx_head
= rep
->re_tx_head
;
1126 if (rep
->re_tx
[tx_head
].ret_busy
)
1128 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1129 rep
->re_flags
|= REF_SEND_AVAIL
;
1133 assert(!(rep
->re_flags
& REF_SEND_AVAIL
));
1134 assert(!(rep
->re_flags
& REF_PACK_SENT
));
1137 ret
= rep
->re_tx
[tx_head
].v_ret_buf
;
1138 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1139 iov_offset
+= IOVEC_NR
* sizeof(rep
->re_iovec_s
[0]))
1144 cps
= sys_safecopyfrom(mp
->DL_ENDPT
, mp
->DL_GRANT
, iov_offset
,
1145 (vir_bytes
) rep
->re_iovec_s
,
1146 n
* sizeof(rep
->re_iovec_s
[0]), D
);
1148 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps
);
1151 for (j
= 0, iovp
= rep
->re_iovec_s
; j
<n
; j
++, iovp
++)
1154 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
) {
1155 panic("invalid packet size");
1157 cps
= sys_safecopyfrom(mp
->DL_ENDPT
, iovp
->iov_grant
,
1158 0, (vir_bytes
) ret
, s
, D
);
1160 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps
);
1166 if (size
< ETH_MIN_PACK_SIZE
)
1167 panic("invalid packet size: %d", size
);
1169 rl_outl(rep
->re_base_port
, RL_TSD0
+tx_head
*4,
1170 rep
->re_ertxth
| size
);
1171 rep
->re_tx
[tx_head
].ret_busy
= TRUE
;
1173 if (++tx_head
== N_TX_BUF
)
1175 assert(tx_head
< RL_N_TX
);
1176 rep
->re_tx_head
= tx_head
;
1178 rep
->re_flags
|= REF_PACK_SENT
;
1180 /* If the interrupt handler called, don't send a reply. The reply
1181 * will be sent after all interrupts are handled.
1190 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
1191 tx_head
, rep
->re_tx_tail
,
1192 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1193 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1194 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
1195 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
1196 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
1197 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
1198 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
1202 panic("should not be sending");
1204 rep
->re_tx_mess
= *mp
;
1208 /*===========================================================================*
1210 *===========================================================================*/
1211 static void rl_check_ints(rep
)
1215 10-1f R
/W TSD
[0-3] Transmit Status of Descriptor
[0-3]
1216 31 R CRS Carrier Sense Lost
1217 30 R TABT Transmit Abort
1218 29 R OWC Out of Window Collision
1219 27-24 R NCC
[3-0] Number of Collision Count
1221 21-16 R
/W ERTXH
[5-0] Early Tx Threshold
1222 15 R TOK Transmit OK
1223 14 R TUN Transmit FIFO Underrun
1225 12-0 R
/W SIZE Descriptor Size
1226 3e-3f R
/W ISR Interrupt Status Register
1227 6 R
/W FOVW Fx FIFO Overflow Interrupt
1228 5 R
/W PUN
/LinkChg Packet Underrun
/ Link Change Interrupt
1229 3 R
/W TER Transmit Error Interrupt
1230 2 R
/W TOK Transmit OK Interrupt
1231 3e-3f R
/W ISR Interrupt Status Register
1232 15 R
/W SERR System Error Interrupt
1233 14 R
/W TimeOut Time Out Interrupt
1234 13 R
/W LenChg Cable Length Change Interrupt
1235 3e-3f R
/W ISR Interrupt Status Register
1236 4 R
/W RXOVW Rx Buffer Overflow Interrupt
1237 1 R
/W RER Receive Error Interrupt
1238 0 R
/W ROK Receive OK Interrupt
1239 4c
-4f R
/W MPC Missed Packet Counter
1240 60-61 R TSAD Transmit Status of All Descriptors
1241 15-12 R TOK
[3-0] TOK bit of Descriptor
[3-0]
1242 11-8 R TUN
[3-0] TUN bit of Descriptor
[3-0]
1243 7-4 R TABT
[3-0] TABT bit of Descriptor
[3-0]
1244 3-0 R OWN
[3-0] OWN bit of Descriptor
[3-0]
1245 6c
-6d R DIS Disconnect Counter
1246 15-0 R DCNT Disconnect Counter
1247 6e-6f R FCSC False Carrier Sense Counter
1248 15-0 R FCSCNT False Carrier event counter
1249 72-73 R REC RX_ER Counter
1250 15-0 R RXERCNT Received packet counter
1255 re_flags
= rep
->re_flags
;
1257 if ((re_flags
& REF_READING
) &&
1258 !(rl_inb(rep
->re_base_port
, RL_CR
) & RL_CR_BUFE
))
1260 rl_readv_s(&rep
->re_rx_mess
, TRUE
/* from int */);
1262 if (rep
->re_clear_rx
)
1265 if (rep
->re_need_reset
)
1268 if (rep
->re_send_int
)
1270 rl_writev_s(&rep
->re_tx_mess
, TRUE
/* from int */);
1273 if (rep
->re_report_link
)
1274 rl_report_link(rep
);
1276 if (rep
->re_flags
& (REF_PACK_SENT
| REF_PACK_RECV
))
1280 /*===========================================================================*
1282 *===========================================================================*/
1283 static void rl_report_link(rep
)
1287 u16_t mii_ctrl
, mii_status
, mii_ana
, mii_anlpa
, mii_ane
, mii_extstat
;
1291 rep
->re_report_link
= FALSE
;
1292 port
= rep
->re_base_port
;
1293 msr
= rl_inb(port
, RL_MSR
);
1294 link_up
= !(msr
& RL_MSR_LINKB
);
1295 rep
->re_link_up
= link_up
;
1298 printf("%s: link down\n", rep
->re_name
);
1302 mii_ctrl
= rl_inw(port
, RL_BMCR
);
1303 mii_status
= rl_inw(port
, RL_BMSR
);
1304 mii_ana
= rl_inw(port
, RL_ANAR
);
1305 mii_anlpa
= rl_inw(port
, RL_ANLPAR
);
1306 mii_ane
= rl_inw(port
, RL_ANER
);
1309 if (mii_ctrl
& (MII_CTRL_LB
|MII_CTRL_PD
|MII_CTRL_ISO
))
1311 printf("%s: PHY: ", rep
->re_name
);
1313 if (mii_ctrl
& MII_CTRL_LB
)
1315 printf("loopback mode");
1318 if (mii_ctrl
& MII_CTRL_PD
)
1320 if (!f
) printf(", ");
1322 printf("powered down");
1324 if (mii_ctrl
& MII_CTRL_ISO
)
1326 if (!f
) printf(", ");
1333 if (!(mii_ctrl
& MII_CTRL_ANE
))
1335 printf("%s: manual config: ", rep
->re_name
);
1336 switch(mii_ctrl
& (MII_CTRL_SP_LSB
|MII_CTRL_SP_MSB
))
1338 case MII_CTRL_SP_10
: printf("10 Mbps"); break;
1339 case MII_CTRL_SP_100
: printf("100 Mbps"); break;
1340 case MII_CTRL_SP_1000
: printf("1000 Mbps"); break;
1341 case MII_CTRL_SP_RES
: printf("reserved speed"); break;
1343 if (mii_ctrl
& MII_CTRL_DM
)
1344 printf(", full duplex");
1346 printf(", half duplex");
1351 if (!debug
) goto resspeed
;
1353 printf("%s: ", rep
->re_name
);
1354 mii_print_stat_speed(mii_status
, mii_extstat
);
1357 if (!(mii_status
& MII_STATUS_ANC
))
1358 printf("%s: auto-negotiation not complete\n", rep
->re_name
);
1359 if (mii_status
& MII_STATUS_RF
)
1360 printf("%s: remote fault detected\n", rep
->re_name
);
1361 if (!(mii_status
& MII_STATUS_ANA
))
1363 printf("%s: local PHY has no auto-negotiation ability\n",
1366 if (!(mii_status
& MII_STATUS_LS
))
1367 printf("%s: link down\n", rep
->re_name
);
1368 if (mii_status
& MII_STATUS_JD
)
1369 printf("%s: jabber condition detected\n", rep
->re_name
);
1370 if (!(mii_status
& MII_STATUS_EC
))
1372 printf("%s: no extended register set\n", rep
->re_name
);
1375 if (!(mii_status
& MII_STATUS_ANC
))
1378 printf("%s: local cap.: ", rep
->re_name
);
1379 mii_print_techab(mii_ana
);
1382 if (mii_ane
& MII_ANE_PDF
)
1383 printf("%s: parallel detection fault\n", rep
->re_name
);
1384 if (!(mii_ane
& MII_ANE_LPANA
))
1386 printf("%s: link-partner does not support auto-negotiation\n",
1391 printf("%s: remote cap.: ", rep
->re_name
);
1392 mii_print_techab(mii_anlpa
);
1396 printf("%s: ", rep
->re_name
);
1397 printf("link up at %d Mbps, ", (msr
& RL_MSR_SPEED_10
) ? 10 : 100);
1398 printf("%s duplex\n", ((mii_ctrl
& MII_CTRL_DM
) ? "full" : "half"));
1402 static void mii_print_techab(u16_t techab
)
1405 if ((techab
& MII_ANA_SEL_M
) != MII_ANA_SEL_802_3
)
1407 printf("strange selector 0x%x, value 0x%x",
1408 techab
& MII_ANA_SEL_M
,
1409 (techab
& MII_ANA_TAF_M
) >> MII_ANA_TAF_S
);
1413 if (techab
& (MII_ANA_100T4
| MII_ANA_100TXFD
| MII_ANA_100TXHD
))
1415 printf("100 Mbps: ");
1418 if (techab
& MII_ANA_100T4
)
1423 if (techab
& (MII_ANA_100TXFD
| MII_ANA_100TXHD
))
1429 switch(techab
& (MII_ANA_100TXFD
|MII_ANA_100TXHD
))
1431 case MII_ANA_100TXFD
: printf("FD"); break;
1432 case MII_ANA_100TXHD
: printf("HD"); break;
1433 default: printf("FD/HD"); break;
1437 if (techab
& (MII_ANA_10TFD
| MII_ANA_10THD
))
1441 printf("10 Mbps: ");
1444 switch(techab
& (MII_ANA_10TFD
|MII_ANA_10THD
))
1446 case MII_ANA_10TFD
: printf("FD"); break;
1447 case MII_ANA_10THD
: printf("HD"); break;
1448 default: printf("FD/HD"); break;
1451 if (techab
& MII_ANA_PAUSE_SYM
)
1456 printf("pause(SYM)");
1458 if (techab
& MII_ANA_PAUSE_ASYM
)
1463 printf("pause(ASYM)");
1465 if (techab
& MII_ANA_TAF_RES
)
1470 printf("0x%x", (techab
& MII_ANA_TAF_RES
) >> MII_ANA_TAF_S
);
1474 static void mii_print_stat_speed(u16_t stat
, u16_t extstat
)
1478 if (stat
& MII_STATUS_EXT_STAT
)
1480 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
|
1481 MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
1483 printf("1000 Mbps: ");
1486 if (extstat
& (MII_ESTAT_1000XFD
| MII_ESTAT_1000XHD
))
1491 (MII_ESTAT_1000XFD
|MII_ESTAT_1000XHD
))
1493 case MII_ESTAT_1000XFD
: printf("FD"); break;
1494 case MII_ESTAT_1000XHD
: printf("HD"); break;
1495 default: printf("FD/HD"); break;
1498 if (extstat
& (MII_ESTAT_1000TFD
| MII_ESTAT_1000THD
))
1505 (MII_ESTAT_1000TFD
|MII_ESTAT_1000THD
))
1507 case MII_ESTAT_1000TFD
: printf("FD"); break;
1508 case MII_ESTAT_1000THD
: printf("HD"); break;
1509 default: printf("FD/HD"); break;
1514 if (stat
& (MII_STATUS_100T4
|
1515 MII_STATUS_100XFD
| MII_STATUS_100XHD
|
1516 MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
1521 printf("100 Mbps: ");
1523 if (stat
& MII_STATUS_100T4
)
1528 if (stat
& (MII_STATUS_100XFD
| MII_STATUS_100XHD
))
1534 switch(stat
& (MII_STATUS_100XFD
|MII_STATUS_100XHD
))
1536 case MII_STATUS_100XFD
: printf("FD"); break;
1537 case MII_STATUS_100XHD
: printf("HD"); break;
1538 default: printf("FD/HD"); break;
1541 if (stat
& (MII_STATUS_100T2FD
| MII_STATUS_100T2HD
))
1547 switch(stat
& (MII_STATUS_100T2FD
|MII_STATUS_100T2HD
))
1549 case MII_STATUS_100T2FD
: printf("FD"); break;
1550 case MII_STATUS_100T2HD
: printf("HD"); break;
1551 default: printf("FD/HD"); break;
1555 if (stat
& (MII_STATUS_10FD
| MII_STATUS_10HD
))
1559 printf("10 Mbps: ");
1562 switch(stat
& (MII_STATUS_10FD
|MII_STATUS_10HD
))
1564 case MII_STATUS_10FD
: printf("FD"); break;
1565 case MII_STATUS_10HD
: printf("HD"); break;
1566 default: printf("FD/HD"); break;
1571 /*===========================================================================*
1573 *===========================================================================*/
1574 static void rl_clear_rx(re_t
*rep
)
1580 rep
->re_clear_rx
= FALSE
;
1581 port
= rep
->re_base_port
;
1583 /* Reset the receiver */
1584 cr
= rl_inb(port
, RL_CR
);
1586 rl_outb(port
, RL_CR
, cr
);
1589 if (!(rl_inb(port
, RL_CR
) & RL_CR_RE
))
1591 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
1592 if (rl_inb(port
, RL_CR
) & RL_CR_RE
)
1593 panic("cannot disable receiver");
1596 printf("RBSTART = 0x%08x\n", rl_inl(port
, RL_RBSTART
));
1597 printf("CAPR = 0x%04x\n", rl_inw(port
, RL_CAPR
));
1598 printf("CBR = 0x%04x\n", rl_inw(port
, RL_CBR
));
1599 printf("RCR = 0x%08x\n", rl_inl(port
, RL_RCR
));
1602 rl_outb(port
, RL_CR
, cr
| RL_CR_RE
);
1604 rl_outl(port
, RL_RCR
, RX_BUFBITS
);
1608 rep
->re_stat
.ets_missedP
++;
1611 /*===========================================================================*
1613 *===========================================================================*/
1614 static void rl_do_reset(rep
)
1617 rep
->re_need_reset
= FALSE
;
1622 if (rep
->re_flags
& REF_SEND_AVAIL
)
1624 rep
->re_tx
[rep
->re_tx_head
].ret_busy
= FALSE
;
1625 rep
->re_send_int
= TRUE
;
1629 /*===========================================================================*
1631 *===========================================================================*/
1632 static void rl_getstat_s(mp
)
1641 assert(rep
->re_mode
== REM_ENABLED
);
1642 assert(rep
->re_flags
& REF_ENABLED
);
1644 stats
= rep
->re_stat
;
1646 r
= sys_safecopyto(mp
->DL_ENDPT
, mp
->DL_GRANT
, 0,
1647 (vir_bytes
) &stats
, sizeof(stats
), D
);
1649 panic("rl_getstat_s: sys_safecopyto failed: %d", r
);
1651 mp
->m_type
= DL_STAT_REPLY
;
1652 r
= send(mp
->m_source
, mp
);
1654 panic("rl_getstat_s: send failed: %d", r
);
1657 /*===========================================================================*
1659 *===========================================================================*/
1660 static void reply(rep
)
1668 if (rep
->re_flags
& REF_PACK_SENT
)
1669 flags
|= DL_PACK_SEND
;
1670 if (rep
->re_flags
& REF_PACK_RECV
)
1671 flags
|= DL_PACK_RECV
;
1673 reply
.m_type
= DL_TASK_REPLY
;
1674 reply
.DL_FLAGS
= flags
;
1675 reply
.DL_COUNT
= rep
->re_read_s
;
1677 r
= send(rep
->re_client
, &reply
);
1680 printf("RTL8139 tried sending to %d, type %d\n",
1681 rep
->re_client
, reply
.m_type
);
1682 panic("send failed: %d", r
);
1686 rep
->re_flags
&= ~(REF_PACK_SENT
| REF_PACK_RECV
);
1689 /*===========================================================================*
1691 *===========================================================================*/
1692 static void mess_reply(req
, reply_mess
)
1694 message
*reply_mess
;
1696 if (send(req
->m_source
, reply_mess
) != OK
)
1697 panic("unable to mess_reply");
1701 /*===========================================================================*
1703 *===========================================================================*/
1704 static void dump_phy(rep
)
1710 port
= rep
->re_base_port
;
1712 t
= rl_inb(port
, RL_MSR
);
1713 printf("MSR: 0x%02lx\n", t
);
1714 if (t
& RL_MSR_SPEED_10
)
1715 printf("\t10 Mbps\n");
1716 if (t
& RL_MSR_LINKB
)
1717 printf("\tLink failed\n");
1719 t
= rl_inb(port
, RL_CONFIG1
);
1720 printf("CONFIG1: 0x%02lx\n", t
);
1722 t
= rl_inb(port
, RL_CONFIG3
);
1723 printf("CONFIG3: 0x%02lx\n", t
);
1725 t
= rl_inb(port
, RL_CONFIG4
);
1726 printf("CONFIG4: 0x%02lx\n", t
);
1728 t
= rl_inw(port
, RL_BMCR
);
1729 printf("BMCR (MII_CTRL): 0x%04lx\n", t
);
1731 t
= rl_inw(port
, RL_BMSR
);
1733 if (t
& MII_STATUS_100T4
)
1734 printf(" 100Base-T4");
1735 if (t
& MII_STATUS_100XFD
)
1736 printf(" 100Base-X-FD");
1737 if (t
& MII_STATUS_100XHD
)
1738 printf(" 100Base-X-HD");
1739 if (t
& MII_STATUS_10FD
)
1740 printf(" 10Mbps-FD");
1741 if (t
& MII_STATUS_10HD
)
1742 printf(" 10Mbps-HD");
1743 if (t
& MII_STATUS_100T2FD
)
1744 printf(" 100Base-T2-FD");
1745 if (t
& MII_STATUS_100T2HD
)
1746 printf(" 100Base-T2-HD");
1747 if (t
& MII_STATUS_EXT_STAT
)
1748 printf(" Ext-stat");
1749 if (t
& MII_STATUS_RES
)
1750 printf(" res-0x%lx", t
& MII_STATUS_RES
);
1751 if (t
& MII_STATUS_MFPS
)
1753 if (t
& MII_STATUS_ANC
)
1755 if (t
& MII_STATUS_RF
)
1756 printf(" remote-fault");
1757 if (t
& MII_STATUS_ANA
)
1759 if (t
& MII_STATUS_LS
)
1761 if (t
& MII_STATUS_JD
)
1763 if (t
& MII_STATUS_EC
)
1764 printf(" Extended-capability");
1767 t
= rl_inw(port
, RL_ANAR
);
1768 printf("ANAR (MII_ANA): 0x%04lx\n", t
);
1770 t
= rl_inw(port
, RL_ANLPAR
);
1771 printf("ANLPAR: 0x%04lx\n", t
);
1773 t
= rl_inw(port
, RL_ANER
);
1774 printf("ANER (MII_ANE): ");
1775 if (t
& MII_ANE_RES
)
1776 printf(" res-0x%lx", t
& MII_ANE_RES
);
1777 if (t
& MII_ANE_PDF
)
1778 printf(" Par-Detect-Fault");
1779 if (t
& MII_ANE_LPNPA
)
1780 printf(" LP-Next-Page-Able");
1781 if (t
& MII_ANE_NPA
)
1782 printf(" Loc-Next-Page-Able");
1784 printf(" Page-Received");
1785 if (t
& MII_ANE_LPANA
)
1786 printf(" LP-Auto-Neg-Able");
1789 t
= rl_inw(port
, RL_NWAYTR
);
1790 printf("NWAYTR: 0x%04lx\n", t
);
1791 t
= rl_inw(port
, RL_CSCR
);
1792 printf("CSCR: 0x%04lx\n", t
);
1794 t
= rl_inb(port
, RL_CONFIG5
);
1795 printf("CONFIG5: 0x%02lx\n", t
);
1799 /*===========================================================================*
1801 *===========================================================================*/
1802 static void do_hard_int(void)
1806 /* Run interrupt handler at driver level. */
1807 rl_handler(&re_state
);
1809 /* Reenable interrupts for this hook. */
1810 if ((s
=sys_irqenable(&re_state
.re_hook_id
)) != OK
)
1811 printf("RTL8139: error, couldn't enable interrupts: %d\n", s
);
1814 /*===========================================================================*
1816 *===========================================================================*/
1817 static int rl_handler(re_t
*rep
)
1819 int i
, port
, tx_head
, tx_tail
, link_up
;
1821 u32_t tsd
, tcr
, ertxth
;
1826 int_event_check
= FALSE
; /* disable check by default */
1828 port
= rep
->re_base_port
;
1831 isr
= rl_inw(port
, RL_ISR
);
1832 rl_outw(port
, RL_ISR
, isr
);
1834 if (isr
& RL_IMR_FOVW
)
1836 isr
&= ~RL_IMR_FOVW
;
1837 /* Should do anything? */
1839 rep
->re_stat
.ets_fifoOver
++;
1841 if (isr
& RL_IMR_PUN
)
1845 /* Either the link status changed or there was a TX fifo
1848 link_up
= !(rl_inb(port
, RL_MSR
) & RL_MSR_LINKB
);
1849 if (link_up
!= rep
->re_link_up
)
1851 rep
->re_report_link
= TRUE
;
1852 rep
->re_got_int
= TRUE
;
1853 int_event_check
= TRUE
;
1856 if (isr
& RL_IMR_RXOVW
)
1858 isr
&= ~RL_IMR_RXOVW
;
1860 /* Clear the receive buffer */
1861 rep
->re_clear_rx
= TRUE
;
1862 rep
->re_got_int
= TRUE
;
1863 int_event_check
= TRUE
;
1866 if (isr
& (RL_ISR_RER
| RL_ISR_ROK
))
1868 isr
&= ~(RL_ISR_RER
| RL_ISR_ROK
);
1870 if (!rep
->re_got_int
&& (rep
->re_flags
& REF_READING
))
1872 rep
->re_got_int
= TRUE
;
1873 int_event_check
= TRUE
;
1877 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) &&
1878 (rep
->re_flags
& REF_SEND_AVAIL
) &&
1879 (rep
->re_tx
[0].ret_busy
|| rep
->re_tx
[1].ret_busy
||
1880 rep
->re_tx
[2].ret_busy
|| rep
->re_tx
[3].ret_busy
))
1884 "rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
1885 rep
->re_tx_head
, rep
->re_tx_tail
,
1886 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
1887 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
1889 "rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
1890 rl_inw(port
, RL_TSAD
),
1891 rl_inl(port
, RL_TSD0
+0*4),
1892 rl_inl(port
, RL_TSD0
+1*4),
1893 rl_inl(port
, RL_TSD0
+2*4),
1894 rl_inl(port
, RL_TSD0
+3*4));
1897 if ((isr
& (RL_ISR_TER
| RL_ISR_TOK
)) || 1)
1899 isr
&= ~(RL_ISR_TER
| RL_ISR_TOK
);
1901 tsad
= rl_inw(port
, RL_TSAD
);
1902 if (tsad
& (RL_TSAD_TABT0
|RL_TSAD_TABT1
|
1903 RL_TSAD_TABT2
|RL_TSAD_TABT3
))
1906 /* Do we need a watch dog? */
1907 /* Just reset the whole chip */
1908 rep
->re_need_reset
= TRUE
;
1909 rep
->re_got_int
= TRUE
;
1910 int_event_check
= TRUE
;
1912 /* Reset transmitter */
1913 rep
->re_stat
.ets_transAb
++;
1915 cr
= rl_inb(port
, RL_CR
);
1917 rl_outb(port
, RL_CR
, cr
);
1920 if (!(rl_inb(port
, RL_CR
) & RL_CR_TE
))
1922 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < system_hz
);
1923 if (rl_inb(port
, RL_CR
) & RL_CR_TE
) {
1924 panic("cannot disable transmitter");
1926 rl_outb(port
, RL_CR
, cr
| RL_CR_TE
);
1928 tcr
= rl_inl(port
, RL_TCR
);
1929 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_IFG_STD
);
1931 printf("rl_handler: reset after abort\n");
1933 if (rep
->re_flags
& REF_SEND_AVAIL
)
1935 printf("rl_handler: REF_SEND_AVAIL\n");
1936 rep
->re_send_int
= TRUE
;
1937 rep
->re_got_int
= TRUE
;
1938 int_event_check
= TRUE
;
1940 for (i
= 0; i
< N_TX_BUF
; i
++)
1941 rep
->re_tx
[i
].ret_busy
= FALSE
;
1944 printf("rl_handler, TABT, tasd = 0x%04x\n",
1947 /* Find the aborted transmit request */
1948 for (i
= 0; i
< N_TX_BUF
; i
++)
1950 tsd
= rl_inl(port
, RL_TSD0
+i
*4);
1951 if (tsd
& RL_TSD_TABT
)
1957 "rl_handler: can't find aborted TX req.\n");
1961 printf("TSD%d = 0x%04lx\n", i
, tsd
);
1963 /* Set head and tail to this buffer */
1964 rep
->re_tx_head
= rep
->re_tx_tail
= i
;
1967 /* Aborted transmission, just kick the device
1968 * and be done with it.
1970 rep
->re_stat
.ets_transAb
++;
1971 tcr
= rl_inl(port
, RL_TCR
);
1972 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
1976 /* Transmit completed */
1977 tx_head
= rep
->re_tx_head
;
1978 tx_tail
= rep
->re_tx_tail
;
1979 for (i
= 0; i
< 2*N_TX_BUF
; i
++)
1981 if (!rep
->re_tx
[tx_tail
].ret_busy
)
1983 /* Strange, this buffer is not in-use.
1984 * Increment tx_tail until tx_head is
1985 * reached (or until we find a buffer that
1988 if (tx_tail
== tx_head
)
1990 if (++tx_tail
>= N_TX_BUF
)
1992 assert(tx_tail
< RL_N_TX
);
1993 rep
->re_tx_tail
= tx_tail
;
1996 tsd
= rl_inl(port
, RL_TSD0
+tx_tail
*4);
1997 if (!(tsd
& RL_TSD_OWN
))
1999 /* Buffer is not yet ready */
2003 /* Should collect statistics */
2004 if (tsd
& RL_TSD_CRS
)
2005 rep
->re_stat
.ets_carrSense
++;
2006 if (tsd
& RL_TSD_TABT
)
2008 printf("rl_handler, TABT, TSD%d = 0x%04lx\n",
2010 assert(0); /* CLRABT is not all that
2011 * effective, why not?
2013 rep
->re_stat
.ets_transAb
++;
2014 tcr
= rl_inl(port
, RL_TCR
);
2015 rl_outl(port
, RL_TCR
, tcr
| RL_TCR_CLRABT
);
2017 if (tsd
& RL_TSD_OWC
)
2018 rep
->re_stat
.ets_OWC
++;
2019 if (tsd
& RL_TSD_CDH
)
2020 rep
->re_stat
.ets_CDheartbeat
++;
2022 /* What about collisions? */
2023 if (tsd
& RL_TSD_TOK
)
2024 rep
->re_stat
.ets_packetT
++;
2026 rep
->re_stat
.ets_sendErr
++;
2027 if (tsd
& RL_TSD_TUN
)
2029 rep
->re_stat
.ets_fifoUnder
++;
2031 /* Increase ERTXTH */
2032 ertxth
= tsd
+ (1 << RL_TSD_ERTXTH_S
);
2033 ertxth
&= RL_TSD_ERTXTH_M
;
2034 if (debug
&& ertxth
> rep
->re_ertxth
)
2036 printf("%s: new ertxth: %ld bytes\n",
2038 (ertxth
>> RL_TSD_ERTXTH_S
) *
2040 rep
->re_ertxth
= ertxth
;
2043 rep
->re_tx
[tx_tail
].ret_busy
= FALSE
;
2046 if (rep
->re_flags
& REF_SEND_AVAIL
)
2048 printf("TSD%d: %08lx\n", tx_tail
, tsd
);
2050 "rl_handler: head %d, tail %d, busy: %d %d %d %d\n",
2052 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2053 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2057 if (++tx_tail
>= N_TX_BUF
)
2059 assert(tx_tail
< RL_N_TX
);
2060 rep
->re_tx_tail
= tx_tail
;
2062 if (rep
->re_flags
& REF_SEND_AVAIL
)
2065 printf("rl_handler: REF_SEND_AVAIL\n");
2067 rep
->re_send_int
= TRUE
;
2068 if (!rep
->re_got_int
)
2070 rep
->re_got_int
= TRUE
;
2071 int_event_check
= TRUE
;
2075 assert(i
< 2*N_TX_BUF
);
2079 printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
2086 /*===========================================================================*
2088 *===========================================================================*/
2089 static void rl_watchdog_f(tp
)
2093 /* Use a synchronous alarm instead of a watchdog timer. */
2094 sys_setalarm(system_hz
, 0);
2098 if (rep
->re_mode
!= REM_ENABLED
)
2100 if (!(rep
->re_flags
& REF_SEND_AVAIL
))
2102 /* Assume that an idle system is alive */
2103 rep
->re_tx_alive
= TRUE
;
2106 if (rep
->re_tx_alive
)
2108 rep
->re_tx_alive
= FALSE
;
2111 printf("rl_watchdog_f: resetting instance %d\n", re_instance
);
2112 printf("TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
2113 rl_inw(rep
->re_base_port
, RL_TSAD
),
2114 rl_inl(rep
->re_base_port
, RL_TSD0
+0*4),
2115 rl_inl(rep
->re_base_port
, RL_TSD0
+1*4),
2116 rl_inl(rep
->re_base_port
, RL_TSD0
+2*4),
2117 rl_inl(rep
->re_base_port
, RL_TSD0
+3*4));
2118 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
2119 rep
->re_tx_head
, rep
->re_tx_tail
,
2120 rep
->re_tx
[0].ret_busy
, rep
->re_tx
[1].ret_busy
,
2121 rep
->re_tx
[2].ret_busy
, rep
->re_tx
[3].ret_busy
);
2122 rep
->re_need_reset
= TRUE
;
2123 rep
->re_got_int
= TRUE
;
2130 _PROTOTYPE( static void rtl_init
, (struct dpeth
*dep
) );
2131 _PROTOTYPE( static u16_t get_ee_word
, (dpeth_t
*dep
, int a
) );
2132 _PROTOTYPE( static void ee_wen
, (dpeth_t
*dep
) );
2133 _PROTOTYPE( static void set_ee_word
, (dpeth_t
*dep
, int a
, u16_t w
) );
2134 _PROTOTYPE( static void ee_wds
, (dpeth_t
*dep
) );
2136 static void rtl_init(dep
)
2139 u8_t reg_a
, reg_b
, cr
, config0
, config2
, config3
;
2143 printf("rtl_init called\n");
2147 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2148 reg_a
= inb_reg0(dep
, DP_DUM1
);
2149 reg_b
= inb_reg0(dep
, DP_DUM2
);
2151 printf("rtl_init: '%c', '%c'\n", reg_a
, reg_b
);
2153 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2154 config0
= inb_reg3(dep
, 3);
2155 config2
= inb_reg3(dep
, 5);
2156 config3
= inb_reg3(dep
, 6);
2157 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2159 printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
2160 config0
, config2
, config3
);
2162 if (0 == sys_getkenv("RTL8029FD",9+1, val
, sizeof(val
)))
2164 printf("rtl_init: setting full-duplex mode\n");
2165 outb_reg0(dep
, DP_CR
, CR_PS_P3
);
2167 cr
= inb_reg3(dep
, 1);
2168 outb_reg3(dep
, 1, cr
| 0xc0);
2170 outb_reg3(dep
, 6, config3
| 0x40);
2171 config3
= inb_reg3(dep
, 6);
2173 config2
= inb_reg3(dep
, 5);
2174 outb_reg3(dep
, 5, config2
| 0x20);
2175 config2
= inb_reg3(dep
, 5);
2177 outb_reg3(dep
, 1, cr
);
2179 outb_reg0(dep
, DP_CR
, CR_PS_P0
);
2181 printf("rtl_init: config 2 = %x\n", config2
);
2182 printf("rtl_init: config 3 = %x\n", config3
);
2185 for (i
= 0; i
<64; i
++)
2186 printf("%x ", get_ee_word(dep
, i
));
2189 if (0 == sys_getkenv("RTL8029MN",9+1, val
, sizeof(val
)))
2193 set_ee_word(dep
, 0x78/2, 0x10ec);
2194 set_ee_word(dep
, 0x7A/2, 0x8029);
2195 set_ee_word(dep
, 0x7C/2, 0x10ec);
2196 set_ee_word(dep
, 0x7E/2, 0x8029);
2200 assert(get_ee_word(dep
, 0x78/2) == 0x10ec);
2201 assert(get_ee_word(dep
, 0x7A/2) == 0x8029);
2202 assert(get_ee_word(dep
, 0x7C/2) == 0x10ec);
2203 assert(get_ee_word(dep
, 0x7E/2) == 0x8029);
2206 if (0 == sys_getkenv("RTL8029XXX",10+1, val
, sizeof(val
)))
2210 set_ee_word(dep
, 0x76/2, 0x8029);
2214 assert(get_ee_word(dep
, 0x76/2) == 0x8029);
2218 static u16_t
get_ee_word(dep
, a
)
2225 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2227 /* Switch to 9346 mode and enable CS */
2228 outb_reg3(dep
, 1, 0x80 | 0x8);
2230 cmd
= 0x180 | (a
& 0x3f); /* 1 1 0 a5 a4 a3 a2 a1 a0 */
2231 for (i
= 8; i
>= 0; i
--)
2233 b
= (cmd
& (1 << i
));
2236 /* Cmd goes out on the rising edge of the clock */
2237 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2238 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2240 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2243 for (i
= 0; i
<16; i
++)
2247 /* Data is shifted out on the rising edge. Read at the
2250 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4);
2251 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2252 b
= inb_reg3(dep
, 1);
2256 outb_reg3(dep
, 1, 0x80); /* drop CS */
2257 outb_reg3(dep
, 1, 0x00); /* back to normal */
2258 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
2263 static void ee_wen(dep
)
2269 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2271 /* Switch to 9346 mode and enable CS */
2272 outb_reg3(dep
, 1, 0x80 | 0x8);
2274 cmd
= 0x130; /* 1 0 0 1 1 x x x x */
2275 for (i
= 8; i
>= 0; i
--)
2277 b
= (cmd
& (1 << i
));
2280 /* Cmd goes out on the rising edge of the clock */
2281 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2282 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2284 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2285 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2286 /* micro_delay(1); */ /* Is this required? */
2289 static void set_ee_word(dpeth_t
*dep
, int a
, u16_t w
)
2297 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
2299 cmd
= 0x140 | (a
& 0x3f); /* 1 0 1 a5 a4 a3 a2 a1 a0 */
2300 for (i
= 8; i
>= 0; i
--)
2302 b
= (cmd
& (1 << i
));
2305 /* Cmd goes out on the rising edge of the clock */
2306 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2307 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2309 for (i
= 15; i
>= 0; i
--)
2314 /* Cmd goes out on the rising edge of the clock */
2315 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2316 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2318 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of data */
2319 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2320 /* micro_delay(1); */ /* Is this required? */
2321 outb_reg3(dep
, 1, 0x80 | 0x8); /* Set CS */
2324 if (inb_reg3(dep
, 1) & 1)
2326 } while (getuptime(&t1
) == OK
&& (t1
== t0
));
2327 if (!(inb_reg3(dep
, 1) & 1))
2328 panic("device remains busy");
2331 static void ee_wds(dep
)
2337 outb_reg0(dep
, DP_CR
, CR_PS_P3
); /* Bank 3 */
2339 /* Switch to 9346 mode and enable CS */
2340 outb_reg3(dep
, 1, 0x80 | 0x8);
2342 cmd
= 0x100; /* 1 0 0 0 0 x x x x */
2343 for (i
= 8; i
>= 0; i
--)
2345 b
= (cmd
& (1 << i
));
2348 /* Cmd goes out on the rising edge of the clock */
2349 outb_reg3(dep
, 1, 0x80 | 0x8 | b
);
2350 outb_reg3(dep
, 1, 0x80 | 0x8 | 0x4 | b
);
2352 outb_reg3(dep
, 1, 0x80 | 0x8); /* End of cmd */
2353 outb_reg3(dep
, 1, 0x80); /* Drop CS */
2354 outb_reg3(dep
, 1, 0x00); /* back to normal */
2355 outb_reg0(dep
, DP_CR
, CR_PS_P0
); /* back to bank 0 */
2359 PRIVATE
void tell_dev(buf
, size
, pci_bus
, pci_dev
, pci_func
)
2370 r
= ds_retrieve_label_endpt("amddev", &dev_e
);
2375 "rtl8139`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n",
2381 m
.m_type
= IOMMU_MAP
;
2388 r
= sendrec(dev_e
, &m
);
2391 printf("rtl8139`tell_dev: sendrec to %d failed: %d\n",
2397 printf("rtl8139`tell_dev: dma map request failed: %d\n",
2404 * $PchId: rtl8139.c,v 1.3 2003/09/11 14:15:15 philip Exp $