3.1.7 branch.
[minix.git] / drivers / rtl8139 / rtl8139.c
blob3ba0c411f163ea7a12b1af263ae82ce38cbfc591
1 /*
2 * rtl8139.c
4 * This file contains a ethernet device driver for Realtek rtl8139 based
5 * ethernet cards.
7 * Created: Aug 2003 by Philip Homburg <philip@cs.vu.nl>
8 * Changes:
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 */
17 #include "rtl8139.h"
19 PRIVATE struct pcitab
21 u16_t vid;
22 u16_t did;
23 int checkclass;
24 } pcitab[]=
26 { 0x10ec, 0x8139, 0 }, /* Realtek RTL8139 */
28 /* Alternative IDs */
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 */
46 { 0x0000, 0x0000, 0 }
49 PUBLIC re_t re_state;
51 static int re_instance;
53 static tmra_ut rl_watchdog;
55 static unsigned my_inb(u16_t port) {
56 u32_t value;
57 int s;
58 if ((s=sys_inb(port, &value)) !=OK)
59 printf("RTL8139: warning, sys_inb failed: %d\n", s);
60 return value;
62 static unsigned my_inw(u16_t port) {
63 u32_t value;
64 int s;
65 if ((s=sys_inw(port, &value)) !=OK)
66 printf("RTL8139: warning, sys_inw failed: %d\n", s);
67 return value;
69 static unsigned my_inl(u16_t port) {
70 u32_t value;
71 int s;
72 if ((s=sys_inl(port, &value)) !=OK)
73 printf("RTL8139: warning, sys_inl failed: %d\n", s);
74 return value;
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) {
81 int s;
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) {
86 int s;
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) {
91 int s;
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,
114 u16_t extstat) );
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) );
123 #if 0
124 _PROTOTYPE( static void dump_phy, (re_t *rep) );
125 #endif
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.
134 PRIVATE message m;
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) );
146 EXTERN int env_argc;
147 EXTERN char **env_argv;
149 /*===========================================================================*
150 * main *
151 *===========================================================================*/
152 int main(int argc, char *argv[])
154 int r;
155 int ipc_status;
157 /* SEF local startup. */
158 env_setargs(argc, argv);
159 sef_local_startup();
161 while (TRUE)
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)) {
168 case CLOCK:
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
180 * are used again.
182 rl_watchdog_f(NULL);
183 break;
184 case HARDWARE:
185 do_hard_int();
186 if (int_event_check)
187 check_int_events();
188 break ;
189 case TTY_PROC_NR:
190 rtl8139_dump(&m);
191 break;
192 default:
193 panic("illegal notify from: %d",
194 m.m_source);
197 /* done, get nwe message */
198 continue;
201 switch (m.m_type)
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;
207 default:
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. */
232 sef_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. */
241 long v;
242 #if RTL8139_FKEY
243 int r, fkeys, sfkeys;
244 #endif
246 system_hz = sys_hz();
248 v = 0;
249 (void) env_parse("instance", "d", 0, &v, 0, 255);
250 re_instance = (int) v;
252 #if RTL8139_FKEY
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);
257 #endif
259 /* Claim buffer memory now. */
260 rl_init_buf(&re_state);
262 /* Announce we are up! */
263 netdriver_announce();
265 return(OK);
268 /*===========================================================================*
269 * sef_cb_signal_handler *
270 *===========================================================================*/
271 PRIVATE void sef_cb_signal_handler(int signo)
273 re_t *rep;
275 /* Only check for termination signal, ignore anything else. */
276 if (signo != SIGTERM) return;
278 rep = &re_state;
279 if (rep->re_mode == REM_ENABLED)
280 rl_outb(rep->re_base_port, RL_CR, 0);
282 exit(0);
285 /*===========================================================================*
286 * check_int_events *
287 *===========================================================================*/
288 static void check_int_events(void)
290 re_t *rep;
292 rep= &re_state;
294 if (rep->re_mode != REM_ENABLED)
295 return;
296 if (!rep->re_got_int)
297 return;
298 rep->re_got_int= 0;
299 assert(rep->re_flags & REF_ENABLED);
300 rl_check_ints(rep);
303 /*===========================================================================*
304 * rtl8139_dump *
305 *===========================================================================*/
306 static void rtl8139_dump(m)
307 message *m; /* pointer to request message */
309 re_t *rep;
311 rep= &re_state;
313 printf("\n");
314 if (rep->re_mode == REM_DISABLED)
315 printf("Realtek RTL 8139 instance %d is disabled\n",
316 re_instance);
318 if (rep->re_mode != REM_ENABLED)
319 return;
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 /*===========================================================================*
360 * rl_init *
361 *===========================================================================*/
362 static void rl_init(mp)
363 message *mp;
365 static int first_time= 1;
367 re_t *rep;
368 message reply_mess;
370 if (first_time)
372 first_time= 0;
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);
380 rep= &re_state;
381 if (rep->re_mode == REM_DISABLED)
383 /* This is the default, try to (re)locate the device. */
384 rl_conf_hw(rep);
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);
391 return;
393 if (rep->re_mode == REM_ENABLED)
394 rl_init_hw(rep);
395 #if VERBOSE /* load silently ... can always check status later */
396 rl_report_link(rep);
397 #endif
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;
412 rl_rec_mode(rep);
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 /*===========================================================================*
422 * rl_pci_conf *
423 *===========================================================================*/
424 static void rl_pci_conf()
426 re_t *rep;
427 static char envvar[] = RL_ENVVAR "#";
428 static char envfmt[] = "*:d.d.d";
429 static char val[128];
430 long v;
432 rep= &re_state;
434 strcpy(rep->re_name, "rtl8139#0");
435 rep->re_name[8] += re_instance;
436 rep->re_seen= FALSE;
437 envvar[sizeof(RL_ENVVAR)-1]= '0'+re_instance;
438 if (0 == env_get_param(envvar, val, sizeof(val)) &&
439 ! env_prefix(envvar, "pci")) {
440 env_panic(envvar);
442 v= 0;
443 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
444 rep->re_pcibus= v;
445 v= 0;
446 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
447 rep->re_pcidev= v;
448 v= 0;
449 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
450 rep->re_pcifunc= v;
452 pci_init();
454 if (rl_probe(rep, re_instance))
455 rep->re_seen= TRUE;
458 /*===========================================================================*
459 * rl_probe *
460 *===========================================================================*/
461 static int rl_probe(rep, skip)
462 re_t *rep;
463 int skip;
465 int i, r, devind, just_one;
466 u16_t vid, did;
467 u32_t bar;
468 u8_t ilr;
469 char *dname;
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);
476 if (r == 0)
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);
481 return 0;
483 pci_ids(devind, &vid, &did);
484 just_one= TRUE;
486 else
488 r= pci_first_dev(&devind, &vid, &did);
489 if (r == 0)
490 return 0;
491 just_one= FALSE;
494 for(;;)
496 for (i= 0; pcitab[i].vid != 0; i++)
498 if (pcitab[i].vid != vid)
499 continue;
500 if (pcitab[i].did != did)
501 continue;
502 if (pcitab[i].checkclass) {
503 panic("class check not implemented");
505 break;
507 if (pcitab[i].vid != 0)
509 if (just_one || !skip)
510 break;
511 skip--;
514 if (just_one)
516 printf(
517 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
518 rep->re_name, vid, did,
519 rep->re_pcibus,
520 rep->re_pcidev, rep->re_pcifunc);
521 return 0;
524 r= pci_next_dev(&devind, &vid, &did);
525 if (!r)
526 return 0;
529 #if VERBOSE /* stay silent at startup, can always get status later */
530 dname= pci_dev_name(vid, did);
531 if (!dname)
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));
535 #endif
536 pci_reserve(devind);
537 /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
538 bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
539 if (bar < 0x400) {
540 panic("base address is not properly configured");
542 rep->re_base_port= bar;
544 ilr= pci_attr_r8(devind, PCI_ILR);
545 rep->re_irq= ilr;
546 if (debug)
548 printf("%s: using I/O address 0x%lx, IRQ %d\n",
549 rep->re_name, (unsigned long)bar, ilr);
552 return TRUE;
555 /*===========================================================================*
556 * rl_conf_hw *
557 *===========================================================================*/
558 static void rl_conf_hw(rep)
559 re_t *rep;
561 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
563 rep->re_mode= REM_DISABLED; /* Superfluous */
565 if (rep->re_seen)
567 /* PCI device is present */
568 rep->re_mode= REM_ENABLED;
570 if (rep->re_mode != REM_ENABLED)
571 return;
573 rep->re_flags= REF_EMPTY;
574 rep->re_link_up= -1; /* Unknown */
575 rep->re_got_int= 0;
576 rep->re_send_int= 0;
577 rep->re_report_link= 0;
578 rep->re_clear_rx= 0;
579 rep->re_need_reset= 0;
580 rep->re_tx_alive= 0;
581 rep->re_read_s= 0;
582 rep->re_tx_head= 0;
583 rep->re_tx_tail= 0;
584 rep->re_ertxth= RL_TSD_ERTXTH_8;
585 rep->re_stat= empty_stat;
588 /*===========================================================================*
589 * rl_init_buf *
590 *===========================================================================*/
591 static void rl_init_buf(rep)
592 re_t *rep;
594 size_t rx_bufsize, tx_bufsize, tot_bufsize;
595 phys_bytes buf;
596 char *mallocbuf;
597 int i, off;
599 /* Allocate receive and transmit buffers */
600 tx_bufsize= ETH_MAX_PACK_SIZE_TAGGED;
601 if (tx_bufsize % 4)
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;
630 buf += tx_bufsize;
631 mallocbuf += tx_bufsize;
633 rep->re_rx_buf= buf;
634 rep->v_re_rx_buf= mallocbuf;
637 /*===========================================================================*
638 * rl_init_hw *
639 *===========================================================================*/
640 static void rl_init_hw(rep)
641 re_t *rep;
643 int s, i;
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);
656 rl_reset_hw(rep);
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 */
662 if (rep->re_model) {
663 printf("%s: model %s\n", rep->re_name, rep->re_model);
664 } else
666 printf("%s: unknown model 0x%08x\n",
667 rep->re_name,
668 rl_inl(rep->re_base_port, RL_TCR) &
669 (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
671 #endif
673 rl_confaddr(rep);
674 if (debug)
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],
680 i < 5 ? ':' : '\n');
685 /*===========================================================================*
686 * rl_reset_hw *
687 *===========================================================================*/
688 static void rl_reset_hw(rep)
689 re_t *rep;
691 port_t port;
692 u32_t t;
693 phys_bytes bus_buf;
694 int i;
695 clock_t t0,t1;
697 port= rep->re_base_port;
699 #if 0
700 /* Reset the PHY */
701 rl_outb(port, RL_BMCR, MII_CTRL_RST);
702 getuptime(&t0);
703 do {
704 if (!(rl_inb(port, RL_BMCR) & MII_CTRL_RST))
705 break;
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");
709 #endif
711 /* Reset the device */
712 #if VERBOSE
713 printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
714 port, rl_inb(port, RL_CR));
715 #endif
716 rl_outb(port, RL_CR, RL_CR_RST);
717 getuptime(&t0);
718 do {
719 if (!(rl_inb(port, RL_CR) & RL_CR_RST))
720 break;
721 } while (getuptime(&t1)==OK && (t1-t0) < system_hz);
722 #if VERBOSE
723 printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
724 port, rl_inb(port, RL_CR));
725 #endif
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";
736 break;
737 case RL_TCR_HWVER_RTL8139B:
738 rep->re_model= "RTL8139B / RTL8130";
739 break;
740 case RL_TCR_HWVER_RTL8100: rep->re_model= "RTL8100"; break;
741 case RL_TCR_HWVER_RTL8100B:
742 rep->re_model= "RTL8100B/RTL8139D";
743 break;
744 case RL_TCR_HWVER_RTL8139CP: rep->re_model= "RTL8139C+"; break;
745 case RL_TCR_HWVER_RTL8101: rep->re_model= "RTL8101"; break;
746 default:
747 rep->re_model= NULL;
748 break;
751 #if 0
752 printf("REVID: 0x%02x\n", rl_inb(port, RL_REVID));
753 #endif
755 /* Intialize Rx */
757 /* Should init multicast mask */
758 #if 0
759 08-0f R/W MAR[0-7] multicast
760 #endif
761 bus_buf= vm_1phys2bus(rep->re_rx_buf);
762 rl_outl(port, RL_RBSTART, bus_buf);
764 /* Initialize Tx */
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);
774 #if 0
775 dump_phy(rep);
776 #endif
778 t= rl_inw(port, RL_IMR);
779 rl_outw(port, RL_IMR, t | (RL_IMR_SERR | RL_IMR_TIMEOUT |
780 RL_IMR_LENCHG));
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 /*===========================================================================*
802 * rl_confaddr *
803 *===========================================================================*/
804 static void rl_confaddr(rep)
805 re_t *rep;
807 static char eakey[]= RL_ENVVAR "#_EA";
808 static char eafmt[]= "x:x:x:x:x:x";
810 int i;
811 port_t port;
812 u32_t w;
813 long v;
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)
823 break;
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 */
830 if (i == 6)
832 port= rep->re_base_port;
833 rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
834 w= 0;
835 for (i= 0; i<4; i++)
836 w |= (rep->re_address.ea_addr[i] << (i*8));
837 rl_outl(port, RL_IDR, w);
838 w= 0;
839 for (i= 4; i<6; i++)
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 */
846 for (i= 0; i<6; i++)
847 rep->re_address.ea_addr[i]= rl_inb(port, RL_IDR+i);
850 /*===========================================================================*
851 * rl_rec_mode *
852 *===========================================================================*/
853 static void rl_rec_mode(rep)
854 re_t *rep;
856 port_t port;
857 u32_t rcr;
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)
865 rcr |= RL_RCR_AB;
866 if (rep->re_flags & REF_MULTI)
867 rcr |= RL_RCR_AM;
868 rcr |= RL_RCR_APM;
870 rl_outl(port, RL_RCR, rcr);
873 /*===========================================================================*
874 * rl_readv_s *
875 *===========================================================================*/
876 static void rl_readv_s(const message *mp, int from_int)
878 int i, j, n, o, s, s1, count, size;
879 port_t port;
880 unsigned amount, totlen, packlen;
881 phys_bytes dst_phys;
882 u16_t d_start, d_end;
883 u32_t l, rxstat = 0x12345678;
884 re_t *rep;
885 iovec_s_t *iovp;
886 int cps;
887 int iov_offset = 0;
889 rep= &re_state;
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 */
907 goto 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;
920 if (d_end > d_start)
921 amount= d_end-d_start;
922 else
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)
929 #if 0
930 printf("rl_readv: late buffer overflow\n");
931 #endif
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 */
948 printf(
949 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
950 totlen, rxstat, d_start);
951 printf(
952 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
953 d_start, d_end, totlen, rxstat);
954 panic(NULL);
957 #if 0
958 printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
959 d_start, d_end, totlen, rxstat);
960 #endif
962 if (totlen+4 > amount)
964 printf("rl_readv: packet not yet ready\n");
965 goto suspend;
968 /* Should subtract the CRC */
969 packlen= totlen - ETH_CRC_SIZE;
971 size= 0;
972 o= d_start+4;
973 for (i= 0; i<count; i += IOVEC_NR,
974 iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
976 n= IOVEC_NR;
977 if (i+n > count)
978 n= count-i;
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);
983 if (cps != OK) {
984 panic("rl_readv_s: sys_safecopyfrom failed: %d",
985 cps);
988 for (j= 0, iovp= rep->re_iovec_s; j<n; j++, iovp++)
990 s= iovp->iov_size;
991 if (size + s > packlen)
993 assert(packlen > size);
994 s= packlen-size;
997 #if 0
998 if (sys_umap(mp->DL_ENDPT, D, iovp->iov_addr, s, &dst_phys) != OK)
999 panic("umap_local failed");
1000 #endif
1002 if (o >= RX_BUFSIZE)
1004 o -= RX_BUFSIZE;
1005 assert(o < RX_BUFSIZE);
1008 if (o+s > RX_BUFSIZE)
1010 assert(o<RX_BUFSIZE);
1011 s1= RX_BUFSIZE-o;
1013 cps = sys_safecopyto(mp->DL_ENDPT,
1014 iovp->iov_grant, 0,
1015 (vir_bytes) rep->v_re_rx_buf+o, s1, D);
1016 if (cps != OK) {
1017 panic("rl_readv_s: sys_safecopyto failed: %d",
1018 cps);
1020 cps = sys_safecopyto(mp->DL_ENDPT,
1021 iovp->iov_grant, s1,
1022 (vir_bytes) rep->v_re_rx_buf, s-s1, S);
1023 if (cps != OK) {
1024 panic("rl_readv_s: sys_safecopyto failed: %d", cps);
1027 else
1029 cps = sys_safecopyto(mp->DL_ENDPT,
1030 iovp->iov_grant, 0,
1031 (vir_bytes) rep->v_re_rx_buf+o, s, D);
1032 if (cps != OK)
1033 panic("rl_readv_s: sys_safecopyto failed: %d", cps);
1036 size += s;
1037 if (size == packlen)
1038 break;
1039 o += s;
1041 if (size == packlen)
1042 break;
1044 if (size < packlen)
1046 assert(0);
1049 if (rep->re_clear_rx)
1051 /* For some reason the receiver FIFO is not stopped when
1052 * the buffer is full.
1054 #if 0
1055 printf("rl_readv: later buffer overflow\n");
1056 #endif
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 */
1065 l= d_start;
1066 l += totlen+4;
1067 l= (l+3) & ~3; /* align */
1068 if (l >= RX_BUFSIZE)
1070 l -= RX_BUFSIZE;
1071 assert(l < RX_BUFSIZE);
1073 rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF);
1075 if (!from_int)
1076 reply(rep);
1078 return;
1080 suspend:
1081 if (from_int)
1083 assert(rep->re_flags & REF_READING);
1085 /* No need to store any state */
1086 return;
1089 rep->re_rx_mess= *mp;
1090 assert(!(rep->re_flags & REF_READING));
1091 rep->re_flags |= REF_READING;
1093 reply(rep);
1096 /*===========================================================================*
1097 * rl_writev_s *
1098 *===========================================================================*/
1099 static void rl_writev_s(const message *mp, int from_int)
1101 int i, j, n, s, count, size;
1102 int tx_head;
1103 re_t *rep;
1104 iovec_s_t *iovp;
1105 char *ret;
1106 int cps;
1107 int iov_offset = 0;
1109 rep= &re_state;
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);
1117 if (from_int)
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;
1130 goto suspend;
1133 assert(!(rep->re_flags & REF_SEND_AVAIL));
1134 assert(!(rep->re_flags & REF_PACK_SENT));
1136 size= 0;
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]))
1141 n= IOVEC_NR;
1142 if (i+n > count)
1143 n= count-i;
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);
1147 if (cps != OK) {
1148 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps);
1151 for (j= 0, iovp= rep->re_iovec_s; j<n; j++, iovp++)
1153 s= iovp->iov_size;
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);
1159 if (cps != OK) {
1160 panic("rl_writev_s: sys_safecopyfrom failed: %d", cps);
1162 size += s;
1163 ret += s;
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)
1174 tx_head= 0;
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.
1183 if (from_int)
1184 return;
1185 reply(rep);
1186 return;
1188 suspend:
1189 #if 0
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));
1199 #endif
1201 if (from_int)
1202 panic("should not be sending");
1204 rep->re_tx_mess= *mp;
1205 reply(rep);
1208 /*===========================================================================*
1209 * rl_check_ints *
1210 *===========================================================================*/
1211 static void rl_check_ints(rep)
1212 re_t *rep;
1214 #if 0
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
1220 23-22 reserved
1221 21-16 R/W ERTXH[5-0] Early Tx Threshold
1222 15 R TOK Transmit OK
1223 14 R TUN Transmit FIFO Underrun
1224 13 R/W OWN OWN
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
1251 #endif
1253 int re_flags;
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)
1263 rl_clear_rx(rep);
1265 if (rep->re_need_reset)
1266 rl_do_reset(rep);
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))
1277 reply(rep);
1280 /*===========================================================================*
1281 * rl_report_link *
1282 *===========================================================================*/
1283 static void rl_report_link(rep)
1284 re_t *rep;
1286 port_t port;
1287 u16_t mii_ctrl, mii_status, mii_ana, mii_anlpa, mii_ane, mii_extstat;
1288 u8_t msr;
1289 int f, link_up;
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;
1296 if (!link_up)
1298 printf("%s: link down\n", rep->re_name);
1299 return;
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);
1307 mii_extstat= 0;
1309 if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
1311 printf("%s: PHY: ", rep->re_name);
1312 f= 1;
1313 if (mii_ctrl & MII_CTRL_LB)
1315 printf("loopback mode");
1316 f= 0;
1318 if (mii_ctrl & MII_CTRL_PD)
1320 if (!f) printf(", ");
1321 f= 0;
1322 printf("powered down");
1324 if (mii_ctrl & MII_CTRL_ISO)
1326 if (!f) printf(", ");
1327 f= 0;
1328 printf("isolated");
1330 printf("\n");
1331 return;
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");
1345 else
1346 printf(", half duplex");
1347 printf("\n");
1348 return;
1351 if (!debug) goto resspeed;
1353 printf("%s: ", rep->re_name);
1354 mii_print_stat_speed(mii_status, mii_extstat);
1355 printf("\n");
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",
1364 rep->re_name);
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);
1373 goto resspeed;
1375 if (!(mii_status & MII_STATUS_ANC))
1376 goto resspeed;
1378 printf("%s: local cap.: ", rep->re_name);
1379 mii_print_techab(mii_ana);
1380 printf("\n");
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",
1387 rep->re_name);
1388 goto resspeed;
1391 printf("%s: remote cap.: ", rep->re_name);
1392 mii_print_techab(mii_anlpa);
1393 printf("\n");
1395 resspeed:
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)
1404 int fs, ft;
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);
1410 return;
1412 fs= 1;
1413 if (techab & (MII_ANA_100T4 | MII_ANA_100TXFD | MII_ANA_100TXHD))
1415 printf("100 Mbps: ");
1416 fs= 0;
1417 ft= 1;
1418 if (techab & MII_ANA_100T4)
1420 printf("T4");
1421 ft= 0;
1423 if (techab & (MII_ANA_100TXFD | MII_ANA_100TXHD))
1425 if (!ft)
1426 printf(", ");
1427 ft= 0;
1428 printf("TX-");
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))
1439 if (!fs)
1440 printf(", ");
1441 printf("10 Mbps: ");
1442 fs= 0;
1443 printf("T-");
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)
1453 if (!fs)
1454 printf(", ");
1455 fs= 0;
1456 printf("pause(SYM)");
1458 if (techab & MII_ANA_PAUSE_ASYM)
1460 if (!fs)
1461 printf(", ");
1462 fs= 0;
1463 printf("pause(ASYM)");
1465 if (techab & MII_ANA_TAF_RES)
1467 if (!fs)
1468 printf(", ");
1469 fs= 0;
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)
1476 int fs, ft;
1477 fs= 1;
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: ");
1484 fs= 0;
1485 ft= 1;
1486 if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD))
1488 ft= 0;
1489 printf("X-");
1490 switch(extstat &
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))
1500 if (!ft)
1501 printf(", ");
1502 ft= 0;
1503 printf("T-");
1504 switch(extstat &
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))
1518 if (!fs)
1519 printf(", ");
1520 fs= 0;
1521 printf("100 Mbps: ");
1522 ft= 1;
1523 if (stat & MII_STATUS_100T4)
1525 printf("T4");
1526 ft= 0;
1528 if (stat & (MII_STATUS_100XFD | MII_STATUS_100XHD))
1530 if (!ft)
1531 printf(", ");
1532 ft= 0;
1533 printf("TX-");
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))
1543 if (!ft)
1544 printf(", ");
1545 ft= 0;
1546 printf("T2-");
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))
1557 if (!fs)
1558 printf(", ");
1559 printf("10 Mbps: ");
1560 fs= 0;
1561 printf("T-");
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 /*===========================================================================*
1572 * rl_clear_rx *
1573 *===========================================================================*/
1574 static void rl_clear_rx(re_t *rep)
1576 port_t port;
1577 u8_t cr;
1578 clock_t t0,t1;
1580 rep->re_clear_rx= FALSE;
1581 port= rep->re_base_port;
1583 /* Reset the receiver */
1584 cr= rl_inb(port, RL_CR);
1585 cr &= ~RL_CR_RE;
1586 rl_outb(port, RL_CR, cr);
1587 getuptime(&t0);
1588 do {
1589 if (!(rl_inb(port, RL_CR) & RL_CR_RE))
1590 break;
1591 } while (getuptime(&t1)==OK && (t1-t0) < system_hz);
1592 if (rl_inb(port, RL_CR) & RL_CR_RE)
1593 panic("cannot disable receiver");
1595 #if 0
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));
1600 #endif
1602 rl_outb(port, RL_CR, cr | RL_CR_RE);
1604 rl_outl(port, RL_RCR, RX_BUFBITS);
1606 rl_rec_mode(rep);
1608 rep->re_stat.ets_missedP++;
1611 /*===========================================================================*
1612 * rl_do_reset *
1613 *===========================================================================*/
1614 static void rl_do_reset(rep)
1615 re_t *rep;
1617 rep->re_need_reset= FALSE;
1618 rl_reset_hw(rep);
1619 rl_rec_mode(rep);
1621 rep->re_tx_head= 0;
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 /*===========================================================================*
1630 * rl_getstat_s *
1631 *===========================================================================*/
1632 static void rl_getstat_s(mp)
1633 message *mp;
1635 int r;
1636 eth_stat_t stats;
1637 re_t *rep;
1639 rep= &re_state;
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);
1648 if (r != OK)
1649 panic("rl_getstat_s: sys_safecopyto failed: %d", r);
1651 mp->m_type= DL_STAT_REPLY;
1652 r= send(mp->m_source, mp);
1653 if (r != OK)
1654 panic("rl_getstat_s: send failed: %d", r);
1657 /*===========================================================================*
1658 * reply *
1659 *===========================================================================*/
1660 static void reply(rep)
1661 re_t *rep;
1663 message reply;
1664 int flags;
1665 int r;
1667 flags = DL_NOFLAGS;
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);
1679 if (r < 0) {
1680 printf("RTL8139 tried sending to %d, type %d\n",
1681 rep->re_client, reply.m_type);
1682 panic("send failed: %d", r);
1685 rep->re_read_s = 0;
1686 rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
1689 /*===========================================================================*
1690 * mess_reply *
1691 *===========================================================================*/
1692 static void mess_reply(req, reply_mess)
1693 message *req;
1694 message *reply_mess;
1696 if (send(req->m_source, reply_mess) != OK)
1697 panic("unable to mess_reply");
1700 #if 0
1701 /*===========================================================================*
1702 * dump_phy *
1703 *===========================================================================*/
1704 static void dump_phy(rep)
1705 re_t *rep;
1707 port_t port;
1708 u32_t t;
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);
1732 printf("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)
1752 printf(" MFPS");
1753 if (t & MII_STATUS_ANC)
1754 printf(" ANC");
1755 if (t & MII_STATUS_RF)
1756 printf(" remote-fault");
1757 if (t & MII_STATUS_ANA)
1758 printf(" ANA");
1759 if (t & MII_STATUS_LS)
1760 printf(" Link");
1761 if (t & MII_STATUS_JD)
1762 printf(" Jabber");
1763 if (t & MII_STATUS_EC)
1764 printf(" Extended-capability");
1765 printf("\n");
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");
1783 if (t & MII_ANE_PR)
1784 printf(" Page-Received");
1785 if (t & MII_ANE_LPANA)
1786 printf(" LP-Auto-Neg-Able");
1787 printf("\n");
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);
1797 #endif
1799 /*===========================================================================*
1800 * do_hard_int *
1801 *===========================================================================*/
1802 static void do_hard_int(void)
1804 int s;
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 /*===========================================================================*
1815 * rl_handler *
1816 *===========================================================================*/
1817 static int rl_handler(re_t *rep)
1819 int i, port, tx_head, tx_tail, link_up;
1820 u16_t isr, tsad;
1821 u32_t tsd, tcr, ertxth;
1822 #if 0
1823 u8_t cr;
1824 #endif
1825 clock_t t0,t1;
1826 int_event_check = FALSE; /* disable check by default */
1828 port= rep->re_base_port;
1830 /* Ack interrupt */
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)
1843 isr &= ~RL_IMR_PUN;
1845 /* Either the link status changed or there was a TX fifo
1846 * underrun.
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;
1876 #if 0
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))
1883 printf(
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);
1888 printf(
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));
1896 #endif
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))
1905 #if 0
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;
1911 #elif 0
1912 /* Reset transmitter */
1913 rep->re_stat.ets_transAb++;
1915 cr= rl_inb(port, RL_CR);
1916 cr &= ~RL_CR_TE;
1917 rl_outb(port, RL_CR, cr);
1918 getuptime(&t0);
1919 do {
1920 if (!(rl_inb(port, RL_CR) & RL_CR_TE))
1921 break;
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;
1942 rep->re_tx_head= 0;
1943 #else
1944 printf("rl_handler, TABT, tasd = 0x%04x\n",
1945 tsad);
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)
1952 break;
1954 if (i >= N_TX_BUF)
1956 printf(
1957 "rl_handler: can't find aborted TX req.\n");
1959 else
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);
1973 #endif
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
1986 * is in-use.
1988 if (tx_tail == tx_head)
1989 break;
1990 if (++tx_tail >= N_TX_BUF)
1991 tx_tail= 0;
1992 assert(tx_tail < RL_N_TX);
1993 rep->re_tx_tail= tx_tail;
1994 continue;
1996 tsd= rl_inl(port, RL_TSD0+tx_tail*4);
1997 if (!(tsd & RL_TSD_OWN))
1999 /* Buffer is not yet ready */
2000 break;
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",
2009 tx_tail, tsd);
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++;
2025 else
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",
2037 rep->re_name,
2038 (ertxth >> RL_TSD_ERTXTH_S) *
2039 32);
2040 rep->re_ertxth= ertxth;
2043 rep->re_tx[tx_tail].ret_busy= FALSE;
2045 #if 0
2046 if (rep->re_flags & REF_SEND_AVAIL)
2048 printf("TSD%d: %08lx\n", tx_tail, tsd);
2049 printf(
2050 "rl_handler: head %d, tail %d, busy: %d %d %d %d\n",
2051 tx_head, tx_tail,
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);
2055 #endif
2057 if (++tx_tail >= N_TX_BUF)
2058 tx_tail= 0;
2059 assert(tx_tail < RL_N_TX);
2060 rep->re_tx_tail= tx_tail;
2062 if (rep->re_flags & REF_SEND_AVAIL)
2064 #if 0
2065 printf("rl_handler: REF_SEND_AVAIL\n");
2066 #endif
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);
2077 if (isr)
2079 printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
2080 isr);
2083 return 1;
2086 /*===========================================================================*
2087 * rl_watchdog_f *
2088 *===========================================================================*/
2089 static void rl_watchdog_f(tp)
2090 timer_t *tp;
2092 re_t *rep;
2093 /* Use a synchronous alarm instead of a watchdog timer. */
2094 sys_setalarm(system_hz, 0);
2096 rep= &re_state;
2098 if (rep->re_mode != REM_ENABLED)
2099 return;
2100 if (!(rep->re_flags & REF_SEND_AVAIL))
2102 /* Assume that an idle system is alive */
2103 rep->re_tx_alive= TRUE;
2104 return;
2106 if (rep->re_tx_alive)
2108 rep->re_tx_alive= FALSE;
2109 return;
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;
2125 check_int_events();
2128 #if 0
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)
2137 dpeth_t *dep;
2139 u8_t reg_a, reg_b, cr, config0, config2, config3;
2140 int i;
2141 char val[128];
2143 printf("rtl_init called\n");
2144 ne_init(dep);
2146 /* ID */
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));
2187 printf("\n");
2189 if (0 == sys_getkenv("RTL8029MN",9+1, val, sizeof(val)))
2191 ee_wen(dep);
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);
2198 ee_wds(dep);
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)))
2208 ee_wen(dep);
2210 set_ee_word(dep, 0x76/2, 0x8029);
2212 ee_wds(dep);
2214 assert(get_ee_word(dep, 0x76/2) == 0x8029);
2218 static u16_t get_ee_word(dep, a)
2219 dpeth_t *dep;
2220 int a;
2222 int b, i, cmd;
2223 u16_t w;
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));
2234 b= (b ? 2 : 0);
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 */
2242 w= 0;
2243 for (i= 0; i<16; i++)
2245 w <<= 1;
2247 /* Data is shifted out on the rising edge. Read at the
2248 * falling edge.
2250 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);
2251 outb_reg3(dep, 1, 0x80 | 0x8 | b);
2252 b= inb_reg3(dep, 1);
2253 w |= (b & 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 */
2260 return w;
2263 static void ee_wen(dep)
2264 dpeth_t *dep;
2266 int b, i, cmd;
2267 u16_t w;
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));
2278 b= (b ? 2 : 0);
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)
2290 dpeth_t *dep;
2291 int a;
2292 u16_t w;
2294 int b, i, cmd;
2295 clock_t t0, t1;
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));
2303 b= (b ? 2 : 0);
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--)
2311 b= (w & (1 << i));
2312 b= (b ? 2 : 0);
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 */
2322 getuptime(&t0);
2323 do {
2324 if (inb_reg3(dep, 1) & 1)
2325 break;
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)
2332 dpeth_t *dep;
2334 int b, i, cmd;
2335 u16_t w;
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));
2346 b= (b ? 2 : 0);
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 */
2357 #endif
2359 PRIVATE void tell_dev(buf, size, pci_bus, pci_dev, pci_func)
2360 vir_bytes buf;
2361 size_t size;
2362 int pci_bus;
2363 int pci_dev;
2364 int pci_func;
2366 int r;
2367 endpoint_t dev_e;
2368 message m;
2370 r= ds_retrieve_label_endpt("amddev", &dev_e);
2371 if (r != OK)
2373 #if 0
2374 printf(
2375 "rtl8139`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n",
2377 #endif
2378 return;
2381 m.m_type= IOMMU_MAP;
2382 m.m2_i1= pci_bus;
2383 m.m2_i2= pci_dev;
2384 m.m2_i3= pci_func;
2385 m.m2_l1= buf;
2386 m.m2_l2= size;
2388 r= sendrec(dev_e, &m);
2389 if (r != OK)
2391 printf("rtl8139`tell_dev: sendrec to %d failed: %d\n",
2392 dev_e, r);
2393 return;
2395 if (m.m_type != OK)
2397 printf("rtl8139`tell_dev: dma map request failed: %d\n",
2398 m.m_type);
2399 return;
2404 * $PchId: rtl8139.c,v 1.3 2003/09/11 14:15:15 philip Exp $