use oxpcie only if enabled to avoid baud bottleneck of uart.
[minix.git] / drivers / fxp / fxp.c
blob01156ba576a71b7b87c36d77d0002c64a25de103
1 /*
2 * fxp.c
4 * This file contains an ethernet device driver for Intel 82557, 82558,
5 * 82559, 82550, and 82562 fast ethernet controllers.
7 * Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
8 */
10 #include <minix/drivers.h>
11 #include <minix/netdriver.h>
13 #include <stdlib.h>
14 #include <net/hton.h>
15 #include <net/gen/ether.h>
16 #include <net/gen/eth_io.h>
17 #include <machine/pci.h>
18 #include <minix/ds.h>
19 #include <minix/endpoint.h>
21 #include <timers.h>
23 #define tmra_ut timer_t
24 #define tmra_inittimer(tp) tmr_inittimer(tp)
25 #define debug 0
26 #define RAND_UPDATE /**/
27 #define printW() ((void)0)
29 #include "assert.h"
30 #include "fxp.h"
31 #include "mii.h"
33 /* Number of receive buffers */
34 #define N_RX_BUF 40
36 /* Number of transmit buffers */
37 #define N_TX_BUF 4
39 /* I/O vectors are handled IOVEC_NR entries at a time. */
40 #define IOVEC_NR 16
42 /* Configuration */
43 #define FXP_ENVVAR "FXPETH"
45 struct pcitab
47 u16_t vid;
48 u16_t did;
49 int checkclass;
52 PRIVATE struct pcitab pcitab_fxp[]=
54 { 0x8086, 0x1229, 0 }, /* Intel 82557, etc. */
55 { 0x8086, 0x2449, 0 }, /* Intel 82801BA/BAM/CA/CAM */
56 { 0x8086, 0x103d, 0 }, /* Intel 82801DB */
57 { 0x8086, 0x1064, 0 }, /* Intel 82562 */
59 { 0x0000, 0x0000, 0 }
62 typedef int irq_hook_t;
64 static timer_t *fxp_timers= NULL;
65 static clock_t fxp_next_timeout= 0;
67 /* ignore interrupt for the moment */
68 #define interrupt(x) 0
70 PRIVATE union tmpbuf
72 char pad[4096];
73 struct cbl_conf cc;
74 struct ias ias;
75 } *tmpbufp;
77 typedef struct fxp
79 port_t fxp_base_port;
80 int fxp_mode;
81 int fxp_got_int;
82 int fxp_send_int;
83 int fxp_flags;
84 int fxp_client;
85 int fxp_features; /* Needed? */
86 int fxp_irq;
87 int fxp_type; /* What kind of hardware */
88 int fxp_ee_addrlen; /* #EEPROM address bits */
89 int fxp_tx_alive;
90 int fxp_need_reset;
92 /* Rx */
93 vir_bytes fxp_read_s;
94 int fxp_rx_nbuf;
95 int fxp_rx_bufsize;
96 struct rfd *fxp_rx_buf;
97 phys_bytes fxp_rx_busaddr;
98 int fxp_rx_head;
99 int fxp_rx_need_restart;
100 int fxp_need_conf; /* Re-configure after draining send
101 * queue
104 /* Tx */
105 int fxp_tx_nbuf;
106 int fxp_tx_bufsize;
107 struct tx *fxp_tx_buf;
108 phys_bytes fxp_tx_busaddr;
109 int fxp_tx_idle;
110 int fxp_tx_head;
111 int fxp_tx_tail;
112 int fxp_tx_threshold;
114 /* Link status */
115 int fxp_report_link;
116 int fxp_link_up;
117 int fxp_mii_busy;
118 u16_t fxp_mii_scr;
120 /* PCI related */
121 int fxp_seen; /* TRUE iff device available */
122 u8_t fxp_pcibus;
123 u8_t fxp_pcidev;
124 u8_t fxp_pcifunc;
126 /* 'large' items */
127 irq_hook_t fxp_hook;
128 ether_addr_t fxp_address;
129 message fxp_rx_mess;
130 message fxp_tx_mess;
131 struct sc fxp_stat;
132 u8_t fxp_conf_bytes[CC_BYTES_NR];
133 char fxp_name[sizeof("fxp#n")];
134 iovec_t fxp_iovec[IOVEC_NR];
135 iovec_s_t fxp_iovec_s[IOVEC_NR];
137 fxp_t;
139 /* fxp_mode */
140 #define FM_DISABLED 0x0
141 #define FM_ENABLED 0x1
143 /* fxp_flags */
144 #define FF_EMPTY 0x000
145 #define FF_PACK_SENT 0x001
146 #define FF_PACK_RECV 0x002
147 #define FF_SEND_AVAIL 0x004
148 #define FF_READING 0x010
149 #define FF_PROMISC 0x040
150 #define FF_MULTI 0x080
151 #define FF_BROAD 0x100
152 #define FF_ENABLED 0x200
154 /* fxp_features */
155 #define FFE_NONE 0x0
157 /* fxp_type */
158 #define FT_UNKNOWN 0x0
159 #define FT_82557 0x1
160 #define FT_82558A 0x2
161 #define FT_82559 0x4
162 #define FT_82801 0x8
164 PRIVATE int fxp_instance;
166 PRIVATE fxp_t *fxp_state;
168 PRIVATE tmra_ut fxp_watchdog;
170 PRIVATE u32_t system_hz;
172 #define fxp_inb(port, offset) (do_inb((port) + (offset)))
173 #define fxp_inl(port, offset) (do_inl((port) + (offset)))
174 #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
175 #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
177 _PROTOTYPE( static void fxp_init, (message *mp) );
178 _PROTOTYPE( static void fxp_pci_conf, (void) );
179 _PROTOTYPE( static int fxp_probe, (fxp_t *fp, int skip) );
180 _PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp) );
181 _PROTOTYPE( static void fxp_init_hw, (fxp_t *fp) );
182 _PROTOTYPE( static void fxp_init_buf, (fxp_t *fp) );
183 _PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp) );
184 _PROTOTYPE( static void fxp_confaddr, (fxp_t *fp) );
185 _PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp) );
186 _PROTOTYPE( static void fxp_writev_s, (const message *mp, int from_int) );
187 _PROTOTYPE( static void fxp_readv_s, (message *mp, int from_int) );
188 _PROTOTYPE( static void fxp_do_conf, (fxp_t *fp) );
189 _PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
190 phys_bytes bus_addr, int check_idle) );
191 _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
192 phys_bytes bus_addr, int check_idle) );
193 _PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
194 _PROTOTYPE( static void fxp_getstat_s, (message *mp) );
195 _PROTOTYPE( static void fxp_handler, (fxp_t *fp) );
196 _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) );
197 _PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp) );
198 _PROTOTYPE( static int fxp_link_changed, (fxp_t *fp) );
199 _PROTOTYPE( static void fxp_report_link, (fxp_t *fp) );
200 _PROTOTYPE( static void reply, (fxp_t *fp) );
201 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
202 _PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg) );
203 _PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
204 _PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) );
205 _PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,
206 tmr_func_t watchdog) );
207 _PROTOTYPE( static void fxp_expire_timers,(void) );
208 _PROTOTYPE( static u8_t do_inb, (port_t port) );
209 _PROTOTYPE( static u32_t do_inl, (port_t port) );
210 _PROTOTYPE( static void do_outb, (port_t port, u8_t v) );
211 _PROTOTYPE( static void do_outl, (port_t port, u32_t v) );
212 _PROTOTYPE( static void tell_dev, (vir_bytes start, size_t size,
213 int pci_bus, int pci_dev, int pci_func) );
215 PRIVATE void handle_hw_intr(void)
217 int r;
218 fxp_t *fp;
220 fp= fxp_state;
222 if (fp->fxp_mode != FM_ENABLED)
223 return;
224 fxp_handler(fp);
226 r= sys_irqenable(&fp->fxp_hook);
227 if (r != OK) {
228 panic("unable enable interrupts: %d", r);
231 if (!fp->fxp_got_int)
232 return;
233 fp->fxp_got_int= 0;
234 assert(fp->fxp_flags & FF_ENABLED);
235 fxp_check_ints(fp);
238 /* SEF functions and variables. */
239 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
240 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
241 FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
242 EXTERN int env_argc;
243 EXTERN char **env_argv;
245 /*===========================================================================*
246 * main *
247 *===========================================================================*/
248 int main(int argc, char *argv[])
250 message m;
251 int ipc_status;
252 int r;
254 /* SEF local startup. */
255 env_setargs(argc, argv);
256 sef_local_startup();
258 while (TRUE)
260 if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK)
261 panic("netdriver_receive failed: %d", r);
263 if (is_ipc_notify(ipc_status)) {
264 switch (_ENDPOINT_P(m.m_source)) {
265 case HARDWARE:
266 handle_hw_intr();
267 break;
268 case CLOCK:
269 fxp_expire_timers();
270 break;
271 default:
272 panic(" illegal notify from: %d", m.m_source);
275 /* get new message */
276 continue;
279 switch (m.m_type)
281 case DL_WRITEV_S: fxp_writev_s(&m, FALSE); break;
282 case DL_READV_S: fxp_readv_s(&m, FALSE); break;
283 case DL_CONF: fxp_init(&m); break;
284 case DL_GETSTAT_S: fxp_getstat_s(&m); break;
285 default:
286 panic(" illegal message: %d", m.m_type);
291 /*===========================================================================*
292 * sef_local_startup *
293 *===========================================================================*/
294 PRIVATE void sef_local_startup()
296 /* Register init callbacks. */
297 sef_setcb_init_fresh(sef_cb_init_fresh);
298 sef_setcb_init_lu(sef_cb_init_fresh);
299 sef_setcb_init_restart(sef_cb_init_fresh);
301 /* Register live update callbacks. */
302 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
303 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
305 /* Register signal callbacks. */
306 sef_setcb_signal_handler(sef_cb_signal_handler);
308 /* Let SEF perform startup. */
309 sef_startup();
312 /*===========================================================================*
313 * sef_cb_init_fresh *
314 *===========================================================================*/
315 PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
317 /* Initialize the fxp driver. */
318 long v;
319 int r;
320 vir_bytes ft;
322 system_hz = sys_hz();
324 v = 0;
325 (void) env_parse("instance", "d", 0, &v, 0, 255);
326 fxp_instance = (int) v;
328 ft = sizeof(*fxp_state);
330 if(!(fxp_state = alloc_contig(ft, 0, NULL)))
331 panic("couldn't allocate table: %d", ENOMEM);
333 memset(fxp_state, 0, ft);
335 if((r=tsc_calibrate()) != OK)
336 panic("tsc_calibrate failed: %d", r);
338 /* Announce we are up! */
339 netdriver_announce();
341 return(OK);
344 /*===========================================================================*
345 * sef_cb_signal_handler *
346 *===========================================================================*/
347 PRIVATE void sef_cb_signal_handler(int signo)
349 port_t port;
350 fxp_t *fp;
352 /* Only check for termination signal, ignore anything else. */
353 if (signo != SIGTERM) return;
355 fp= fxp_state;
357 if (fp->fxp_mode == FM_ENABLED && (fp->fxp_flags & FF_ENABLED)) {
358 port= fp->fxp_base_port;
360 /* Reset device */
361 if (debug)
362 printf("%s: resetting device\n", fp->fxp_name);
363 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
366 exit(0);
369 /*===========================================================================*
370 * fxp_init *
371 *===========================================================================*/
372 static void fxp_init(mp)
373 message *mp;
375 static int first_time= 1;
377 fxp_t *fp;
378 message reply_mess;
380 if (first_time)
382 first_time= 0;
383 fxp_pci_conf(); /* Configure PCI devices. */
385 tmra_inittimer(&fxp_watchdog);
386 tmr_arg(&fxp_watchdog)->ta_int= 0;
387 fxp_set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f);
390 fp= fxp_state;
391 if (fp->fxp_mode == FM_DISABLED)
393 /* This is the default, try to (re)locate the device. */
394 fxp_conf_hw(fp);
395 if (fp->fxp_mode == FM_DISABLED)
397 /* Probe failed, or the device is configured off. */
398 reply_mess.m_type= DL_CONF_REPLY;
399 reply_mess.DL_STAT= ENXIO;
400 mess_reply(mp, &reply_mess);
401 return;
403 if (fp->fxp_mode == FM_ENABLED)
404 fxp_init_hw(fp);
405 fxp_report_link(fp);
408 assert(fp->fxp_mode == FM_ENABLED);
409 assert(fp->fxp_flags & FF_ENABLED);
411 fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
413 if (mp->DL_MODE & DL_PROMISC_REQ)
414 fp->fxp_flags |= FF_PROMISC;
415 if (mp->DL_MODE & DL_MULTI_REQ)
416 fp->fxp_flags |= FF_MULTI;
417 if (mp->DL_MODE & DL_BROAD_REQ)
418 fp->fxp_flags |= FF_BROAD;
420 fxp_rec_mode(fp);
422 reply_mess.m_type = DL_CONF_REPLY;
423 reply_mess.DL_STAT = OK;
424 *(ether_addr_t *) reply_mess.DL_HWADDR = fp->fxp_address;
426 mess_reply(mp, &reply_mess);
429 /*===========================================================================*
430 * fxp_pci_conf *
431 *===========================================================================*/
432 static void fxp_pci_conf()
434 static char envvar[] = FXP_ENVVAR "#";
435 static char envfmt[] = "*:d.d.d";
437 fxp_t *fp;
438 long v;
440 fp= fxp_state;
442 strcpy(fp->fxp_name, "fxp#0");
443 fp->fxp_name[4] += fxp_instance;
444 fp->fxp_seen= FALSE;
445 fp->fxp_features= FFE_NONE;
446 envvar[sizeof(FXP_ENVVAR)-1]= '0'+fxp_instance;
447 #if 0
448 if (getenv(envvar) != NULL)
450 if (strcmp(getenv(envvar), "off") == 0)
452 fp->fxp_pcibus= 255;
454 if (!env_prefix(envvar, "pci"))
455 env_panic(envvar);
457 #endif
459 pci_init();
461 if (fp->fxp_pcibus == 255)
462 return;
464 v= 0;
465 #if 0
466 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
467 #endif
468 fp->fxp_pcibus= v;
469 v= 0;
470 #if 0
471 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
472 #endif
473 fp->fxp_pcidev= v;
474 v= 0;
475 #if 0
476 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
477 #endif
478 fp->fxp_pcifunc= v;
480 if (fxp_probe(fp, fxp_instance))
481 fp->fxp_seen= TRUE;
484 /*===========================================================================*
485 * fxp_probe *
486 *===========================================================================*/
487 static int fxp_probe(fxp_t *fp, int skip)
489 int i, r, devind, just_one;
490 u16_t vid, did;
491 u32_t bar;
492 u8_t ilr, rev;
493 char *dname, *str;
495 if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)
497 /* Look for specific PCI device */
498 r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,
499 fp->fxp_pcifunc, &devind);
500 if (r == 0)
502 printf("%s: no PCI device found at %d.%d.%d\n",
503 fp->fxp_name, fp->fxp_pcibus,
504 fp->fxp_pcidev, fp->fxp_pcifunc);
505 return FALSE;
507 pci_ids(devind, &vid, &did);
508 just_one= TRUE;
510 else
512 r= pci_first_dev(&devind, &vid, &did);
513 if (r == 0)
514 return FALSE;
515 just_one= FALSE;
518 for(;;)
520 for (i= 0; pcitab_fxp[i].vid != 0; i++)
522 if (pcitab_fxp[i].vid != vid)
523 continue;
524 if (pcitab_fxp[i].did != did)
525 continue;
526 if (pcitab_fxp[i].checkclass) {
527 panic("fxp_probe: class check not implemented");
529 break;
531 if (pcitab_fxp[i].vid != 0)
533 if (just_one || !skip)
534 break;
535 skip--;
538 if (just_one)
540 printf(
541 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
542 fp->fxp_name, vid, did,
543 fp->fxp_pcibus,
544 fp->fxp_pcidev, fp->fxp_pcifunc);
545 return FALSE;
548 r= pci_next_dev(&devind, &vid, &did);
549 if (!r)
550 return FALSE;
553 dname= pci_dev_name(vid, did);
554 #if VERBOSE
555 if (!dname)
556 dname= "unknown device";
557 printf("%s: %s (%04x/%04x) at %s\n",
558 fp->fxp_name, dname, vid, did, pci_slot_name(devind));
559 #endif
560 pci_reserve(devind);
562 bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
563 if (bar < 0x400) {
564 panic("fxp_probe: base address is not properly configured");
566 fp->fxp_base_port= bar;
568 ilr= pci_attr_r8(devind, PCI_ILR);
569 fp->fxp_irq= ilr;
570 if (debug)
572 printf("%s: using I/O address 0x%lx, IRQ %d\n",
573 fp->fxp_name, (unsigned long)bar, ilr);
576 rev= pci_attr_r8(devind, PCI_REV);
577 str= NULL;
578 fp->fxp_type= FT_UNKNOWN;
579 switch(rev)
581 case FXP_REV_82557A: str= "82557A"; /* 0x01 */
582 fp->fxp_type= FT_82557;
583 break;
584 case FXP_REV_82557B: str= "82557B"; break; /* 0x02 */
585 case FXP_REV_82557C: str= "82557C"; break; /* 0x03 */
586 case FXP_REV_82558A: str= "82558A"; /* 0x04 */
587 fp->fxp_type= FT_82558A;
588 break;
589 case FXP_REV_82558B: str= "82558B"; break; /* 0x05 */
590 case FXP_REV_82559A: str= "82559A"; break; /* 0x06 */
591 case FXP_REV_82559B: str= "82559B"; break; /* 0x07 */
592 case FXP_REV_82559C: str= "82559C"; /* 0x08 */
593 fp->fxp_type= FT_82559;
594 break;
595 case FXP_REV_82559ERA: str= "82559ER-A"; /* 0x09 */
596 fp->fxp_type= FT_82559;
597 break;
598 case FXP_REV_82550_1: str= "82550(1)"; /* 0x0C */
599 fp->fxp_type= FT_82559;
600 break;
601 case FXP_REV_82550_2: str= "82550(2)"; /* 0x0D */
602 fp->fxp_type= FT_82559;
603 break;
604 case FXP_REV_82550_3: str= "82550(3)"; /* 0x0E */
605 fp->fxp_type= FT_82559;
606 break;
607 case FXP_REV_82551_1: str= "82551(1)"; /* 0x0F */
608 fp->fxp_type= FT_82559;
609 break;
610 case FXP_REV_82551_2: str= "82551(2)"; /* 0x10 */
611 fp->fxp_type= FT_82559;
612 break;
613 case FXP_REV_82801DB: str= "82801DB"; /* 0x81 */
614 fp->fxp_type= FT_82801;
615 break;
618 #if VERBOSE
619 if (str)
620 printf("%s: device revision: %s\n", fp->fxp_name, str);
621 else
622 printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
623 #endif
625 if (fp->fxp_type == FT_UNKNOWN)
627 printf("fxp_probe: device is not supported by this driver\n");
628 return FALSE;
631 return TRUE;
634 /*===========================================================================*
635 * fxp_conf_hw *
636 *===========================================================================*/
637 static void fxp_conf_hw(fxp_t *fp)
639 int i;
640 int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;
642 fp->fxp_mode= FM_DISABLED; /* Superfluous */
644 if (!fp->fxp_seen)
645 return;
647 /* PCI device is present */
648 fp->fxp_mode= FM_ENABLED;
650 fp->fxp_flags= FF_EMPTY;
651 fp->fxp_got_int= 0;
652 fp->fxp_send_int= 0;
653 fp->fxp_ee_addrlen= 0; /* Unknown */
654 fp->fxp_need_reset= 0;
655 fp->fxp_report_link= 0;
656 fp->fxp_link_up= -1; /* Unknown */
657 fp->fxp_mii_busy= 0;
658 fp->fxp_read_s= 0;
659 fp->fxp_rx_need_restart= 0;
660 fp->fxp_need_conf= 0;
661 fp->fxp_tx_head= 0;
662 fp->fxp_tx_tail= 0;
663 fp->fxp_tx_alive= 0;
664 fp->fxp_tx_threshold= TXTT_MIN;
666 /* Try to come up with a sensible configuration for the current
667 * device. Unfortunately every device is different, defaults are
668 * not always zero, and some fields are re-used with a completely
669 * different interpretation. We start out with a sensible default
670 * for all devices and then add device specific changes.
672 fp->fxp_conf_bytes[0]= CC_BYTES_NR;
673 fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
674 fp->fxp_conf_bytes[2]= CAI_DEFAULT;
675 fp->fxp_conf_bytes[3]= 0;
676 fp->fxp_conf_bytes[4]= 0;
677 fp->fxp_conf_bytes[5]= 0;
678 fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
679 fp->fxp_conf_bytes[7]= CUR_1;
680 fp->fxp_conf_bytes[8]= CCB8_503_MII;
681 fp->fxp_conf_bytes[9]= 0;
682 fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
683 CCB10_RES1;
684 fp->fxp_conf_bytes[11]= 0;
685 fp->fxp_conf_bytes[12]= CIS_DEFAULT;
686 fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
687 fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
688 fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
689 fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
690 fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
691 fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
692 fp->fxp_conf_bytes[19]= CCB19_FDPE;
693 fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
694 fp->fxp_conf_bytes[21]= CCB21_RES21;
696 #if VERBOSE
697 for (i= 0; i<CC_BYTES_NR; i++)
698 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
699 printf("\n");
700 #endif
702 mwi= 0; /* Do we want "Memory Write and Invalidate"? */
703 ext_stat1= 0; /* Do we want extended statistical counters? */
704 ext_stat2= 0; /* Do we want even more statistical counters? */
705 lim_fifo= 0; /* Limit number of frame in TX FIFO */
706 i82503= 0; /* Older 10 Mbps interface on the 82557 */
707 fc= 0; /* Flow control */
709 switch(fp->fxp_type)
711 case FT_82557:
712 if (i82503)
714 fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;
715 fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;
717 break;
718 case FT_82558A:
719 case FT_82559:
720 case FT_82801:
721 if (mwi)
722 fp->fxp_conf_bytes[3] |= CCB3_MWIE;
723 if (ext_stat1)
724 fp->fxp_conf_bytes[6] &= ~CCB6_ESC;
725 if (ext_stat2)
726 fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;
727 if (lim_fifo)
728 fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;
729 if (fc)
731 /* From FreeBSD driver */
732 fp->fxp_conf_bytes[16]= 0x1f;
733 fp->fxp_conf_bytes[17]= 0x01;
735 fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |
736 CCB19_FDRSTOFC;
739 fp->fxp_conf_bytes[18] |= CCB18_LROK;
741 if (fp->fxp_type == FT_82801)
743 fp->fxp_conf_bytes[6] = 0xba; /* ctrl 1 */
744 fp->fxp_conf_bytes[15] = 0x48; /* promiscuous */
745 fp->fxp_conf_bytes[21] = 0x05; /* mc_all */
747 break;
748 default:
749 panic("fxp_conf_hw: bad device type: %d", fp->fxp_type);
752 #if VERBOSE
753 for (i= 0; i<CC_BYTES_NR; i++)
754 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
755 printf("\n");
756 #endif
759 /*===========================================================================*
760 * fxp_init_hw *
761 *===========================================================================*/
762 static void fxp_init_hw(fp)
763 fxp_t *fp;
765 int i, r, isr;
766 port_t port;
767 u32_t bus_addr;
769 port= fp->fxp_base_port;
771 fxp_init_buf(fp);
773 fp->fxp_flags = FF_EMPTY;
774 fp->fxp_flags |= FF_ENABLED;
776 /* Set the interrupt handler and policy. Do not automatically
777 * reenable interrupts. Return the IRQ line number on interrupts.
779 fp->fxp_hook = fp->fxp_irq;
780 r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
781 if (r != OK)
782 panic("sys_irqsetpolicy failed: %d", r);
784 fxp_reset_hw(fp);
786 r= sys_irqenable(&fp->fxp_hook);
787 if (r != OK)
788 panic("sys_irqenable failed: %d", r);
790 /* Reset PHY? */
792 fxp_do_conf(fp);
794 /* Set pointer to statistical counters */
795 r= sys_umap(SELF, VM_D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
796 &bus_addr);
797 if (r != OK)
798 panic("sys_umap failed: %d", r);
799 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);
801 /* Ack previous interrupts */
802 isr= fxp_inb(port, SCB_INT_STAT);
803 fxp_outb(port, SCB_INT_STAT, isr);
805 /* Enable interrupts */
806 fxp_outb(port, SCB_INT_MASK, 0);
808 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
809 TRUE /* check idle */);
811 fxp_confaddr(fp);
812 if (debug)
814 printf("%s: Ethernet address ", fp->fxp_name);
815 for (i= 0; i < 6; i++)
817 printf("%x%c", fp->fxp_address.ea_addr[i],
818 i < 5 ? ':' : '\n');
823 /*===========================================================================*
824 * fxp_init_buf *
825 *===========================================================================*/
826 static void fxp_init_buf(fp)
827 fxp_t *fp;
829 size_t rx_totbufsize, tx_totbufsize, tot_bufsize, alloc_bufsize;
830 char *alloc_buf;
831 phys_bytes buf;
832 int i, r;
833 struct rfd *rfdp;
834 struct tx *txp;
835 phys_bytes ph;
837 fp->fxp_rx_nbuf= N_RX_BUF;
838 rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
839 fp->fxp_rx_bufsize= rx_totbufsize;
841 fp->fxp_tx_nbuf= N_TX_BUF;
842 tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
843 fp->fxp_tx_bufsize= tx_totbufsize;
845 tot_bufsize= sizeof(*tmpbufp) + tx_totbufsize + rx_totbufsize;
846 if (tot_bufsize % 4096)
847 tot_bufsize += 4096 - (tot_bufsize % 4096);
848 alloc_bufsize= tot_bufsize;
849 alloc_buf= alloc_contig(alloc_bufsize, AC_ALIGN4K, &ph);
850 if (alloc_buf == NULL) {
851 panic("fxp_init_buf: unable to alloc_contig size: %d", alloc_bufsize);
854 buf= (phys_bytes)alloc_buf;
856 tell_dev((vir_bytes)buf, tot_bufsize, 0, 0, 0);
858 tmpbufp= (union tmpbuf *)buf;
860 fp->fxp_rx_buf= (struct rfd *)&tmpbufp[1];
861 r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_rx_buf, rx_totbufsize,
862 &fp->fxp_rx_busaddr);
863 if (r != OK)
864 panic("sys_umap failed: %d", r);
866 #if 0
867 printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n",
868 fp->fxp_rx_busaddr, fp->fxp_rx_buf);
869 #endif
871 for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
873 rfdp->rfd_status= 0;
874 rfdp->rfd_command= 0;
875 if (i != fp->fxp_rx_nbuf-1)
877 r= sys_umap(SELF, VM_D, (vir_bytes)&rfdp[1],
878 sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
879 if (r != OK)
880 panic("sys_umap failed: %d", r);
882 else
884 rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
885 rfdp->rfd_command |= RFDC_EL;
887 rfdp->rfd_reserved= 0;
888 rfdp->rfd_res= 0;
889 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
892 fp->fxp_rx_head= 0;
894 fp->fxp_tx_buf= (struct tx *)((char *)fp->fxp_rx_buf+rx_totbufsize);
895 r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_tx_buf,
896 (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
897 if (r != OK)
898 panic("sys_umap failed: %d", r);
900 for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
902 txp->tx_status= 0;
903 txp->tx_command= TXC_EL | CBL_NOP; /* Just in case */
904 if (i != fp->fxp_tx_nbuf-1)
906 r= sys_umap(SELF, VM_D, (vir_bytes)&txp[1],
907 (phys_bytes)sizeof(txp[1]),
908 &txp->tx_linkaddr);
909 if (r != OK)
910 panic("sys_umap failed: %d", r);
912 else
914 txp->tx_linkaddr= fp->fxp_tx_busaddr;
916 txp->tx_tbda= TX_TBDA_NIL;
917 txp->tx_size= 0;
918 txp->tx_tthresh= fp->fxp_tx_threshold;
919 txp->tx_ntbd= 0;
921 fp->fxp_tx_idle= 1;
924 /*===========================================================================*
925 * fxp_reset_hw *
926 *===========================================================================*/
927 static void fxp_reset_hw(fp)
928 fxp_t *fp;
930 /* Inline the function in init? */
931 port_t port;
933 port= fp->fxp_base_port;
935 /* Reset device */
936 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
937 tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY));
939 /* Disable interrupts */
940 fxp_outb(port, SCB_INT_MASK, SIM_M);
942 /* Set CU base to zero */
943 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
945 /* Set RU base to zero */
946 fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
949 /*===========================================================================*
950 * fxp_confaddr *
951 *===========================================================================*/
952 static void fxp_confaddr(fxp_t *fp)
954 static char eakey[]= FXP_ENVVAR "#_EA";
955 static char eafmt[]= "x:x:x:x:x:x";
956 clock_t t0,t1;
957 int i, r;
958 u32_t bus_addr;
959 long v;
961 /* User defined ethernet address? */
962 eakey[sizeof(FXP_ENVVAR)-1]= '0' + fxp_instance;
964 for (i= 0; i < 6; i++)
966 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
967 break;
968 fp->fxp_address.ea_addr[i]= v;
971 if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
973 if (i == 0)
975 /* Get ethernet address from EEPROM */
976 for (i= 0; i<3; i++)
978 v= eeprom_read(fp, i);
979 fp->fxp_address.ea_addr[i*2]= (v & 0xff);
980 fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
984 /* Tell NIC about ethernet address */
985 tmpbufp->ias.ias_status= 0;
986 tmpbufp->ias.ias_command= CBL_C_EL | CBL_AIS;
987 tmpbufp->ias.ias_linkaddr= 0;
988 memcpy(tmpbufp->ias.ias_ethaddr, fp->fxp_address.ea_addr,
989 sizeof(tmpbufp->ias.ias_ethaddr));
990 r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->ias,
991 (phys_bytes)sizeof(tmpbufp->ias), &bus_addr);
992 if (r != OK)
993 panic("sys_umap failed: %d", r);
995 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
997 getuptime(&t0);
998 do {
999 /* Wait for CU command to complete */
1000 if (tmpbufp->ias.ias_status & CBL_F_C)
1001 break;
1002 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
1004 if (!(tmpbufp->ias.ias_status & CBL_F_C))
1005 panic("fxp_confaddr: CU command failed to complete");
1006 if (!(tmpbufp->ias.ias_status & CBL_F_OK))
1007 panic("fxp_confaddr: CU command failed");
1009 #if VERBOSE
1010 printf("%s: hardware ethernet address: ", fp->fxp_name);
1011 for (i= 0; i<6; i++)
1013 printf("%02x%s", fp->fxp_address.ea_addr[i],
1014 i < 5 ? ":" : "");
1016 printf("\n");
1017 #endif
1020 /*===========================================================================*
1021 * fxp_rec_mode *
1022 *===========================================================================*/
1023 static void fxp_rec_mode(fp)
1024 fxp_t *fp;
1026 fp->fxp_conf_bytes[0]= CC_BYTES_NR; /* Just to be sure */
1027 fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
1028 fp->fxp_conf_bytes[21] &= ~CCB21_MA;
1030 if (fp->fxp_flags & FF_PROMISC)
1031 fp->fxp_conf_bytes[15] |= CCB15_PM;
1032 if (fp->fxp_flags & FF_MULTI)
1033 fp->fxp_conf_bytes[21] |= CCB21_MA;
1035 if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
1036 fp->fxp_conf_bytes[15] |= CCB15_BD;
1038 /* Queue request if not idle */
1039 if (fp->fxp_tx_idle)
1041 fxp_do_conf(fp);
1043 else
1045 printf("fxp_rec_mode: setting fxp_need_conf\n");
1046 fp->fxp_need_conf= TRUE;
1050 /*===========================================================================*
1051 * fxp_writev_s *
1052 *===========================================================================*/
1053 static void fxp_writev_s(const message *mp, int from_int)
1055 endpoint_t iov_endpt;
1056 cp_grant_id_t iov_grant;
1057 vir_bytes iov_offset;
1058 int i, j, n, o, r, s, count, size, prev_head;
1059 int fxp_tx_nbuf, fxp_tx_head;
1060 u16_t tx_command;
1061 fxp_t *fp;
1062 iovec_s_t *iovp;
1063 struct tx *txp, *prev_txp;
1065 fp= fxp_state;
1067 count = mp->DL_COUNT;
1068 fp->fxp_client= mp->m_source;
1070 assert(fp->fxp_mode == FM_ENABLED);
1071 assert(fp->fxp_flags & FF_ENABLED);
1073 if (from_int)
1075 assert(fp->fxp_flags & FF_SEND_AVAIL);
1076 fp->fxp_flags &= ~FF_SEND_AVAIL;
1077 fp->fxp_tx_alive= TRUE;
1080 if (fp->fxp_tx_idle)
1082 txp= fp->fxp_tx_buf;
1083 fxp_tx_head= 0; /* lint */
1084 prev_txp= NULL; /* lint */
1086 else
1088 fxp_tx_nbuf= fp->fxp_tx_nbuf;
1089 prev_head= fp->fxp_tx_head;
1090 fxp_tx_head= prev_head+1;
1091 if (fxp_tx_head == fxp_tx_nbuf)
1092 fxp_tx_head= 0;
1093 assert(fxp_tx_head < fxp_tx_nbuf);
1095 if (fxp_tx_head == fp->fxp_tx_tail)
1097 /* Send queue is full */
1098 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1099 fp->fxp_flags |= FF_SEND_AVAIL;
1100 goto suspend;
1103 prev_txp= &fp->fxp_tx_buf[prev_head];
1104 txp= &fp->fxp_tx_buf[fxp_tx_head];
1107 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1108 assert(!(fp->fxp_flags & FF_PACK_SENT));
1110 iov_endpt= mp->DL_ENDPT;
1111 iov_grant= mp->DL_GRANT;
1113 size= 0;
1114 o= 0;
1115 iov_offset= 0;
1116 for (i= 0; i<count; i += IOVEC_NR,
1117 iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
1119 n= IOVEC_NR;
1120 if (i+n > count)
1121 n= count-i;
1122 r= sys_safecopyfrom(iov_endpt, iov_grant, iov_offset,
1123 (vir_bytes)fp->fxp_iovec_s,
1124 n * sizeof(fp->fxp_iovec_s[0]), D);
1125 if (r != OK)
1126 panic("fxp_writev: sys_safecopyfrom failed: %d", r);
1128 for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
1130 s= iovp->iov_size;
1131 if (size + s > ETH_MAX_PACK_SIZE_TAGGED) {
1132 panic("fxp_writev: invalid packet size: %d", size + s);
1135 r= sys_safecopyfrom(iov_endpt, iovp->iov_grant,
1136 0, (vir_bytes)(txp->tx_buf+o), s, D);
1137 if (r != OK) {
1138 panic("fxp_writev_s: sys_safecopyfrom failed: %d", r);
1140 size += s;
1141 o += s;
1144 if (size < ETH_MIN_PACK_SIZE)
1145 panic("fxp_writev: invalid packet size: %d", size);
1147 txp->tx_status= 0;
1148 txp->tx_command= TXC_EL | CBL_XMIT;
1149 txp->tx_tbda= TX_TBDA_NIL;
1150 txp->tx_size= TXSZ_EOF | size;
1151 txp->tx_tthresh= fp->fxp_tx_threshold;
1152 txp->tx_ntbd= 0;
1153 if (fp->fxp_tx_idle)
1155 fp->fxp_tx_idle= 0;
1156 fp->fxp_tx_head= fp->fxp_tx_tail= 0;
1158 fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
1159 TRUE /* check idle */);
1161 else
1163 /* Link new request in transmit list */
1164 tx_command= prev_txp->tx_command;
1165 assert(tx_command == (TXC_EL | CBL_XMIT));
1166 prev_txp->tx_command= CBL_XMIT;
1167 fp->fxp_tx_head= fxp_tx_head;
1170 fp->fxp_flags |= FF_PACK_SENT;
1172 /* If the interrupt handler called, don't send a reply. The reply
1173 * will be sent after all interrupts are handled.
1175 if (from_int)
1176 return;
1177 reply(fp);
1178 return;
1180 suspend:
1181 if (from_int)
1182 panic("fxp: should not be sending");
1184 fp->fxp_tx_mess= *mp;
1185 reply(fp);
1188 /*===========================================================================*
1189 * fxp_readv_s *
1190 *===========================================================================*/
1191 static void fxp_readv_s(mp, from_int)
1192 message *mp;
1193 int from_int;
1195 int i, j, n, o, r, s, count, size, fxp_rx_head, fxp_rx_nbuf;
1196 endpoint_t iov_endpt;
1197 cp_grant_id_t iov_grant;
1198 port_t port;
1199 unsigned packlen;
1200 vir_bytes iov_offset;
1201 u16_t rfd_status;
1202 u16_t rfd_res;
1203 u8_t scb_status;
1204 fxp_t *fp;
1205 iovec_s_t *iovp;
1206 struct rfd *rfdp, *prev_rfdp;
1208 fp= fxp_state;
1210 count = mp->DL_COUNT;
1211 fp->fxp_client= mp->m_source;
1213 assert(fp->fxp_mode == FM_ENABLED);
1214 assert(fp->fxp_flags & FF_ENABLED);
1216 port= fp->fxp_base_port;
1218 fxp_rx_head= fp->fxp_rx_head;
1219 rfdp= &fp->fxp_rx_buf[fxp_rx_head];
1221 rfd_status= rfdp->rfd_status;
1222 if (!(rfd_status & RFDS_C))
1224 /* Receive buffer is empty, suspend */
1225 goto suspend;
1228 if (!(rfd_status & RFDS_OK))
1230 /* Not OK? What happened? */
1231 assert(0);
1233 else
1235 assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
1236 RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
1237 RFDS_RXERR)));
1239 rfd_res= rfdp->rfd_res;
1240 assert(rfd_res & RFDR_EOF);
1241 assert(rfd_res & RFDR_F);
1243 packlen= rfd_res & RFDSZ_SIZE;
1245 iov_endpt = mp->DL_ENDPT;
1246 iov_grant = mp->DL_GRANT;
1248 size= 0;
1249 o= 0;
1250 iov_offset= 0;
1251 for (i= 0; i<count; i += IOVEC_NR,
1252 iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
1254 n= IOVEC_NR;
1255 if (i+n > count)
1256 n= count-i;
1257 r= sys_safecopyfrom(iov_endpt, iov_grant, iov_offset,
1258 (vir_bytes)fp->fxp_iovec_s,
1259 n * sizeof(fp->fxp_iovec_s[0]), D);
1260 if (r != OK)
1261 panic("fxp_readv_s: sys_safecopyfrom failed: %d", r);
1263 for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
1265 s= iovp->iov_size;
1266 if (size + s > packlen)
1268 assert(packlen > size);
1269 s= packlen-size;
1272 r= sys_safecopyto(iov_endpt, iovp->iov_grant,
1273 0, (vir_bytes)(rfdp->rfd_buf+o), s, D);
1274 if (r != OK)
1276 panic("fxp_readv: sys_safecopyto failed: %d", r);
1279 size += s;
1280 if (size == packlen)
1281 break;
1282 o += s;
1284 if (size == packlen)
1285 break;
1287 if (size < packlen)
1289 assert(0);
1292 fp->fxp_read_s= packlen;
1293 fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
1295 /* Re-init the current buffer */
1296 rfdp->rfd_status= 0;
1297 rfdp->rfd_command= RFDC_EL;
1298 rfdp->rfd_reserved= 0;
1299 rfdp->rfd_res= 0;
1300 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1302 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1303 if (fxp_rx_head == 0)
1305 prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
1307 else
1308 prev_rfdp= &rfdp[-1];
1310 assert(prev_rfdp->rfd_command & RFDC_EL);
1311 prev_rfdp->rfd_command &= ~RFDC_EL;
1313 fxp_rx_head++;
1314 if (fxp_rx_head == fxp_rx_nbuf)
1315 fxp_rx_head= 0;
1316 assert(fxp_rx_head < fxp_rx_nbuf);
1317 fp->fxp_rx_head= fxp_rx_head;
1319 if (!from_int)
1320 reply(fp);
1322 return;
1324 suspend:
1325 if (fp->fxp_rx_need_restart)
1327 fp->fxp_rx_need_restart= 0;
1329 /* Check the status of the RU */
1330 scb_status= fxp_inb(port, SCB_STATUS);
1331 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
1333 /* Race condition? */
1334 printf("fxp_readv: restart race: 0x%x\n",
1335 scb_status);
1336 assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
1338 else
1340 fxp_restart_ru(fp);
1343 if (from_int)
1345 assert(fp->fxp_flags & FF_READING);
1347 /* No need to store any state */
1348 return;
1351 fp->fxp_rx_mess= *mp;
1352 assert(!(fp->fxp_flags & FF_READING));
1353 fp->fxp_flags |= FF_READING;
1355 reply(fp);
1358 /*===========================================================================*
1359 * fxp_do_conf *
1360 *===========================================================================*/
1361 static void fxp_do_conf(fp)
1362 fxp_t *fp;
1364 int r;
1365 u32_t bus_addr;
1366 clock_t t0,t1;
1368 /* Configure device */
1369 tmpbufp->cc.cc_status= 0;
1370 tmpbufp->cc.cc_command= CBL_C_EL | CBL_CONF;
1371 tmpbufp->cc.cc_linkaddr= 0;
1372 memcpy(tmpbufp->cc.cc_bytes, fp->fxp_conf_bytes,
1373 sizeof(tmpbufp->cc.cc_bytes));
1375 r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->cc,
1376 (phys_bytes)sizeof(tmpbufp->cc), &bus_addr);
1377 if (r != OK)
1378 panic("sys_umap failed: %d", r);
1380 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
1382 getuptime(&t0);
1383 do {
1384 /* Wait for CU command to complete */
1385 if (tmpbufp->cc.cc_status & CBL_F_C)
1386 break;
1387 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
1389 if (!(tmpbufp->cc.cc_status & CBL_F_C))
1390 panic("fxp_do_conf: CU command failed to complete");
1391 if (!(tmpbufp->cc.cc_status & CBL_F_OK))
1392 panic("fxp_do_conf: CU command failed");
1396 /*===========================================================================*
1397 * fxp_cu_ptr_cmd *
1398 *===========================================================================*/
1399 static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
1400 fxp_t *fp;
1401 int cmd;
1402 phys_bytes bus_addr;
1403 int check_idle;
1405 clock_t t0,t1;
1406 port_t port;
1407 u8_t scb_cmd;
1409 port= fp->fxp_base_port;
1411 if (check_idle)
1413 /* Consistency check. Make sure that CU is idle */
1414 if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
1415 panic("fxp_cu_ptr_cmd: CU is not idle");
1418 fxp_outl(port, SCB_POINTER, bus_addr);
1419 fxp_outb(port, SCB_CMD, cmd);
1421 /* What is a reasonable time-out? There is nothing in the
1422 * documentation. 1 ms should be enough.
1424 getuptime(&t0);
1425 do {
1426 /* Wait for CU command to be accepted */
1427 scb_cmd= fxp_inb(port, SCB_CMD);
1428 if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
1429 break;
1430 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
1432 if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
1433 panic("fxp_cu_ptr_cmd: CU does not accept command");
1436 /*===========================================================================*
1437 * fxp_ru_ptr_cmd *
1438 *===========================================================================*/
1439 static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
1440 fxp_t *fp;
1441 int cmd;
1442 phys_bytes bus_addr;
1443 int check_idle;
1445 clock_t t0,t1;
1446 port_t port;
1447 u8_t scb_cmd;
1449 port= fp->fxp_base_port;
1451 if (check_idle)
1453 /* Consistency check, make sure that RU is idle */
1454 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
1455 panic("fxp_ru_ptr_cmd: RU is not idle");
1458 fxp_outl(port, SCB_POINTER, bus_addr);
1459 fxp_outb(port, SCB_CMD, cmd);
1461 getuptime(&t0);
1462 do {
1463 /* Wait for RU command to be accepted */
1464 scb_cmd= fxp_inb(port, SCB_CMD);
1465 if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
1466 break;
1467 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
1469 if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
1470 panic("fxp_ru_ptr_cmd: RU does not accept command");
1473 /*===========================================================================*
1474 * fxp_restart_ru *
1475 *===========================================================================*/
1476 static void fxp_restart_ru(fp)
1477 fxp_t *fp;
1479 int i, fxp_rx_nbuf;
1480 port_t port;
1481 struct rfd *rfdp;
1483 port= fp->fxp_base_port;
1485 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1486 for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
1488 rfdp->rfd_status= 0;
1489 rfdp->rfd_command= 0;
1490 if (i == fp->fxp_rx_nbuf-1)
1491 rfdp->rfd_command= RFDC_EL;
1492 rfdp->rfd_reserved= 0;
1493 rfdp->rfd_res= 0;
1494 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1496 fp->fxp_rx_head= 0;
1498 /* Make sure that RU is in the 'No resources' state */
1499 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
1500 panic("fxp_restart_ru: RU is in an unexpected state");
1502 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
1503 FALSE /* do not check idle */);
1506 /*===========================================================================*
1507 * fxp_getstat_s *
1508 *===========================================================================*/
1509 static void fxp_getstat_s(message *mp)
1511 clock_t t0,t1;
1512 int r;
1513 fxp_t *fp;
1514 u32_t *p;
1515 eth_stat_t stats;
1517 fp= fxp_state;
1519 assert(fp->fxp_mode == FM_ENABLED);
1520 assert(fp->fxp_flags & FF_ENABLED);
1522 p= &fp->fxp_stat.sc_tx_fcp;
1523 *p= 0;
1525 /* The dump commmand doesn't take a pointer. Setting a pointer
1526 * doesn't hurt though.
1528 fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
1530 getuptime(&t0);
1531 do {
1532 /* Wait for CU command to complete */
1533 if (*p != 0)
1534 break;
1535 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
1537 if (*p == 0)
1538 panic("fxp_getstat: CU command failed to complete");
1539 if (*p != SCM_DSC)
1540 panic("fxp_getstat: bad magic");
1542 stats.ets_recvErr=
1543 fp->fxp_stat.sc_rx_crc +
1544 fp->fxp_stat.sc_rx_align +
1545 fp->fxp_stat.sc_rx_resource +
1546 fp->fxp_stat.sc_rx_overrun +
1547 fp->fxp_stat.sc_rx_cd +
1548 fp->fxp_stat.sc_rx_short;
1549 stats.ets_sendErr=
1550 fp->fxp_stat.sc_tx_maxcol +
1551 fp->fxp_stat.sc_tx_latecol +
1552 fp->fxp_stat.sc_tx_crs;
1553 stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
1554 stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
1555 stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
1556 stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
1557 stats.ets_packetR= fp->fxp_stat.sc_rx_good;
1558 stats.ets_packetT= fp->fxp_stat.sc_tx_good;
1559 stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
1560 stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
1561 stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
1562 stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
1563 stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
1564 stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
1565 stats.ets_CDheartbeat= 0;
1566 stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
1568 r= sys_safecopyto(mp->DL_ENDPT, mp->DL_GRANT, 0, (vir_bytes)&stats,
1569 sizeof(stats), D);
1570 if (r != OK)
1571 panic("fxp_getstat_s: sys_safecopyto failed: %d", r);
1573 mp->m_type= DL_STAT_REPLY;
1574 r= send(mp->m_source, mp);
1575 if (r != OK)
1576 panic("fxp_getstat_s: send failed: %d", r);
1579 /*===========================================================================*
1580 * fxp_handler *
1581 *===========================================================================*/
1582 static void fxp_handler(fxp_t *fp)
1584 int port;
1585 u16_t isr;
1587 RAND_UPDATE
1589 port= fp->fxp_base_port;
1591 /* Ack interrupt */
1592 isr= fxp_inb(port, SCB_INT_STAT);
1593 fxp_outb(port, SCB_INT_STAT, isr);
1595 if (isr & SIS_FR)
1597 isr &= ~SIS_FR;
1599 if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
1601 fp->fxp_got_int= TRUE;
1602 interrupt(fxp_tasknr);
1605 if (isr & SIS_CNA)
1607 isr &= ~SIS_CNA;
1608 if (!fp->fxp_tx_idle)
1610 fp->fxp_send_int= TRUE;
1611 if (!fp->fxp_got_int)
1613 fp->fxp_got_int= TRUE;
1614 interrupt(fxp_tasknr);
1618 if (isr & SIS_RNR)
1620 isr &= ~SIS_RNR;
1622 /* Assume that receive buffer is full of packets. fxp_readv
1623 * will restart the RU.
1625 fp->fxp_rx_need_restart= 1;
1627 if (isr)
1629 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
1630 isr);
1634 /*===========================================================================*
1635 * fxp_check_ints *
1636 *===========================================================================*/
1637 static void fxp_check_ints(fxp_t *fp)
1639 int n, fxp_flags, prev_tail;
1640 int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
1641 port_t port;
1642 u32_t busaddr;
1643 u16_t tx_status;
1644 u8_t scb_status;
1645 struct tx *txp;
1647 fxp_flags= fp->fxp_flags;
1649 if (fxp_flags & FF_READING)
1651 if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
1652 ; /* Nothing */
1653 else
1655 fxp_readv_s(&fp->fxp_rx_mess, TRUE /* from int */);
1658 if (fp->fxp_tx_idle)
1659 ; /* Nothing to do */
1660 else if (fp->fxp_send_int)
1662 fp->fxp_send_int= FALSE;
1663 fxp_tx_tail= fp->fxp_tx_tail;
1664 fxp_tx_nbuf= fp->fxp_tx_nbuf;
1665 n= 0;
1666 for (;;)
1668 txp= &fp->fxp_tx_buf[fxp_tx_tail];
1669 tx_status= txp->tx_status;
1670 if (!(tx_status & TXS_C))
1671 break;
1673 n++;
1675 assert(tx_status & TXS_OK);
1676 if (tx_status & TXS_U)
1678 fxp_tx_threshold= fp->fxp_tx_threshold;
1679 if (fxp_tx_threshold < TXTT_MAX)
1681 fxp_tx_threshold++;
1682 fp->fxp_tx_threshold= fxp_tx_threshold;
1684 printf(
1685 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
1686 fxp_tx_threshold);
1689 if (txp->tx_command & TXC_EL)
1691 fp->fxp_tx_idle= 1;
1692 break;
1695 fxp_tx_tail++;
1696 if (fxp_tx_tail == fxp_tx_nbuf)
1697 fxp_tx_tail= 0;
1698 assert(fxp_tx_tail < fxp_tx_nbuf);
1701 if (fp->fxp_need_conf)
1703 /* Check the status of the CU */
1704 port= fp->fxp_base_port;
1705 scb_status= fxp_inb(port, SCB_STATUS);
1706 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
1708 /* Nothing to do */
1709 printf("scb_status = 0x%x\n", scb_status);
1711 else
1713 printf("fxp_check_ints: fxp_need_conf\n");
1714 fp->fxp_need_conf= FALSE;
1715 fxp_do_conf(fp);
1719 if (n)
1721 if (!fp->fxp_tx_idle)
1723 fp->fxp_tx_tail= fxp_tx_tail;
1725 /* Check the status of the CU */
1726 port= fp->fxp_base_port;
1727 scb_status= fxp_inb(port, SCB_STATUS);
1728 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
1730 /* Nothing to do */
1731 printf("scb_status = 0x%x\n",
1732 scb_status);
1735 else
1737 if (fxp_tx_tail == 0)
1738 prev_tail= fxp_tx_nbuf-1;
1739 else
1740 prev_tail= fxp_tx_tail-1;
1741 busaddr= fp->fxp_tx_buf[prev_tail].
1742 tx_linkaddr;
1744 fxp_cu_ptr_cmd(fp, SC_CU_START,
1745 busaddr, 1 /* check idle */);
1749 if (fp->fxp_flags & FF_SEND_AVAIL)
1751 fxp_writev_s(&fp->fxp_tx_mess,
1752 TRUE /* from int */);
1757 if (fp->fxp_report_link)
1758 fxp_report_link(fp);
1760 if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
1761 reply(fp);
1764 /*===========================================================================*
1765 * fxp_watchdog_f *
1766 *===========================================================================*/
1767 static void fxp_watchdog_f(tp)
1768 timer_t *tp;
1770 fxp_t *fp;
1772 tmr_arg(&fxp_watchdog)->ta_int= 0;
1773 fxp_set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f);
1775 fp= fxp_state;
1776 if (fp->fxp_mode != FM_ENABLED)
1777 return;
1779 /* Handle race condition, MII interface might be busy */
1780 if(!fp->fxp_mii_busy)
1782 /* Check the link status. */
1783 if (fxp_link_changed(fp))
1785 #if VERBOSE
1786 printf("fxp_watchdog_f: link changed\n");
1787 #endif
1788 fp->fxp_report_link= TRUE;
1789 fp->fxp_got_int= TRUE;
1790 interrupt(fxp_tasknr);
1794 if (!(fp->fxp_flags & FF_SEND_AVAIL))
1796 /* Assume that an idle system is alive */
1797 fp->fxp_tx_alive= TRUE;
1798 return;
1800 if (fp->fxp_tx_alive)
1802 fp->fxp_tx_alive= FALSE;
1803 return;
1806 fp->fxp_need_reset= TRUE;
1807 fp->fxp_got_int= TRUE;
1808 interrupt(fxp_tasknr);
1811 /*===========================================================================*
1812 * fxp_link_changed *
1813 *===========================================================================*/
1814 static int fxp_link_changed(fp)
1815 fxp_t *fp;
1817 u16_t scr;
1819 scr= mii_read(fp, MII_SCR);
1820 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
1822 return (fp->fxp_mii_scr != scr);
1825 /*===========================================================================*
1826 * fxp_report_link *
1827 *===========================================================================*/
1828 static void fxp_report_link(fxp_t *fp)
1830 u16_t mii_ctrl, mii_status, mii_id1, mii_id2,
1831 mii_ana, mii_anlpa, mii_ane, mii_extstat,
1832 mii_ms_ctrl, mii_ms_status, scr;
1833 u32_t oui;
1834 int model, rev;
1835 int f, link_up, ms_regs;
1837 /* Assume an 82555 (compatible) PHY. The should be changed for
1838 * 82557 NICs with different PHYs
1840 ms_regs= 0; /* No master/slave registers. */
1842 fp->fxp_report_link= FALSE;
1844 scr= mii_read(fp, MII_SCR);
1845 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
1846 fp->fxp_mii_scr= scr;
1848 mii_ctrl= mii_read(fp, MII_CTRL);
1849 mii_read(fp, MII_STATUS); /* The status reg is latched, read twice */
1850 mii_status= mii_read(fp, MII_STATUS);
1851 mii_id1= mii_read(fp, MII_PHYID_H);
1852 mii_id2= mii_read(fp, MII_PHYID_L);
1853 mii_ana= mii_read(fp, MII_ANA);
1854 mii_anlpa= mii_read(fp, MII_ANLPA);
1855 mii_ane= mii_read(fp, MII_ANE);
1856 if (mii_status & MII_STATUS_EXT_STAT)
1857 mii_extstat= mii_read(fp, MII_EXT_STATUS);
1858 else
1859 mii_extstat= 0;
1860 if (ms_regs)
1862 mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
1863 mii_ms_status= mii_read(fp, MII_MS_STATUS);
1865 else
1867 mii_ms_ctrl= 0;
1868 mii_ms_status= 0;
1871 /* How do we know about the link status? */
1872 link_up= !!(mii_status & MII_STATUS_LS);
1874 fp->fxp_link_up= link_up;
1875 if (!link_up)
1877 #if VERBOSE
1878 printf("%s: link down\n", fp->fxp_name);
1879 #endif
1880 return;
1883 oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) |
1884 ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
1885 model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
1886 rev= (mii_id2 & MII_PL_REV_MASK);
1888 #if VERBOSE
1889 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
1890 #endif
1892 if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
1894 printf("%s: PHY: ", fp->fxp_name);
1895 f= 1;
1896 if (mii_ctrl & MII_CTRL_LB)
1898 printf("loopback mode");
1899 f= 0;
1901 if (mii_ctrl & MII_CTRL_PD)
1903 if (!f) printf(", ");
1904 f= 0;
1905 printf("powered down");
1907 if (mii_ctrl & MII_CTRL_ISO)
1909 if (!f) printf(", ");
1910 f= 0;
1911 printf("isolated");
1913 printf("\n");
1914 return;
1916 if (!(mii_ctrl & MII_CTRL_ANE))
1918 printf("%s: manual config: ", fp->fxp_name);
1919 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
1921 case MII_CTRL_SP_10: printf("10 Mbps"); break;
1922 case MII_CTRL_SP_100: printf("100 Mbps"); break;
1923 case MII_CTRL_SP_1000: printf("1000 Mbps"); break;
1924 case MII_CTRL_SP_RES: printf("reserved speed"); break;
1926 if (mii_ctrl & MII_CTRL_DM)
1927 printf(", full duplex");
1928 else
1929 printf(", half duplex");
1930 printf("\n");
1931 return;
1934 if (!debug) goto resspeed;
1936 printf("%s: ", fp->fxp_name);
1937 mii_print_stat_speed(mii_status, mii_extstat);
1938 printf("\n");
1940 if (!(mii_status & MII_STATUS_ANC))
1941 printf("%s: auto-negotiation not complete\n", fp->fxp_name);
1942 if (mii_status & MII_STATUS_RF)
1943 printf("%s: remote fault detected\n", fp->fxp_name);
1944 if (!(mii_status & MII_STATUS_ANA))
1946 printf("%s: local PHY has no auto-negotiation ability\n",
1947 fp->fxp_name);
1949 if (!(mii_status & MII_STATUS_LS))
1950 printf("%s: link down\n", fp->fxp_name);
1951 if (mii_status & MII_STATUS_JD)
1952 printf("%s: jabber condition detected\n", fp->fxp_name);
1953 if (!(mii_status & MII_STATUS_EC))
1955 printf("%s: no extended register set\n", fp->fxp_name);
1956 goto resspeed;
1958 if (!(mii_status & MII_STATUS_ANC))
1959 goto resspeed;
1961 printf("%s: local cap.: ", fp->fxp_name);
1962 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
1964 printf("1000 Mbps: T-");
1965 switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
1967 case MII_MSC_1000T_FD: printf("FD"); break;
1968 case MII_MSC_1000T_HD: printf("HD"); break;
1969 default: printf("FD/HD"); break;
1971 if (mii_ana)
1972 printf(", ");
1974 mii_print_techab(mii_ana);
1975 printf("\n");
1977 if (mii_ane & MII_ANE_PDF)
1978 printf("%s: parallel detection fault\n", fp->fxp_name);
1979 if (!(mii_ane & MII_ANE_LPANA))
1981 printf("%s: link-partner does not support auto-negotiation\n",
1982 fp->fxp_name);
1983 goto resspeed;
1986 printf("%s: remote cap.: ", fp->fxp_name);
1987 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
1988 if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
1990 printf("1000 Mbps: T-");
1991 switch(mii_ms_status &
1992 (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
1994 case MII_MSS_LP1000T_FD: printf("FD"); break;
1995 case MII_MSS_LP1000T_HD: printf("HD"); break;
1996 default: printf("FD/HD"); break;
1998 if (mii_anlpa)
1999 printf(", ");
2001 mii_print_techab(mii_anlpa);
2002 printf("\n");
2004 if (ms_regs)
2006 printf("%s: ", fp->fxp_name);
2007 if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
2009 printf("manual %s",
2010 (mii_ms_ctrl & MII_MSC_MS_VAL) ?
2011 "MASTER" : "SLAVE");
2013 else
2015 printf("%s device",
2016 (mii_ms_ctrl & MII_MSC_MULTIPORT) ?
2017 "multiport" : "single-port");
2019 if (mii_ms_ctrl & MII_MSC_RES)
2020 printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
2021 printf(": ");
2022 if (mii_ms_status & MII_MSS_FAULT)
2023 printf("M/S config fault");
2024 else if (mii_ms_status & MII_MSS_MASTER)
2025 printf("MASTER");
2026 else
2027 printf("SLAVE");
2028 printf("\n");
2031 if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
2033 if (!(mii_ms_status & MII_MSS_LOCREC))
2035 printf("%s: local receiver not OK\n",
2036 fp->fxp_name);
2038 if (!(mii_ms_status & MII_MSS_REMREC))
2040 printf("%s: remote receiver not OK\n",
2041 fp->fxp_name);
2044 if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
2046 printf("%s", fp->fxp_name);
2047 if (mii_ms_status & MII_MSS_RES)
2048 printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
2049 if (mii_ms_status & MII_MSS_IDLE_ERR)
2051 printf(" idle error %d",
2052 mii_ms_status & MII_MSS_IDLE_ERR);
2054 printf("\n");
2057 resspeed:
2058 #if VERBOSE
2059 printf("%s: link up, %d Mbps, %s duplex\n",
2060 fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
2061 (scr & MII_SCR_FD) ? "full" : "half");
2062 #endif
2066 /*===========================================================================*
2067 * reply *
2068 *===========================================================================*/
2069 static void reply(fp)
2070 fxp_t *fp;
2072 message reply;
2073 int flags;
2074 int r;
2076 flags = DL_NOFLAGS;
2077 if (fp->fxp_flags & FF_PACK_SENT)
2078 flags |= DL_PACK_SEND;
2079 if (fp->fxp_flags & FF_PACK_RECV)
2080 flags |= DL_PACK_RECV;
2082 reply.m_type = DL_TASK_REPLY;
2083 reply.DL_FLAGS = flags;
2084 reply.DL_COUNT = fp->fxp_read_s;
2086 r= send(fp->fxp_client, &reply);
2088 if (r < 0)
2089 panic("fxp: send failed: %d", r);
2091 fp->fxp_read_s = 0;
2092 fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
2095 /*===========================================================================*
2096 * mess_reply *
2097 *===========================================================================*/
2098 static void mess_reply(req, reply_mess)
2099 message *req;
2100 message *reply_mess;
2102 if (send(req->m_source, reply_mess) != OK)
2103 panic("fxp: unable to mess_reply");
2106 /*===========================================================================*
2107 * eeprom_read *
2108 *===========================================================================*/
2109 PRIVATE u16_t eeprom_read(fp, reg)
2110 fxp_t *fp;
2111 int reg;
2113 port_t port;
2114 u16_t v;
2115 int b, i, alen;
2117 alen= fp->fxp_ee_addrlen;
2118 if (!alen)
2120 eeprom_addrsize(fp);
2121 alen= fp->fxp_ee_addrlen;
2122 assert(alen == 6 || alen == 8);
2125 port= fp->fxp_base_port;
2127 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
2128 v= EEPROM_READ_PREFIX;
2129 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
2131 b= ((v & (1 << i)) ? CE_EEDI : 0);
2132 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2133 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2134 micro_delay(EESK_PERIOD/2+1);
2135 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2136 micro_delay(EESK_PERIOD/2+1);
2139 v= reg;
2140 for (i= alen-1; i >= 0; i--)
2142 b= ((v & (1 << i)) ? CE_EEDI : 0);
2143 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2144 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2145 micro_delay(EESK_PERIOD/2+1);
2146 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2147 micro_delay(EESK_PERIOD/2+1);
2150 v= 0;
2151 for (i= 0; i<16; i++)
2153 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2154 micro_delay(EESK_PERIOD/2+1);
2155 b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
2156 v= (v << 1) | b;
2157 fxp_outb(port, CSR_EEPROM, CE_EECS );
2158 micro_delay(EESK_PERIOD/2+1);
2160 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2161 micro_delay(EECS_DELAY);
2163 return v;
2166 /*===========================================================================*
2167 * eeprom_addrsize *
2168 *===========================================================================*/
2169 PRIVATE void eeprom_addrsize(fp)
2170 fxp_t *fp;
2172 port_t port;
2173 u16_t v;
2174 int b, i;
2176 port= fp->fxp_base_port;
2178 /* Try to find out the size of the EEPROM */
2179 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
2180 v= EEPROM_READ_PREFIX;
2181 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
2183 b= ((v & (1 << i)) ? CE_EEDI : 0);
2184 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2185 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2186 micro_delay(EESK_PERIOD/2+1);
2187 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2188 micro_delay(EESK_PERIOD/2+1);
2191 for (i= 0; i<32; i++)
2193 b= 0;
2194 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2195 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2196 micro_delay(EESK_PERIOD/2+1);
2197 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2198 micro_delay(EESK_PERIOD/2+1);
2199 v= fxp_inb(port, CSR_EEPROM);
2200 if (!(v & CE_EEDO))
2201 break;
2203 if (i >= 32)
2204 panic("eeprom_addrsize: failed");
2205 fp->fxp_ee_addrlen= i+1;
2207 /* Discard 16 data bits */
2208 for (i= 0; i<16; i++)
2210 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2211 micro_delay(EESK_PERIOD/2+1);
2212 fxp_outb(port, CSR_EEPROM, CE_EECS );
2213 micro_delay(EESK_PERIOD/2+1);
2215 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2216 micro_delay(EECS_DELAY);
2218 #if VERBOSE
2219 printf("%s EEPROM address length: %d\n",
2220 fp->fxp_name, fp->fxp_ee_addrlen);
2221 #endif
2224 /*===========================================================================*
2225 * mii_read *
2226 *===========================================================================*/
2227 PRIVATE u16_t mii_read(fp, reg)
2228 fxp_t *fp;
2229 int reg;
2231 clock_t t0,t1;
2232 port_t port;
2233 u32_t v;
2235 port= fp->fxp_base_port;
2237 assert(!fp->fxp_mii_busy);
2238 fp->fxp_mii_busy++;
2240 if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
2241 panic("mii_read: MDI not ready");
2242 fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
2243 (reg << CM_REG_SHIFT));
2245 getuptime(&t0);
2246 do {
2247 v= fxp_inl(port, CSR_MDI_CTL);
2248 if (v & CM_READY)
2249 break;
2250 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
2252 if (!(v & CM_READY))
2253 panic("mii_read: MDI not ready after command");
2255 fp->fxp_mii_busy--;
2256 assert(!fp->fxp_mii_busy);
2258 return v & CM_DATA_MASK;
2261 /*===========================================================================*
2262 * fxp_set_timer *
2263 *===========================================================================*/
2264 PRIVATE void fxp_set_timer(tp, delta, watchdog)
2265 timer_t *tp; /* timer to be set */
2266 clock_t delta; /* in how many ticks */
2267 tmr_func_t watchdog; /* watchdog function to be called */
2269 clock_t now; /* current time */
2270 int r;
2272 /* Get the current time. */
2273 r= getuptime(&now);
2274 if (r != OK)
2275 panic("unable to get uptime from clock: %d", r);
2277 /* Add the timer to the local timer queue. */
2278 tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
2280 /* Possibly reschedule an alarm call. This happens when a new timer
2281 * is added in front.
2283 if (fxp_next_timeout == 0 ||
2284 fxp_timers->tmr_exp_time < fxp_next_timeout)
2286 fxp_next_timeout= fxp_timers->tmr_exp_time;
2287 #if VERBOSE
2288 printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
2289 fxp_next_timeout, fxp_next_timeout-now);
2290 #endif
2291 r= sys_setalarm(fxp_next_timeout, 1);
2292 if (r != OK)
2293 panic("unable to set synchronous alarm: %d", r);
2297 /*===========================================================================*
2298 * fxp_expire_tmrs *
2299 *===========================================================================*/
2300 PRIVATE void fxp_expire_timers()
2302 /* A synchronous alarm message was received. Check if there are any expired
2303 * timers. Possibly reschedule the next alarm.
2305 clock_t now; /* current time */
2306 int r;
2308 /* Get the current time to compare the timers against. */
2309 r= getuptime(&now);
2310 if (r != OK)
2311 panic("Unable to get uptime from clock: %d", r);
2313 /* Scan the timers queue for expired timers. Dispatch the watchdog function
2314 * for each expired timers. Possibly a new alarm call must be scheduled.
2316 tmrs_exptimers(&fxp_timers, now, NULL);
2317 if (fxp_timers == NULL)
2318 fxp_next_timeout= TMR_NEVER;
2319 else
2320 { /* set new alarm */
2321 fxp_next_timeout = fxp_timers->tmr_exp_time;
2322 r= sys_setalarm(fxp_next_timeout, 1);
2323 if (r != OK)
2324 panic("Unable to set synchronous alarm: %d", r);
2328 static u8_t do_inb(port_t port)
2330 int r;
2331 u32_t value;
2333 r= sys_inb(port, &value);
2334 if (r != OK)
2335 panic("sys_inb failed: %d", r);
2336 return value;
2339 static u32_t do_inl(port_t port)
2341 int r;
2342 u32_t value;
2344 r= sys_inl(port, &value);
2345 if (r != OK)
2346 panic("sys_inl failed: %d", r);
2347 return value;
2350 static void do_outb(port_t port, u8_t value)
2352 int r;
2354 r= sys_outb(port, value);
2355 if (r != OK)
2356 panic("sys_outb failed: %d", r);
2359 static void do_outl(port_t port, u32_t value)
2361 int r;
2363 r= sys_outl(port, value);
2364 if (r != OK)
2365 panic("sys_outl failed: %d", r);
2368 PRIVATE void tell_dev(buf, size, pci_bus, pci_dev, pci_func)
2369 vir_bytes buf;
2370 size_t size;
2371 int pci_bus;
2372 int pci_dev;
2373 int pci_func;
2375 int r;
2376 endpoint_t dev_e;
2377 message m;
2379 r= ds_retrieve_label_endpt("amddev", &dev_e);
2380 if (r != OK)
2382 #if 0
2383 printf(
2384 "fxp`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n",
2386 #endif
2387 return;
2390 m.m_type= IOMMU_MAP;
2391 m.m2_i1= pci_bus;
2392 m.m2_i2= pci_dev;
2393 m.m2_i3= pci_func;
2394 m.m2_l1= buf;
2395 m.m2_l2= size;
2397 r= sendrec(dev_e, &m);
2398 if (r != OK)
2400 printf("fxp`tell_dev: sendrec to %d failed: %d\n",
2401 dev_e, r);
2402 return;
2404 if (m.m_type != OK)
2406 printf("fxp`tell_dev: dma map request failed: %d\n",
2407 m.m_type);
2408 return;
2413 * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $