dec21140A ethernet driver for virtualpc, contributed by nicolas tittley.
[minix.git] / drivers / fxp / fxp.c
blob0f8ca0e603e1d3fbf11f513eaf0f4f835cf26520
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 * The valid messages and their parameters are:
9 * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
10 * |------------+----------+---------+----------+---------+---------+---------|
11 * | HARDINT | | | | | | |
12 * |------------|----------|---------|----------|---------|---------|---------|
13 * | DL_WRITE | port nr | proc nr | count | mode | address | |
14 * |------------|----------|---------|----------|---------|---------|---------|
15 * | DL_WRITEV | port nr | proc nr | count | mode | address | |
16 * |------------|----------|---------|----------|---------|---------|---------|
17 * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
18 * |------------|----------|---------|----------|---------|---------|---------|
19 * | DL_READ | port nr | proc nr | count | | address | |
20 * |------------|----------|---------|----------|---------|---------|---------|
21 * | DL_READV | port nr | proc nr | count | | address | |
22 * |------------|----------|---------|----------|---------|---------|---------|
23 * | DL_READV_S | port nr | proc nr | count | | | grant |
24 * |------------|----------|---------|----------|---------|---------|---------|
25 * | DL_CONF | port nr | proc nr | | mode | address | |
26 * |------------|----------|---------|----------|---------|---------|---------|
27 * | DL_GETSTAT | port nr | proc nr | | | address | |
28 * |------------|----------|---------|----------|---------|---------|---------|
29 * |DL_GETSTAT_S| port nr | proc nr | | | | grant |
30 * |------------|----------|---------|----------|---------|---------|---------|
31 * | DL_STOP | port_nr | | | | | |
32 * |------------+----------+---------+----------+---------+---------+---------|
34 * The messages sent are:
36 * m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
37 * |-------------+----------+---------+----------+---------+---------|
38 * |DL_TASK_REPLY| port nr | proc nr | rd-count | err|stat| clock |
39 * |-------------+----------+---------+----------+---------+---------|
41 * m_type m3_i1 m3_i2 m3_ca1
42 * |-------------+---------+-----------+---------------|
43 * |DL_CONF_REPLY| port nr | last port | ethernet addr |
44 * |-------------+---------+-----------+---------------|
46 * m_type DL_PORT DL_STAT
47 * |------------|---------|-----------|
48 * |DL_STAT_REPL| port nr | err |
49 * |------------|---------|-----------|
52 * Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
55 #include "../drivers.h"
57 #include <stdlib.h>
58 #include <net/hton.h>
59 #include <net/gen/ether.h>
60 #include <net/gen/eth_io.h>
61 #include <ibm/pci.h>
62 #include <minix/ds.h>
63 #include <minix/endpoint.h>
65 #include <timers.h>
67 #define tmra_ut timer_t
68 #define tmra_inittimer(tp) tmr_inittimer(tp)
69 #define Proc_number(p) proc_number(p)
70 #define debug 0
71 #define RAND_UPDATE /**/
72 #define printW() ((void)0)
73 #define vm_1phys2bus(p) (p)
75 #include "assert.h"
76 #include "fxp.h"
77 #include "mii.h"
79 /* Number of receive buffers */
80 #define N_RX_BUF 40
82 /* Number of transmit buffers */
83 #define N_TX_BUF 4
85 /* I/O vectors are handled IOVEC_NR entries at a time. */
86 #define IOVEC_NR 16
88 /* Configuration */
89 #define FXP_ENVVAR "FXPETH"
91 struct pcitab
93 u16_t vid;
94 u16_t did;
95 int checkclass;
98 PRIVATE struct pcitab pcitab_fxp[]=
100 { 0x8086, 0x1229, 0 }, /* Intel 82557, etc. */
101 { 0x8086, 0x2449, 0 }, /* Intel 82801BA/BAM/CA/CAM */
102 { 0x8086, 0x103d, 0 }, /* Intel 82801DB */
103 { 0x8086, 0x1064, 0 }, /* Intel 82562 */
105 { 0x0000, 0x0000, 0 }
108 #define FXP_PORT_NR 1 /* Minix */
110 typedef int irq_hook_t;
112 static timer_t *fxp_timers= NULL;
113 static clock_t fxp_next_timeout= 0;
115 /* ignore interrupt for the moment */
116 #define interrupt(x) 0
118 union tmpbuf
120 char pad[4096];
121 struct cbl_conf cc;
122 struct ias ias;
123 } *tmpbufp;
125 typedef struct fxp
127 port_t fxp_base_port;
128 int fxp_mode;
129 int fxp_got_int;
130 int fxp_send_int;
131 int fxp_flags;
132 int fxp_client;
133 int fxp_features; /* Needed? */
134 int fxp_irq;
135 int fxp_type; /* What kind of hardware */
136 int fxp_ee_addrlen; /* #EEPROM address bits */
137 int fxp_tx_alive;
138 int fxp_need_reset;
140 /* Rx */
141 vir_bytes fxp_read_s;
142 int fxp_rx_nbuf;
143 int fxp_rx_bufsize;
144 struct rfd *fxp_rx_buf;
145 phys_bytes fxp_rx_busaddr;
146 int fxp_rx_head;
147 int fxp_rx_need_restart;
148 int fxp_need_conf; /* Re-configure after draining send
149 * queue
152 /* Tx */
153 int fxp_tx_nbuf;
154 int fxp_tx_bufsize;
155 struct tx *fxp_tx_buf;
156 phys_bytes fxp_tx_busaddr;
157 int fxp_tx_idle;
158 int fxp_tx_head;
159 int fxp_tx_tail;
160 int fxp_tx_threshold;
162 /* Link status */
163 int fxp_report_link;
164 int fxp_link_up;
165 int fxp_mii_busy;
166 u16_t fxp_mii_scr;
168 /* PCI related */
169 int fxp_seen; /* TRUE iff device available */
170 u8_t fxp_pcibus;
171 u8_t fxp_pcidev;
172 u8_t fxp_pcifunc;
174 /* 'large' items */
175 irq_hook_t fxp_hook;
176 ether_addr_t fxp_address;
177 message fxp_rx_mess;
178 message fxp_tx_mess;
179 struct sc fxp_stat;
180 u8_t fxp_conf_bytes[CC_BYTES_NR];
181 char fxp_name[sizeof("fxp#n")];
182 iovec_t fxp_iovec[IOVEC_NR];
183 iovec_s_t fxp_iovec_s[IOVEC_NR];
185 fxp_t;
187 /* fxp_mode */
188 #define FM_DISABLED 0x0
189 #define FM_ENABLED 0x1
191 /* fxp_flags */
192 #define FF_EMPTY 0x000
193 #define FF_PACK_SENT 0x001
194 #define FF_PACK_RECV 0x002
195 #define FF_SEND_AVAIL 0x004
196 #define FF_READING 0x010
197 #define FF_PROMISC 0x040
198 #define FF_MULTI 0x080
199 #define FF_BROAD 0x100
200 #define FF_ENABLED 0x200
202 /* fxp_features */
203 #define FFE_NONE 0x0
205 /* fxp_type */
206 #define FT_UNKNOWN 0x0
207 #define FT_82557 0x1
208 #define FT_82558A 0x2
209 #define FT_82559 0x4
210 #define FT_82801 0x8
212 static fxp_t *fxp_table;
213 phys_bytes fxp_table_phys;
215 static u16_t eth_ign_proto;
216 static tmra_ut fxp_watchdog;
217 static char *progname;
219 extern int errno;
221 u32_t system_hz;
223 #define fxp_inb(port, offset) (do_inb((port) + (offset)))
224 #define fxp_inw(port, offset) (do_inw((port) + (offset)))
225 #define fxp_inl(port, offset) (do_inl((port) + (offset)))
226 #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
227 #define fxp_outw(port, offset, value) (do_outw((port) + (offset), (value)))
228 #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
230 _PROTOTYPE( static void fxp_init, (message *mp) );
231 _PROTOTYPE( static void fxp_pci_conf, (void) );
232 _PROTOTYPE( static int fxp_probe, (fxp_t *fp) );
233 _PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp) );
234 _PROTOTYPE( static void fxp_init_hw, (fxp_t *fp) );
235 _PROTOTYPE( static void fxp_init_buf, (fxp_t *fp) );
236 _PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp) );
237 _PROTOTYPE( static void fxp_confaddr, (fxp_t *fp) );
238 _PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp) );
239 _PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
240 int vectored) );
241 _PROTOTYPE( static void fxp_writev_s, (message *mp, int from_int) );
242 _PROTOTYPE( static void fxp_readv, (message *mp, int from_int,
243 int vectored) );
244 _PROTOTYPE( static void fxp_readv_s, (message *mp, int from_int) );
245 _PROTOTYPE( static void fxp_do_conf, (fxp_t *fp) );
246 _PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
247 phys_bytes bus_addr, int check_idle) );
248 _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
249 phys_bytes bus_addr, int check_idle) );
250 _PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
251 _PROTOTYPE( static void fxp_getstat, (message *mp) );
252 _PROTOTYPE( static void fxp_getstat_s, (message *mp) );
253 _PROTOTYPE( static void fxp_getname, (message *mp) );
254 _PROTOTYPE( static int fxp_handler, (fxp_t *fp) );
255 _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) );
256 _PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp) );
257 _PROTOTYPE( static int fxp_link_changed, (fxp_t *fp) );
258 _PROTOTYPE( static void fxp_report_link, (fxp_t *fp) );
259 _PROTOTYPE( static void fxp_stop, (void));
260 _PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) );
261 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
262 _PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg) );
263 _PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
264 _PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) );
265 _PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,
266 tmr_func_t watchdog) );
267 _PROTOTYPE( static void fxp_expire_timers,(void) );
268 _PROTOTYPE( static u8_t do_inb, (port_t port) );
269 _PROTOTYPE( static u32_t do_inl, (port_t port) );
270 _PROTOTYPE( static void do_outb, (port_t port, u8_t v) );
271 _PROTOTYPE( static void do_outl, (port_t port, u32_t v) );
272 _PROTOTYPE( static void tell_dev, (vir_bytes start, size_t size,
273 int pci_bus, int pci_dev, int pci_func) );
275 PRIVATE void handle_hw_intr(void)
277 int i, r;
278 fxp_t *fp;
280 for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++) {
281 if (fp->fxp_mode != FM_ENABLED)
282 return;
283 fxp_handler(fp);
285 r= sys_irqenable(&fp->fxp_hook);
286 if (r != OK) {
287 panic("FXP", "unable enable interrupts", r);
290 if (!fp->fxp_got_int)
291 return;
292 fp->fxp_got_int= 0;
293 assert(fp->fxp_flags & FF_ENABLED);
294 fxp_check_ints(fp);
298 /* SEF functions and variables. */
299 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
300 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
301 EXTERN int env_argc;
302 EXTERN char **env_argv;
304 /*===========================================================================*
305 * main *
306 *===========================================================================*/
307 int main(int argc, char *argv[])
309 message m;
310 int r;
312 /* SEF local startup. */
313 env_setargs(argc, argv);
314 sef_local_startup();
316 while (TRUE)
318 if ((r= sef_receive(ANY, &m)) != OK)
319 panic("FXP","sef_receive failed", r);
321 if (is_notify(m.m_type)) {
322 switch (_ENDPOINT_P(m.m_source)) {
323 case HARDWARE:
324 handle_hw_intr();
325 break;
326 case PM_PROC_NR:
328 sigset_t set;
330 if (getsigset(&set) != 0) break;
332 if (sigismember(&set, SIGTERM))
333 fxp_stop();
335 break;
337 case CLOCK:
338 fxp_expire_timers();
339 break;
340 default:
341 panic("FXP"," illegal notify from", m.m_source);
344 /* get new message */
345 continue;
348 switch (m.m_type)
350 case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break;
351 case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break;
352 case DL_WRITEV_S: fxp_writev_s(&m, FALSE); break;
353 case DL_READ: fxp_readv(&m, FALSE, FALSE); break;
354 case DL_READV: fxp_readv(&m, FALSE, TRUE); break;
355 case DL_READV_S: fxp_readv_s(&m, FALSE); break;
356 case DL_CONF: fxp_init(&m); break;
357 case DL_GETSTAT: fxp_getstat(&m); break;
358 case DL_GETSTAT_S: fxp_getstat_s(&m); break;
359 case DL_GETNAME: fxp_getname(&m); break;
360 default:
361 panic("FXP"," illegal message", m.m_type);
366 /*===========================================================================*
367 * sef_local_startup *
368 *===========================================================================*/
369 PRIVATE void sef_local_startup()
371 /* Register init callbacks. */
372 sef_setcb_init_fresh(sef_cb_init_fresh);
373 sef_setcb_init_restart(sef_cb_init_fresh);
375 /* No live update support for now. */
377 /* Let SEF perform startup. */
378 sef_startup();
381 /*===========================================================================*
382 * sef_cb_init_fresh *
383 *===========================================================================*/
384 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
386 /* Initialize the fxp driver. */
387 int r;
388 u32_t tasknr;
389 long v;
390 vir_bytes ft;
392 ft = sizeof(*fxp_table)*FXP_PORT_NR;
393 system_hz = sys_hz();
395 if (env_argc < 1)
396 panic("FXP", "A head which at this time has no name", NO_NUM);
397 (progname=strrchr(env_argv[0],'/')) ? progname++
398 : (progname=env_argv[0]);
400 v= 0;
401 #if 0
402 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
403 #endif
404 eth_ign_proto= htons((u16_t) v);
406 if(!(fxp_table = alloc_contig(ft, 0, &fxp_table_phys)))
407 panic("FXP","couldn't allocate table", ENOMEM);
409 memset(fxp_table, 0, ft);
411 if((r=tsc_calibrate()) != OK)
412 panic("FXP","tsc_calibrate failed", r);
414 /* Try to notify inet that we are present (again) */
415 r= ds_retrieve_label_num("inet", &tasknr);
416 if (r == OK)
417 notify(tasknr);
418 else if (r != ESRCH)
419 printf("fxp: ds_retrieve_label_num failed for 'inet': %d\n", r);
421 return(OK);
424 /*===========================================================================*
425 * fxp_init *
426 *===========================================================================*/
427 static void fxp_init(mp)
428 message *mp;
430 static int first_time= 1;
432 int port;
433 fxp_t *fp;
434 message reply_mess;
436 if (first_time)
438 first_time= 0;
439 fxp_pci_conf(); /* Configure PCI devices. */
441 tmra_inittimer(&fxp_watchdog);
442 tmr_arg(&fxp_watchdog)->ta_int= 0;
443 fxp_set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f);
446 port = mp->DL_PORT;
447 if (port < 0 || port >= FXP_PORT_NR)
449 reply_mess.m_type= DL_CONF_REPLY;
450 reply_mess.m3_i1= ENXIO;
451 mess_reply(mp, &reply_mess);
452 return;
454 fp= &fxp_table[port];
455 if (fp->fxp_mode == FM_DISABLED)
457 /* This is the default, try to (re)locate the device. */
458 fxp_conf_hw(fp);
459 if (fp->fxp_mode == FM_DISABLED)
461 /* Probe failed, or the device is configured off. */
462 reply_mess.m_type= DL_CONF_REPLY;
463 reply_mess.m3_i1= ENXIO;
464 mess_reply(mp, &reply_mess);
465 return;
467 if (fp->fxp_mode == FM_ENABLED)
468 fxp_init_hw(fp);
469 fxp_report_link(fp);
472 assert(fp->fxp_mode == FM_ENABLED);
473 assert(fp->fxp_flags & FF_ENABLED);
475 fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
477 if (mp->DL_MODE & DL_PROMISC_REQ)
478 fp->fxp_flags |= FF_PROMISC;
479 if (mp->DL_MODE & DL_MULTI_REQ)
480 fp->fxp_flags |= FF_MULTI;
481 if (mp->DL_MODE & DL_BROAD_REQ)
482 fp->fxp_flags |= FF_BROAD;
484 fp->fxp_client = mp->m_source;
485 fxp_rec_mode(fp);
487 reply_mess.m_type = DL_CONF_REPLY;
488 reply_mess.m3_i1 = mp->DL_PORT;
489 reply_mess.m3_i2 = FXP_PORT_NR;
490 *(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
492 mess_reply(mp, &reply_mess);
495 /*===========================================================================*
496 * fxp_pci_conf *
497 *===========================================================================*/
498 static void fxp_pci_conf()
500 static char envvar[] = FXP_ENVVAR "#";
501 static char envfmt[] = "*:d.d.d";
503 int i, h;
504 fxp_t *fp;
505 long v;
507 for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
509 strcpy(fp->fxp_name, "fxp#0");
510 fp->fxp_name[4] += i;
511 fp->fxp_seen= FALSE;
512 fp->fxp_features= FFE_NONE;
513 envvar[sizeof(FXP_ENVVAR)-1]= '0'+i;
514 #if 0
515 if (getenv(envvar) != NULL)
517 if (strcmp(getenv(envvar), "off") == 0)
519 fp->fxp_pcibus= 255;
520 continue;
522 if (!env_prefix(envvar, "pci"))
523 env_panic(envvar);
525 #endif
527 v= 0;
528 #if 0
529 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
530 #endif
531 fp->fxp_pcibus= v;
532 v= 0;
533 #if 0
534 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
535 #endif
536 fp->fxp_pcidev= v;
537 v= 0;
538 #if 0
539 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
540 #endif
541 fp->fxp_pcifunc= v;
544 pci_init();
546 for (h= 1; h >= 0; h--) {
547 for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
549 if (fp->fxp_pcibus == 255)
550 continue;
551 if (((fp->fxp_pcibus | fp->fxp_pcidev |
552 fp->fxp_pcifunc) != 0) != h)
554 continue;
556 if (fxp_probe(fp))
557 fp->fxp_seen= TRUE;
562 /*===========================================================================*
563 * fxp_probe *
564 *===========================================================================*/
565 static int fxp_probe(fp)
566 fxp_t *fp;
568 int i, r, devind, just_one;
569 u16_t vid, did;
570 u32_t bar;
571 u8_t ilr, rev;
572 char *dname, *str;
574 if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)
576 /* Look for specific PCI device */
577 r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,
578 fp->fxp_pcifunc, &devind);
579 if (r == 0)
581 printf("%s: no PCI device found at %d.%d.%d\n",
582 fp->fxp_name, fp->fxp_pcibus,
583 fp->fxp_pcidev, fp->fxp_pcifunc);
584 return FALSE;
586 pci_ids(devind, &vid, &did);
587 just_one= TRUE;
589 else
591 r= pci_first_dev(&devind, &vid, &did);
592 if (r == 0)
593 return FALSE;
594 just_one= FALSE;
597 for(;;)
599 for (i= 0; pcitab_fxp[i].vid != 0; i++)
601 if (pcitab_fxp[i].vid != vid)
602 continue;
603 if (pcitab_fxp[i].did != did)
604 continue;
605 if (pcitab_fxp[i].checkclass)
607 panic("FXP","fxp_probe: class check not implemented",
608 NO_NUM);
610 break;
612 if (pcitab_fxp[i].vid != 0)
613 break;
615 if (just_one)
617 printf(
618 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
619 fp->fxp_name, vid, did,
620 fp->fxp_pcibus,
621 fp->fxp_pcidev, fp->fxp_pcifunc);
622 return FALSE;
625 r= pci_next_dev(&devind, &vid, &did);
626 if (!r)
627 return FALSE;
630 dname= pci_dev_name(vid, did);
631 #if VERBOSE
632 if (!dname)
633 dname= "unknown device";
634 printf("%s: %s (%04x/%04x) at %s\n",
635 fp->fxp_name, dname, vid, did, pci_slot_name(devind));
636 #endif
637 pci_reserve(devind);
639 bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
640 if (bar < 0x400)
642 panic("FXP","fxp_probe: base address is not properly configured",
643 NO_NUM);
645 fp->fxp_base_port= bar;
647 ilr= pci_attr_r8(devind, PCI_ILR);
648 fp->fxp_irq= ilr;
649 if (debug)
651 printf("%s: using I/O address 0x%lx, IRQ %d\n",
652 fp->fxp_name, (unsigned long)bar, ilr);
655 rev= pci_attr_r8(devind, PCI_REV);
656 str= NULL;
657 fp->fxp_type= FT_UNKNOWN;
658 switch(rev)
660 case FXP_REV_82557A: str= "82557A"; /* 0x01 */
661 fp->fxp_type= FT_82557;
662 break;
663 case FXP_REV_82557B: str= "82557B"; break; /* 0x02 */
664 case FXP_REV_82557C: str= "82557C"; break; /* 0x03 */
665 case FXP_REV_82558A: str= "82558A"; /* 0x04 */
666 fp->fxp_type= FT_82558A;
667 break;
668 case FXP_REV_82558B: str= "82558B"; break; /* 0x05 */
669 case FXP_REV_82559A: str= "82559A"; break; /* 0x06 */
670 case FXP_REV_82559B: str= "82559B"; break; /* 0x07 */
671 case FXP_REV_82559C: str= "82559C"; /* 0x08 */
672 fp->fxp_type= FT_82559;
673 break;
674 case FXP_REV_82559ERA: str= "82559ER-A"; /* 0x09 */
675 fp->fxp_type= FT_82559;
676 break;
677 case FXP_REV_82550_1: str= "82550(1)"; /* 0x0C */
678 fp->fxp_type= FT_82559;
679 break;
680 case FXP_REV_82550_2: str= "82550(2)"; /* 0x0D */
681 fp->fxp_type= FT_82559;
682 break;
683 case FXP_REV_82550_3: str= "82550(3)"; /* 0x0E */
684 fp->fxp_type= FT_82559;
685 break;
686 case FXP_REV_82551_1: str= "82551(1)"; /* 0x0F */
687 fp->fxp_type= FT_82559;
688 break;
689 case FXP_REV_82551_2: str= "82551(2)"; /* 0x10 */
690 fp->fxp_type= FT_82559;
691 break;
692 case FXP_REV_82801DB: str= "82801DB"; /* 0x81 */
693 fp->fxp_type= FT_82801;
694 break;
697 #if VERBOSE
698 if (str)
699 printf("%s: device revision: %s\n", fp->fxp_name, str);
700 else
701 printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
702 #endif
704 if (fp->fxp_type == FT_UNKNOWN)
706 printf("fxp_probe: device is not supported by this driver\n");
707 return FALSE;
710 return TRUE;
713 /*===========================================================================*
714 * fxp_conf_hw *
715 *===========================================================================*/
716 static void fxp_conf_hw(fp)
717 fxp_t *fp;
719 int i;
720 int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;
722 fp->fxp_mode= FM_DISABLED; /* Superfluous */
724 if (!fp->fxp_seen)
725 return;
727 /* PCI device is present */
728 fp->fxp_mode= FM_ENABLED;
730 fp->fxp_flags= FF_EMPTY;
731 fp->fxp_got_int= 0;
732 fp->fxp_send_int= 0;
733 fp->fxp_ee_addrlen= 0; /* Unknown */
734 fp->fxp_need_reset= 0;
735 fp->fxp_report_link= 0;
736 fp->fxp_link_up= -1; /* Unknown */
737 fp->fxp_mii_busy= 0;
738 fp->fxp_read_s= 0;
739 fp->fxp_rx_need_restart= 0;
740 fp->fxp_need_conf= 0;
741 fp->fxp_tx_head= 0;
742 fp->fxp_tx_tail= 0;
743 fp->fxp_tx_alive= 0;
744 fp->fxp_tx_threshold= TXTT_MIN;
746 /* Try to come up with a sensible configuration for the current
747 * device. Unfortunately every device is different, defaults are
748 * not always zero, and some fields are re-used with a completely
749 * different interpretation. We start out with a sensible default
750 * for all devices and then add device specific changes.
752 fp->fxp_conf_bytes[0]= CC_BYTES_NR;
753 fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
754 fp->fxp_conf_bytes[2]= CAI_DEFAULT;
755 fp->fxp_conf_bytes[3]= 0;
756 fp->fxp_conf_bytes[4]= 0;
757 fp->fxp_conf_bytes[5]= 0;
758 fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
759 fp->fxp_conf_bytes[7]= CUR_1;
760 fp->fxp_conf_bytes[8]= CCB8_503_MII;
761 fp->fxp_conf_bytes[9]= 0;
762 fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
763 CCB10_RES1;
764 fp->fxp_conf_bytes[11]= 0;
765 fp->fxp_conf_bytes[12]= CIS_DEFAULT;
766 fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
767 fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
768 fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
769 fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
770 fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
771 fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
772 fp->fxp_conf_bytes[19]= CCB19_FDPE;
773 fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
774 fp->fxp_conf_bytes[21]= CCB21_RES21;
776 #if VERBOSE
777 for (i= 0; i<CC_BYTES_NR; i++)
778 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
779 printf("\n");
780 #endif
782 mwi= 0; /* Do we want "Memory Write and Invalidate"? */
783 ext_stat1= 0; /* Do we want extended statistical counters? */
784 ext_stat2= 0; /* Do we want even more statistical counters? */
785 lim_fifo= 0; /* Limit number of frame in TX FIFO */
786 i82503= 0; /* Older 10 Mbps interface on the 82557 */
787 fc= 0; /* Flow control */
789 switch(fp->fxp_type)
791 case FT_82557:
792 if (i82503)
794 fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;
795 fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;
797 break;
798 case FT_82558A:
799 case FT_82559:
800 case FT_82801:
801 if (mwi)
802 fp->fxp_conf_bytes[3] |= CCB3_MWIE;
803 if (ext_stat1)
804 fp->fxp_conf_bytes[6] &= ~CCB6_ESC;
805 if (ext_stat2)
806 fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;
807 if (lim_fifo)
808 fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;
809 if (fc)
811 /* From FreeBSD driver */
812 fp->fxp_conf_bytes[16]= 0x1f;
813 fp->fxp_conf_bytes[17]= 0x01;
815 fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |
816 CCB19_FDRSTOFC;
819 fp->fxp_conf_bytes[18] |= CCB18_LROK;
821 if (fp->fxp_type == FT_82801)
823 fp->fxp_conf_bytes[6] = 0xba; /* ctrl 1 */
824 fp->fxp_conf_bytes[15] = 0x48; /* promiscuous */
825 fp->fxp_conf_bytes[21] = 0x05; /* mc_all */
827 break;
828 default:
829 panic("FXP","fxp_conf_hw: bad device type", fp->fxp_type);
832 #if VERBOSE
833 for (i= 0; i<CC_BYTES_NR; i++)
834 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
835 printf("\n");
836 #endif
839 /*===========================================================================*
840 * fxp_init_hw *
841 *===========================================================================*/
842 static void fxp_init_hw(fp)
843 fxp_t *fp;
845 int i, r, isr;
846 port_t port;
847 u32_t bus_addr;
849 port= fp->fxp_base_port;
851 fxp_init_buf(fp);
853 fp->fxp_flags = FF_EMPTY;
854 fp->fxp_flags |= FF_ENABLED;
856 /* Set the interrupt handler and policy. Do not automatically
857 * reenable interrupts. Return the IRQ line number on interrupts.
859 fp->fxp_hook = fp->fxp_irq;
860 r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
861 if (r != OK)
862 panic("FXP","sys_irqsetpolicy failed", r);
864 fxp_reset_hw(fp);
866 r= sys_irqenable(&fp->fxp_hook);
867 if (r != OK)
868 panic("FXP","sys_irqenable failed", r);
870 /* Reset PHY? */
872 fxp_do_conf(fp);
874 /* Set pointer to statistical counters */
875 r= sys_umap(SELF, VM_D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
876 &bus_addr);
877 if (r != OK)
878 panic("FXP","sys_umap failed", r);
879 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);
881 /* Ack previous interrupts */
882 isr= fxp_inb(port, SCB_INT_STAT);
883 fxp_outb(port, SCB_INT_STAT, isr);
885 /* Enable interrupts */
886 fxp_outb(port, SCB_INT_MASK, 0);
888 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
889 TRUE /* check idle */);
891 fxp_confaddr(fp);
892 if (debug)
894 printf("%s: Ethernet address ", fp->fxp_name);
895 for (i= 0; i < 6; i++)
897 printf("%x%c", fp->fxp_address.ea_addr[i],
898 i < 5 ? ':' : '\n');
903 /*===========================================================================*
904 * fxp_init_buf *
905 *===========================================================================*/
906 static void fxp_init_buf(fp)
907 fxp_t *fp;
909 size_t rx_totbufsize, tx_totbufsize, tot_bufsize, alloc_bufsize;
910 char *alloc_buf;
911 phys_bytes buf;
912 int i, r;
913 struct rfd *rfdp;
914 struct tx *txp;
915 phys_bytes ph;
917 fp->fxp_rx_nbuf= N_RX_BUF;
918 rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
919 fp->fxp_rx_bufsize= rx_totbufsize;
921 fp->fxp_tx_nbuf= N_TX_BUF;
922 tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
923 fp->fxp_tx_bufsize= tx_totbufsize;
925 tot_bufsize= sizeof(*tmpbufp) + tx_totbufsize + rx_totbufsize;
926 if (tot_bufsize % 4096)
927 tot_bufsize += 4096 - (tot_bufsize % 4096);
928 alloc_bufsize= tot_bufsize;
929 alloc_buf= alloc_contig(alloc_bufsize, AC_ALIGN4K, &ph);
930 if (alloc_buf == NULL)
932 panic(__FILE__, "fxp_init_buf: unable to alloc_contig size",
933 alloc_bufsize);
936 buf= (phys_bytes)alloc_buf;
938 tell_dev((vir_bytes)buf, tot_bufsize, 0, 0, 0);
940 tmpbufp= (union tmpbuf *)buf;
942 fp->fxp_rx_buf= (struct rfd *)&tmpbufp[1];
943 r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_rx_buf, rx_totbufsize,
944 &fp->fxp_rx_busaddr);
945 if (r != OK)
946 panic("FXP","sys_umap failed", r);
948 #if 0
949 printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n",
950 fp->fxp_rx_busaddr, fp->fxp_rx_buf);
951 #endif
953 for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
955 rfdp->rfd_status= 0;
956 rfdp->rfd_command= 0;
957 if (i != fp->fxp_rx_nbuf-1)
959 r= sys_umap(SELF, VM_D, (vir_bytes)&rfdp[1],
960 sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
961 if (r != OK)
962 panic("FXP","sys_umap failed", r);
964 else
966 rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
967 rfdp->rfd_command |= RFDC_EL;
969 rfdp->rfd_reserved= 0;
970 rfdp->rfd_res= 0;
971 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
974 fp->fxp_rx_head= 0;
976 fp->fxp_tx_buf= (struct tx *)((char *)fp->fxp_rx_buf+rx_totbufsize);
977 r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_tx_buf,
978 (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
979 if (r != OK)
980 panic("FXP","sys_umap failed", r);
982 for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
984 txp->tx_status= 0;
985 txp->tx_command= TXC_EL | CBL_NOP; /* Just in case */
986 if (i != fp->fxp_tx_nbuf-1)
988 r= sys_umap(SELF, VM_D, (vir_bytes)&txp[1],
989 (phys_bytes)sizeof(txp[1]),
990 &txp->tx_linkaddr);
991 if (r != OK)
992 panic("FXP","sys_umap failed", r);
994 else
996 txp->tx_linkaddr= fp->fxp_tx_busaddr;
998 txp->tx_tbda= TX_TBDA_NIL;
999 txp->tx_size= 0;
1000 txp->tx_tthresh= fp->fxp_tx_threshold;
1001 txp->tx_ntbd= 0;
1003 fp->fxp_tx_idle= 1;
1006 /*===========================================================================*
1007 * fxp_reset_hw *
1008 *===========================================================================*/
1009 static void fxp_reset_hw(fp)
1010 fxp_t *fp;
1012 /* Inline the function in init? */
1013 port_t port;
1015 port= fp->fxp_base_port;
1017 /* Reset device */
1018 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
1019 tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY));
1021 /* Disable interrupts */
1022 fxp_outb(port, SCB_INT_MASK, SIM_M);
1024 /* Set CU base to zero */
1025 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
1027 /* Set RU base to zero */
1028 fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
1031 /*===========================================================================*
1032 * fxp_confaddr *
1033 *===========================================================================*/
1034 static void fxp_confaddr(fp)
1035 fxp_t *fp;
1037 static char eakey[]= FXP_ENVVAR "#_EA";
1038 static char eafmt[]= "x:x:x:x:x:x";
1039 clock_t t0,t1;
1040 int i, r;
1041 port_t port;
1042 u32_t bus_addr;
1043 long v;
1045 port= fp->fxp_base_port;
1047 /* User defined ethernet address? */
1048 eakey[sizeof(FXP_ENVVAR)-1]= '0' + (fp-fxp_table);
1050 for (i= 0; i < 6; i++)
1052 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
1053 break;
1054 fp->fxp_address.ea_addr[i]= v;
1057 if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
1059 if (i == 0)
1061 /* Get ethernet address from EEPROM */
1062 for (i= 0; i<3; i++)
1064 v= eeprom_read(fp, i);
1065 fp->fxp_address.ea_addr[i*2]= (v & 0xff);
1066 fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
1070 /* Tell NIC about ethernet address */
1071 tmpbufp->ias.ias_status= 0;
1072 tmpbufp->ias.ias_command= CBL_C_EL | CBL_AIS;
1073 tmpbufp->ias.ias_linkaddr= 0;
1074 memcpy(tmpbufp->ias.ias_ethaddr, fp->fxp_address.ea_addr,
1075 sizeof(tmpbufp->ias.ias_ethaddr));
1076 r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->ias,
1077 (phys_bytes)sizeof(tmpbufp->ias), &bus_addr);
1078 if (r != OK)
1079 panic("FXP","sys_umap failed", r);
1081 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
1083 getuptime(&t0);
1084 do {
1085 /* Wait for CU command to complete */
1086 if (tmpbufp->ias.ias_status & CBL_F_C)
1087 break;
1088 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
1090 if (!(tmpbufp->ias.ias_status & CBL_F_C))
1091 panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);
1092 if (!(tmpbufp->ias.ias_status & CBL_F_OK))
1093 panic("FXP","fxp_confaddr: CU command failed", NO_NUM);
1095 #if VERBOSE
1096 printf("%s: hardware ethernet address: ", fp->fxp_name);
1097 for (i= 0; i<6; i++)
1099 printf("%02x%s", fp->fxp_address.ea_addr[i],
1100 i < 5 ? ":" : "");
1102 printf("\n");
1103 #endif
1106 /*===========================================================================*
1107 * fxp_rec_mode *
1108 *===========================================================================*/
1109 static void fxp_rec_mode(fp)
1110 fxp_t *fp;
1112 fp->fxp_conf_bytes[0]= CC_BYTES_NR; /* Just to be sure */
1113 fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
1114 fp->fxp_conf_bytes[21] &= ~CCB21_MA;
1116 if (fp->fxp_flags & FF_PROMISC)
1117 fp->fxp_conf_bytes[15] |= CCB15_PM;
1118 if (fp->fxp_flags & FF_MULTI)
1119 fp->fxp_conf_bytes[21] |= CCB21_MA;
1121 if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
1122 fp->fxp_conf_bytes[15] |= CCB15_BD;
1124 /* Queue request if not idle */
1125 if (fp->fxp_tx_idle)
1127 fxp_do_conf(fp);
1129 else
1131 printf("fxp_rec_mode: setting fxp_need_conf\n");
1132 fp->fxp_need_conf= TRUE;
1136 /*===========================================================================*
1137 * fxp_writev *
1138 *===========================================================================*/
1139 static void fxp_writev(mp, from_int, vectored)
1140 message *mp;
1141 int from_int;
1142 int vectored;
1144 vir_bytes iov_src;
1145 int i, j, n, o, r, s, dl_port, count, size, prev_head;
1146 int fxp_client, fxp_tx_nbuf, fxp_tx_head;
1147 u16_t tx_command;
1148 fxp_t *fp;
1149 iovec_t *iovp;
1150 struct tx *txp, *prev_txp;
1152 dl_port = mp->DL_PORT;
1153 count = mp->DL_COUNT;
1154 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1155 panic("FXP","fxp_writev: illegal port", dl_port);
1156 fp= &fxp_table[dl_port];
1157 fxp_client= mp->DL_PROC;
1158 fp->fxp_client= fxp_client;
1160 assert(fp->fxp_mode == FM_ENABLED);
1161 assert(fp->fxp_flags & FF_ENABLED);
1163 if (from_int)
1165 assert(fp->fxp_flags & FF_SEND_AVAIL);
1166 fp->fxp_flags &= ~FF_SEND_AVAIL;
1167 fp->fxp_tx_alive= TRUE;
1170 if (fp->fxp_tx_idle)
1172 txp= fp->fxp_tx_buf;
1173 fxp_tx_head= 0; /* lint */
1174 prev_txp= NULL; /* lint */
1176 else
1178 fxp_tx_nbuf= fp->fxp_tx_nbuf;
1179 prev_head= fp->fxp_tx_head;
1180 fxp_tx_head= prev_head+1;
1181 if (fxp_tx_head == fxp_tx_nbuf)
1182 fxp_tx_head= 0;
1183 assert(fxp_tx_head < fxp_tx_nbuf);
1185 if (fxp_tx_head == fp->fxp_tx_tail)
1187 /* Send queue is full */
1188 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1189 fp->fxp_flags |= FF_SEND_AVAIL;
1190 goto suspend;
1193 prev_txp= &fp->fxp_tx_buf[prev_head];
1194 txp= &fp->fxp_tx_buf[fxp_tx_head];
1197 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1198 assert(!(fp->fxp_flags & FF_PACK_SENT));
1200 if (vectored)
1203 iov_src = (vir_bytes)mp->DL_ADDR;
1205 size= 0;
1206 o= 0;
1207 for (i= 0; i<count; i += IOVEC_NR,
1208 iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
1210 n= IOVEC_NR;
1211 if (i+n > count)
1212 n= count-i;
1213 r= sys_vircopy(fxp_client, D, iov_src,
1214 SELF, D, (vir_bytes)fp->fxp_iovec,
1215 n * sizeof(fp->fxp_iovec[0]));
1216 if (r != OK)
1217 panic("FXP","fxp_writev: sys_vircopy failed", r);
1219 for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
1221 s= iovp->iov_size;
1222 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
1224 panic("FXP","fxp_writev: invalid packet size",
1225 NO_NUM);
1228 r= sys_vircopy(fxp_client, D, iovp->iov_addr,
1229 SELF, D, (vir_bytes)(txp->tx_buf+o),
1231 if (r != OK)
1233 panic("FXP","fxp_writev: sys_vircopy failed",
1236 size += s;
1237 o += s;
1240 if (size < ETH_MIN_PACK_SIZE)
1241 panic("FXP","fxp_writev: invalid packet size", size);
1243 else
1245 size= mp->DL_COUNT;
1246 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
1247 panic("FXP","fxp_writev: invalid packet size", size);
1249 r= sys_vircopy(fxp_client, D, (vir_bytes)mp->DL_ADDR,
1250 SELF, D, (vir_bytes)txp->tx_buf, size);
1251 if (r != OK)
1252 panic("FXP","fxp_writev: sys_vircopy failed", r);
1255 txp->tx_status= 0;
1256 txp->tx_command= TXC_EL | CBL_XMIT;
1257 txp->tx_tbda= TX_TBDA_NIL;
1258 txp->tx_size= TXSZ_EOF | size;
1259 txp->tx_tthresh= fp->fxp_tx_threshold;
1260 txp->tx_ntbd= 0;
1261 if (fp->fxp_tx_idle)
1263 fp->fxp_tx_idle= 0;
1264 fp->fxp_tx_head= fp->fxp_tx_tail= 0;
1266 fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
1267 TRUE /* check idle */);
1269 else
1271 /* Link new request in transmit list */
1272 tx_command= prev_txp->tx_command;
1273 assert(tx_command == (TXC_EL | CBL_XMIT));
1274 prev_txp->tx_command= CBL_XMIT;
1275 fp->fxp_tx_head= fxp_tx_head;
1278 fp->fxp_flags |= FF_PACK_SENT;
1280 /* If the interrupt handler called, don't send a reply. The reply
1281 * will be sent after all interrupts are handled.
1283 if (from_int)
1284 return;
1285 reply(fp, OK, FALSE);
1286 return;
1288 suspend:
1289 if (from_int)
1290 panic("FXP","fxp: should not be sending\n", NO_NUM);
1292 fp->fxp_tx_mess= *mp;
1293 reply(fp, OK, FALSE);
1296 /*===========================================================================*
1297 * fxp_writev_s *
1298 *===========================================================================*/
1299 static void fxp_writev_s(mp, from_int)
1300 message *mp;
1301 int from_int;
1303 cp_grant_id_t iov_grant;
1304 vir_bytes iov_offset;
1305 int i, j, n, o, r, s, dl_port, count, size, prev_head;
1306 int fxp_client, fxp_tx_nbuf, fxp_tx_head;
1307 u16_t tx_command;
1308 fxp_t *fp;
1309 iovec_s_t *iovp;
1310 struct tx *txp, *prev_txp;
1312 dl_port = mp->DL_PORT;
1313 count = mp->DL_COUNT;
1314 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1315 panic("FXP","fxp_writev: illegal port", dl_port);
1316 fp= &fxp_table[dl_port];
1317 fxp_client= mp->DL_PROC;
1318 fp->fxp_client= fxp_client;
1320 assert(fp->fxp_mode == FM_ENABLED);
1321 assert(fp->fxp_flags & FF_ENABLED);
1323 if (from_int)
1325 assert(fp->fxp_flags & FF_SEND_AVAIL);
1326 fp->fxp_flags &= ~FF_SEND_AVAIL;
1327 fp->fxp_tx_alive= TRUE;
1330 if (fp->fxp_tx_idle)
1332 txp= fp->fxp_tx_buf;
1333 fxp_tx_head= 0; /* lint */
1334 prev_txp= NULL; /* lint */
1336 else
1338 fxp_tx_nbuf= fp->fxp_tx_nbuf;
1339 prev_head= fp->fxp_tx_head;
1340 fxp_tx_head= prev_head+1;
1341 if (fxp_tx_head == fxp_tx_nbuf)
1342 fxp_tx_head= 0;
1343 assert(fxp_tx_head < fxp_tx_nbuf);
1345 if (fxp_tx_head == fp->fxp_tx_tail)
1347 /* Send queue is full */
1348 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1349 fp->fxp_flags |= FF_SEND_AVAIL;
1350 goto suspend;
1353 prev_txp= &fp->fxp_tx_buf[prev_head];
1354 txp= &fp->fxp_tx_buf[fxp_tx_head];
1357 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1358 assert(!(fp->fxp_flags & FF_PACK_SENT));
1360 iov_grant= mp->DL_GRANT;
1362 size= 0;
1363 o= 0;
1364 iov_offset= 0;
1365 for (i= 0; i<count; i += IOVEC_NR,
1366 iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
1368 n= IOVEC_NR;
1369 if (i+n > count)
1370 n= count-i;
1371 r= sys_safecopyfrom(fxp_client, iov_grant, iov_offset,
1372 (vir_bytes)fp->fxp_iovec_s,
1373 n * sizeof(fp->fxp_iovec_s[0]), D);
1374 if (r != OK)
1375 panic("FXP","fxp_writev: sys_safecopyfrom failed", r);
1377 for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
1379 s= iovp->iov_size;
1380 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
1382 panic("FXP","fxp_writev: invalid packet size",
1383 size + s);
1386 r= sys_safecopyfrom(fxp_client, iovp->iov_grant,
1387 0, (vir_bytes)(txp->tx_buf+o), s, D);
1388 if (r != OK)
1390 panic("FXP",
1391 "fxp_writev_s: sys_safecopyfrom failed",
1394 size += s;
1395 o += s;
1398 if (size < ETH_MIN_PACK_SIZE)
1399 panic("FXP","fxp_writev: invalid packet size", size);
1401 txp->tx_status= 0;
1402 txp->tx_command= TXC_EL | CBL_XMIT;
1403 txp->tx_tbda= TX_TBDA_NIL;
1404 txp->tx_size= TXSZ_EOF | size;
1405 txp->tx_tthresh= fp->fxp_tx_threshold;
1406 txp->tx_ntbd= 0;
1407 if (fp->fxp_tx_idle)
1409 fp->fxp_tx_idle= 0;
1410 fp->fxp_tx_head= fp->fxp_tx_tail= 0;
1412 fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
1413 TRUE /* check idle */);
1415 else
1417 /* Link new request in transmit list */
1418 tx_command= prev_txp->tx_command;
1419 assert(tx_command == (TXC_EL | CBL_XMIT));
1420 prev_txp->tx_command= CBL_XMIT;
1421 fp->fxp_tx_head= fxp_tx_head;
1424 fp->fxp_flags |= FF_PACK_SENT;
1426 /* If the interrupt handler called, don't send a reply. The reply
1427 * will be sent after all interrupts are handled.
1429 if (from_int)
1430 return;
1431 reply(fp, OK, FALSE);
1432 return;
1434 suspend:
1435 if (from_int)
1436 panic("FXP","fxp: should not be sending\n", NO_NUM);
1438 fp->fxp_tx_mess= *mp;
1439 reply(fp, OK, FALSE);
1442 /*===========================================================================*
1443 * fxp_readv *
1444 *===========================================================================*/
1445 static void fxp_readv(mp, from_int, vectored)
1446 message *mp;
1447 int from_int;
1448 int vectored;
1450 int i, j, n, o, r, s, dl_port, fxp_client, count, size,
1451 fxp_rx_head, fxp_rx_nbuf;
1452 port_t port;
1453 unsigned packlen;
1454 vir_bytes iov_src;
1455 u16_t rfd_status;
1456 u16_t rfd_res;
1457 u8_t scb_status;
1458 fxp_t *fp;
1459 iovec_t *iovp;
1460 struct rfd *rfdp, *prev_rfdp;
1462 dl_port = mp->DL_PORT;
1463 count = mp->DL_COUNT;
1464 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1465 panic("FXP","fxp_readv: illegal port", dl_port);
1466 fp= &fxp_table[dl_port];
1467 fxp_client= mp->DL_PROC;
1468 fp->fxp_client= fxp_client;
1470 assert(fp->fxp_mode == FM_ENABLED);
1471 assert(fp->fxp_flags & FF_ENABLED);
1473 port= fp->fxp_base_port;
1475 fxp_rx_head= fp->fxp_rx_head;
1476 rfdp= &fp->fxp_rx_buf[fxp_rx_head];
1478 rfd_status= rfdp->rfd_status;
1479 if (!(rfd_status & RFDS_C))
1481 /* Receive buffer is empty, suspend */
1482 goto suspend;
1485 if (!rfd_status & RFDS_OK)
1487 /* Not OK? What happened? */
1488 assert(0);
1490 else
1492 assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
1493 RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
1494 RFDS_RXERR)));
1496 rfd_res= rfdp->rfd_res;
1497 assert(rfd_res & RFDR_EOF);
1498 assert(rfd_res & RFDR_F);
1500 packlen= rfd_res & RFDSZ_SIZE;
1502 if (vectored)
1504 iov_src = (vir_bytes)mp->DL_ADDR;
1506 size= 0;
1507 o= 0;
1508 for (i= 0; i<count; i += IOVEC_NR,
1509 iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
1511 n= IOVEC_NR;
1512 if (i+n > count)
1513 n= count-i;
1514 r= sys_vircopy(fxp_client, D, iov_src,
1515 SELF, D, (vir_bytes)fp->fxp_iovec,
1516 n * sizeof(fp->fxp_iovec[0]));
1517 if (r != OK)
1518 panic("FXP","fxp_readv: sys_vircopy failed", r);
1520 for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
1522 s= iovp->iov_size;
1523 if (size + s > packlen)
1525 assert(packlen > size);
1526 s= packlen-size;
1529 r= sys_vircopy(SELF, D,
1530 (vir_bytes)(rfdp->rfd_buf+o),
1531 fxp_client, D, iovp->iov_addr, s);
1532 if (r != OK)
1534 panic("FXP","fxp_readv: sys_vircopy failed",
1538 size += s;
1539 if (size == packlen)
1540 break;
1541 o += s;
1543 if (size == packlen)
1544 break;
1546 if (size < packlen)
1548 assert(0);
1551 else
1553 assert(0);
1556 fp->fxp_read_s= packlen;
1557 fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
1559 /* Re-init the current buffer */
1560 rfdp->rfd_status= 0;
1561 rfdp->rfd_command= RFDC_EL;
1562 rfdp->rfd_reserved= 0;
1563 rfdp->rfd_res= 0;
1564 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1566 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1567 if (fxp_rx_head == 0)
1569 prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
1571 else
1572 prev_rfdp= &rfdp[-1];
1574 assert(prev_rfdp->rfd_command & RFDC_EL);
1575 prev_rfdp->rfd_command &= ~RFDC_EL;
1577 fxp_rx_head++;
1578 if (fxp_rx_head == fxp_rx_nbuf)
1579 fxp_rx_head= 0;
1580 assert(fxp_rx_head < fxp_rx_nbuf);
1581 fp->fxp_rx_head= fxp_rx_head;
1583 if (!from_int)
1584 reply(fp, OK, FALSE);
1586 return;
1588 suspend:
1589 if (fp->fxp_rx_need_restart)
1591 fp->fxp_rx_need_restart= 0;
1593 /* Check the status of the RU */
1594 scb_status= fxp_inb(port, SCB_STATUS);
1595 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
1597 /* Race condition? */
1598 printf("fxp_readv: restart race: 0x%x\n",
1599 scb_status);
1600 assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
1602 else
1604 fxp_restart_ru(fp);
1607 if (from_int)
1609 assert(fp->fxp_flags & FF_READING);
1611 /* No need to store any state */
1612 return;
1615 fp->fxp_rx_mess= *mp;
1616 assert(!(fp->fxp_flags & FF_READING));
1617 fp->fxp_flags |= FF_READING;
1619 reply(fp, OK, FALSE);
1622 /*===========================================================================*
1623 * fxp_readv_s *
1624 *===========================================================================*/
1625 static void fxp_readv_s(mp, from_int)
1626 message *mp;
1627 int from_int;
1629 int i, j, n, o, r, s, dl_port, fxp_client, count, size,
1630 fxp_rx_head, fxp_rx_nbuf;
1631 cp_grant_id_t iov_grant;
1632 port_t port;
1633 unsigned packlen;
1634 vir_bytes iov_offset;
1635 u16_t rfd_status;
1636 u16_t rfd_res;
1637 u8_t scb_status;
1638 fxp_t *fp;
1639 iovec_s_t *iovp;
1640 struct rfd *rfdp, *prev_rfdp;
1642 dl_port = mp->DL_PORT;
1643 count = mp->DL_COUNT;
1644 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1645 panic("FXP","fxp_readv: illegal port", dl_port);
1646 fp= &fxp_table[dl_port];
1647 fxp_client= mp->DL_PROC;
1648 fp->fxp_client= fxp_client;
1650 assert(fp->fxp_mode == FM_ENABLED);
1651 assert(fp->fxp_flags & FF_ENABLED);
1653 port= fp->fxp_base_port;
1655 fxp_rx_head= fp->fxp_rx_head;
1656 rfdp= &fp->fxp_rx_buf[fxp_rx_head];
1658 rfd_status= rfdp->rfd_status;
1659 if (!(rfd_status & RFDS_C))
1661 /* Receive buffer is empty, suspend */
1662 goto suspend;
1665 if (!rfd_status & RFDS_OK)
1667 /* Not OK? What happened? */
1668 assert(0);
1670 else
1672 assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
1673 RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
1674 RFDS_RXERR)));
1676 rfd_res= rfdp->rfd_res;
1677 assert(rfd_res & RFDR_EOF);
1678 assert(rfd_res & RFDR_F);
1680 packlen= rfd_res & RFDSZ_SIZE;
1682 iov_grant = mp->DL_GRANT;
1684 size= 0;
1685 o= 0;
1686 iov_offset= 0;
1687 for (i= 0; i<count; i += IOVEC_NR,
1688 iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
1690 n= IOVEC_NR;
1691 if (i+n > count)
1692 n= count-i;
1693 r= sys_safecopyfrom(fxp_client, iov_grant, iov_offset,
1694 (vir_bytes)fp->fxp_iovec_s,
1695 n * sizeof(fp->fxp_iovec_s[0]), D);
1696 if (r != OK)
1697 panic("FXP","fxp_readv_s: sys_safecopyfrom failed", r);
1699 for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
1701 s= iovp->iov_size;
1702 if (size + s > packlen)
1704 assert(packlen > size);
1705 s= packlen-size;
1708 r= sys_safecopyto(fxp_client, iovp->iov_grant,
1709 0, (vir_bytes)(rfdp->rfd_buf+o), s, D);
1710 if (r != OK)
1712 panic("FXP","fxp_readv: sys_safecopyto failed",
1716 size += s;
1717 if (size == packlen)
1718 break;
1719 o += s;
1721 if (size == packlen)
1722 break;
1724 if (size < packlen)
1726 assert(0);
1729 fp->fxp_read_s= packlen;
1730 fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
1732 /* Re-init the current buffer */
1733 rfdp->rfd_status= 0;
1734 rfdp->rfd_command= RFDC_EL;
1735 rfdp->rfd_reserved= 0;
1736 rfdp->rfd_res= 0;
1737 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1739 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1740 if (fxp_rx_head == 0)
1742 prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
1744 else
1745 prev_rfdp= &rfdp[-1];
1747 assert(prev_rfdp->rfd_command & RFDC_EL);
1748 prev_rfdp->rfd_command &= ~RFDC_EL;
1750 fxp_rx_head++;
1751 if (fxp_rx_head == fxp_rx_nbuf)
1752 fxp_rx_head= 0;
1753 assert(fxp_rx_head < fxp_rx_nbuf);
1754 fp->fxp_rx_head= fxp_rx_head;
1756 if (!from_int)
1757 reply(fp, OK, FALSE);
1759 return;
1761 suspend:
1762 if (fp->fxp_rx_need_restart)
1764 fp->fxp_rx_need_restart= 0;
1766 /* Check the status of the RU */
1767 scb_status= fxp_inb(port, SCB_STATUS);
1768 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
1770 /* Race condition? */
1771 printf("fxp_readv: restart race: 0x%x\n",
1772 scb_status);
1773 assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
1775 else
1777 fxp_restart_ru(fp);
1780 if (from_int)
1782 assert(fp->fxp_flags & FF_READING);
1784 /* No need to store any state */
1785 return;
1788 fp->fxp_rx_mess= *mp;
1789 assert(!(fp->fxp_flags & FF_READING));
1790 fp->fxp_flags |= FF_READING;
1792 reply(fp, OK, FALSE);
1795 /*===========================================================================*
1796 * fxp_do_conf *
1797 *===========================================================================*/
1798 static void fxp_do_conf(fp)
1799 fxp_t *fp;
1801 int r;
1802 u32_t bus_addr;
1803 clock_t t0,t1;
1805 /* Configure device */
1806 tmpbufp->cc.cc_status= 0;
1807 tmpbufp->cc.cc_command= CBL_C_EL | CBL_CONF;
1808 tmpbufp->cc.cc_linkaddr= 0;
1809 memcpy(tmpbufp->cc.cc_bytes, fp->fxp_conf_bytes,
1810 sizeof(tmpbufp->cc.cc_bytes));
1812 r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->cc,
1813 (phys_bytes)sizeof(tmpbufp->cc), &bus_addr);
1814 if (r != OK)
1815 panic("FXP","sys_umap failed", r);
1817 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
1819 getuptime(&t0);
1820 do {
1821 /* Wait for CU command to complete */
1822 if (tmpbufp->cc.cc_status & CBL_F_C)
1823 break;
1824 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
1826 if (!(tmpbufp->cc.cc_status & CBL_F_C))
1827 panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);
1828 if (!(tmpbufp->cc.cc_status & CBL_F_OK))
1829 panic("FXP","fxp_do_conf: CU command failed", NO_NUM);
1833 /*===========================================================================*
1834 * fxp_cu_ptr_cmd *
1835 *===========================================================================*/
1836 static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
1837 fxp_t *fp;
1838 int cmd;
1839 phys_bytes bus_addr;
1840 int check_idle;
1842 clock_t t0,t1;
1843 port_t port;
1844 u8_t scb_cmd;
1846 port= fp->fxp_base_port;
1848 if (check_idle)
1850 /* Consistency check. Make sure that CU is idle */
1851 if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
1852 panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM);
1855 fxp_outl(port, SCB_POINTER, bus_addr);
1856 fxp_outb(port, SCB_CMD, cmd);
1858 /* What is a reasonable time-out? There is nothing in the
1859 * documentation. 1 ms should be enough.
1861 getuptime(&t0);
1862 do {
1863 /* Wait for CU command to be accepted */
1864 scb_cmd= fxp_inb(port, SCB_CMD);
1865 if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
1866 break;
1867 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
1869 if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
1870 panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);
1873 /*===========================================================================*
1874 * fxp_ru_ptr_cmd *
1875 *===========================================================================*/
1876 static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
1877 fxp_t *fp;
1878 int cmd;
1879 phys_bytes bus_addr;
1880 int check_idle;
1882 clock_t t0,t1;
1883 port_t port;
1884 u8_t scb_cmd;
1886 port= fp->fxp_base_port;
1888 if (check_idle)
1890 /* Consistency check, make sure that RU is idle */
1891 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
1892 panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM);
1895 fxp_outl(port, SCB_POINTER, bus_addr);
1896 fxp_outb(port, SCB_CMD, cmd);
1898 getuptime(&t0);
1899 do {
1900 /* Wait for RU command to be accepted */
1901 scb_cmd= fxp_inb(port, SCB_CMD);
1902 if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
1903 break;
1904 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
1906 if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
1907 panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);
1910 /*===========================================================================*
1911 * fxp_restart_ru *
1912 *===========================================================================*/
1913 static void fxp_restart_ru(fp)
1914 fxp_t *fp;
1916 int i, fxp_rx_nbuf;
1917 port_t port;
1918 struct rfd *rfdp;
1920 port= fp->fxp_base_port;
1922 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1923 for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
1925 rfdp->rfd_status= 0;
1926 rfdp->rfd_command= 0;
1927 if (i == fp->fxp_rx_nbuf-1)
1928 rfdp->rfd_command= RFDC_EL;
1929 rfdp->rfd_reserved= 0;
1930 rfdp->rfd_res= 0;
1931 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1933 fp->fxp_rx_head= 0;
1935 /* Make sure that RU is in the 'No resources' state */
1936 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
1937 panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM);
1939 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
1940 FALSE /* do not check idle */);
1943 /*===========================================================================*
1944 * fxp_getstat *
1945 *===========================================================================*/
1946 static void fxp_getstat(mp)
1947 message *mp;
1949 clock_t t0,t1;
1950 int r, dl_port;
1951 port_t port;
1952 fxp_t *fp;
1953 u32_t *p;
1954 eth_stat_t stats;
1956 dl_port = mp->DL_PORT;
1957 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1958 panic("FXP","fxp_getstat: illegal port", dl_port);
1959 fp= &fxp_table[dl_port];
1960 fp->fxp_client= mp->DL_PROC;
1962 assert(fp->fxp_mode == FM_ENABLED);
1963 assert(fp->fxp_flags & FF_ENABLED);
1965 port= fp->fxp_base_port;
1967 p= &fp->fxp_stat.sc_tx_fcp;
1968 *p= 0;
1970 /* The dump commmand doesn't take a pointer. Setting a pointer
1971 * doesn't hard though.
1973 fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
1975 getuptime(&t0);
1976 do {
1977 /* Wait for CU command to complete */
1978 if (*p != 0)
1979 break;
1980 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
1982 if (*p == 0)
1983 panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
1984 if (*p != SCM_DSC)
1985 panic("FXP","fxp_getstat: bad magic", NO_NUM);
1987 stats.ets_recvErr=
1988 fp->fxp_stat.sc_rx_crc +
1989 fp->fxp_stat.sc_rx_align +
1990 fp->fxp_stat.sc_rx_resource +
1991 fp->fxp_stat.sc_rx_overrun +
1992 fp->fxp_stat.sc_rx_cd +
1993 fp->fxp_stat.sc_rx_short;
1994 stats.ets_sendErr=
1995 fp->fxp_stat.sc_tx_maxcol +
1996 fp->fxp_stat.sc_tx_latecol +
1997 fp->fxp_stat.sc_tx_crs;
1998 stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
1999 stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
2000 stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
2001 stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
2002 stats.ets_packetR= fp->fxp_stat.sc_rx_good;
2003 stats.ets_packetT= fp->fxp_stat.sc_tx_good;
2004 stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
2005 stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
2006 stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
2007 stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
2008 stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
2009 stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
2010 stats.ets_CDheartbeat= 0;
2011 stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
2013 r= sys_vircopy(SELF, D, (vir_bytes)&stats,
2014 mp->DL_PROC, D, (vir_bytes) mp->DL_ADDR, sizeof(stats));
2015 if (r != OK)
2016 panic(__FILE__,"fxp_getstat: sys_vircopy failed", r);
2018 mp->m_type= DL_STAT_REPLY;
2019 mp->DL_PORT= dl_port;
2020 mp->DL_STAT= OK;
2021 r= send(mp->m_source, mp);
2022 if (r != OK)
2023 panic(__FILE__, "fxp_getstat: send failed: %d\n", r);
2027 /*===========================================================================*
2028 * fxp_getstat_s *
2029 *===========================================================================*/
2030 static void fxp_getstat_s(mp)
2031 message *mp;
2033 clock_t t0,t1;
2034 int r, dl_port;
2035 port_t port;
2036 fxp_t *fp;
2037 u32_t *p;
2038 eth_stat_t stats;
2040 dl_port = mp->DL_PORT;
2041 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
2042 panic("FXP","fxp_getstat: illegal port", dl_port);
2043 fp= &fxp_table[dl_port];
2044 fp->fxp_client= mp->DL_PROC;
2046 assert(fp->fxp_mode == FM_ENABLED);
2047 assert(fp->fxp_flags & FF_ENABLED);
2049 port= fp->fxp_base_port;
2051 p= &fp->fxp_stat.sc_tx_fcp;
2052 *p= 0;
2054 /* The dump commmand doesn't take a pointer. Setting a pointer
2055 * doesn't hurt though.
2057 fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
2059 getuptime(&t0);
2060 do {
2061 /* Wait for CU command to complete */
2062 if (*p != 0)
2063 break;
2064 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(1000));
2066 if (*p == 0)
2067 panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
2068 if (*p != SCM_DSC)
2069 panic("FXP","fxp_getstat: bad magic", NO_NUM);
2071 stats.ets_recvErr=
2072 fp->fxp_stat.sc_rx_crc +
2073 fp->fxp_stat.sc_rx_align +
2074 fp->fxp_stat.sc_rx_resource +
2075 fp->fxp_stat.sc_rx_overrun +
2076 fp->fxp_stat.sc_rx_cd +
2077 fp->fxp_stat.sc_rx_short;
2078 stats.ets_sendErr=
2079 fp->fxp_stat.sc_tx_maxcol +
2080 fp->fxp_stat.sc_tx_latecol +
2081 fp->fxp_stat.sc_tx_crs;
2082 stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
2083 stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
2084 stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
2085 stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
2086 stats.ets_packetR= fp->fxp_stat.sc_rx_good;
2087 stats.ets_packetT= fp->fxp_stat.sc_tx_good;
2088 stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
2089 stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
2090 stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
2091 stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
2092 stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
2093 stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
2094 stats.ets_CDheartbeat= 0;
2095 stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
2097 r= sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, (vir_bytes)&stats,
2098 sizeof(stats), D);
2099 if (r != OK)
2100 panic(__FILE__,"fxp_getstat_s: sys_safecopyto failed", r);
2102 mp->m_type= DL_STAT_REPLY;
2103 mp->DL_PORT= dl_port;
2104 mp->DL_STAT= OK;
2105 r= send(mp->m_source, mp);
2106 if (r != OK)
2107 panic(__FILE__, "fxp_getstat_s: send failed: %d\n", r);
2111 /*===========================================================================*
2112 * fxp_getname *
2113 *===========================================================================*/
2114 static void fxp_getname(mp)
2115 message *mp;
2117 int r;
2119 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
2120 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
2121 mp->m_type= DL_NAME_REPLY;
2122 r= send(mp->m_source, mp);
2123 if (r != OK)
2124 panic("FXP", "fxp_getname: send failed", r);
2127 /*===========================================================================*
2128 * fxp_handler *
2129 *===========================================================================*/
2130 static int fxp_handler(fp)
2131 fxp_t *fp;
2133 int port;
2134 u16_t isr;
2136 RAND_UPDATE
2138 port= fp->fxp_base_port;
2140 /* Ack interrupt */
2141 isr= fxp_inb(port, SCB_INT_STAT);
2142 fxp_outb(port, SCB_INT_STAT, isr);
2144 if (isr & SIS_FR)
2146 isr &= ~SIS_FR;
2148 if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
2150 fp->fxp_got_int= TRUE;
2151 interrupt(fxp_tasknr);
2154 if (isr & SIS_CNA)
2156 isr &= ~SIS_CNA;
2157 if (!fp->fxp_tx_idle)
2159 fp->fxp_send_int= TRUE;
2160 if (!fp->fxp_got_int)
2162 fp->fxp_got_int= TRUE;
2163 interrupt(fxp_tasknr);
2167 if (isr & SIS_RNR)
2169 isr &= ~SIS_RNR;
2171 /* Assume that receive buffer is full of packets. fxp_readv
2172 * will restart the RU.
2174 fp->fxp_rx_need_restart= 1;
2176 if (isr)
2178 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
2179 isr);
2182 return 1;
2185 /*===========================================================================*
2186 * fxp_check_ints *
2187 *===========================================================================*/
2188 static void fxp_check_ints(fp)
2189 fxp_t *fp;
2191 int n, fxp_flags, prev_tail;
2192 int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
2193 port_t port;
2194 u32_t busaddr;
2195 u16_t tx_status;
2196 u8_t scb_status;
2197 struct tx *txp;
2199 fxp_flags= fp->fxp_flags;
2201 if (fxp_flags & FF_READING)
2203 if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
2204 ; /* Nothing */
2205 else if (fp->fxp_rx_mess.m_type == DL_READV)
2207 fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
2208 TRUE /* vectored */);
2210 else if (fp->fxp_rx_mess.m_type == DL_READV_S)
2212 fxp_readv_s(&fp->fxp_rx_mess, TRUE /* from int */);
2215 else
2217 assert(fp->fxp_rx_mess.m_type == DL_READ);
2218 fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
2219 FALSE /* !vectored */);
2222 if (fp->fxp_tx_idle)
2223 ; /* Nothing to do */
2224 else if (fp->fxp_send_int)
2226 fp->fxp_send_int= FALSE;
2227 fxp_tx_tail= fp->fxp_tx_tail;
2228 fxp_tx_nbuf= fp->fxp_tx_nbuf;
2229 n= 0;
2230 for (;;)
2232 txp= &fp->fxp_tx_buf[fxp_tx_tail];
2233 tx_status= txp->tx_status;
2234 if (!(tx_status & TXS_C))
2235 break;
2237 n++;
2239 assert(tx_status & TXS_OK);
2240 if (tx_status & TXS_U)
2242 fxp_tx_threshold= fp->fxp_tx_threshold;
2243 if (fxp_tx_threshold < TXTT_MAX)
2245 fxp_tx_threshold++;
2246 fp->fxp_tx_threshold= fxp_tx_threshold;
2248 printf(
2249 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
2250 fxp_tx_threshold);
2253 if (txp->tx_command & TXC_EL)
2255 fp->fxp_tx_idle= 1;
2256 break;
2259 fxp_tx_tail++;
2260 if (fxp_tx_tail == fxp_tx_nbuf)
2261 fxp_tx_tail= 0;
2262 assert(fxp_tx_tail < fxp_tx_nbuf);
2265 if (fp->fxp_need_conf)
2267 /* Check the status of the CU */
2268 port= fp->fxp_base_port;
2269 scb_status= fxp_inb(port, SCB_STATUS);
2270 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
2272 /* Nothing to do */
2273 printf("scb_status = 0x%x\n", scb_status);
2275 else
2277 printf("fxp_check_ints: fxp_need_conf\n");
2278 fp->fxp_need_conf= FALSE;
2279 fxp_do_conf(fp);
2283 if (n)
2285 if (!fp->fxp_tx_idle)
2287 fp->fxp_tx_tail= fxp_tx_tail;
2289 /* Check the status of the CU */
2290 port= fp->fxp_base_port;
2291 scb_status= fxp_inb(port, SCB_STATUS);
2292 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
2294 /* Nothing to do */
2295 printf("scb_status = 0x%x\n",
2296 scb_status);
2299 else
2301 if (fxp_tx_tail == 0)
2302 prev_tail= fxp_tx_nbuf-1;
2303 else
2304 prev_tail= fxp_tx_tail-1;
2305 busaddr= fp->fxp_tx_buf[prev_tail].
2306 tx_linkaddr;
2308 fxp_cu_ptr_cmd(fp, SC_CU_START,
2309 busaddr, 1 /* check idle */);
2313 if (fp->fxp_flags & FF_SEND_AVAIL)
2315 if (fp->fxp_tx_mess.m_type == DL_WRITEV)
2317 fxp_writev(&fp->fxp_tx_mess,
2318 TRUE /* from int */,
2319 TRUE /* vectored */);
2321 else if (fp->fxp_tx_mess.m_type == DL_WRITEV_S)
2323 fxp_writev_s(&fp->fxp_tx_mess,
2324 TRUE /* from int */);
2326 else
2328 assert(fp->fxp_tx_mess.m_type ==
2329 DL_WRITE);
2330 fxp_writev(&fp->fxp_tx_mess,
2331 TRUE /* from int */,
2332 FALSE /* !vectored */);
2338 if (fp->fxp_report_link)
2339 fxp_report_link(fp);
2341 if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
2342 reply(fp, OK, TRUE);
2345 /*===========================================================================*
2346 * fxp_watchdog_f *
2347 *===========================================================================*/
2348 static void fxp_watchdog_f(tp)
2349 timer_t *tp;
2351 int i;
2352 fxp_t *fp;
2354 tmr_arg(&fxp_watchdog)->ta_int= 0;
2355 fxp_set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f);
2357 for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
2359 if (fp->fxp_mode != FM_ENABLED)
2360 continue;
2362 /* Handle race condition, MII interface mgith be busy */
2363 if(!fp->fxp_mii_busy)
2365 /* Check the link status. */
2366 if (fxp_link_changed(fp))
2368 #if VERBOSE
2369 printf("fxp_watchdog_f: link changed\n");
2370 #endif
2371 fp->fxp_report_link= TRUE;
2372 fp->fxp_got_int= TRUE;
2373 interrupt(fxp_tasknr);
2377 if (!(fp->fxp_flags & FF_SEND_AVAIL))
2379 /* Assume that an idle system is alive */
2380 fp->fxp_tx_alive= TRUE;
2381 continue;
2383 if (fp->fxp_tx_alive)
2385 fp->fxp_tx_alive= FALSE;
2386 continue;
2389 fp->fxp_need_reset= TRUE;
2390 fp->fxp_got_int= TRUE;
2391 interrupt(fxp_tasknr);
2395 /*===========================================================================*
2396 * fxp_link_changed *
2397 *===========================================================================*/
2398 static int fxp_link_changed(fp)
2399 fxp_t *fp;
2401 u16_t scr;
2403 scr= mii_read(fp, MII_SCR);
2404 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
2406 return (fp->fxp_mii_scr != scr);
2409 /*===========================================================================*
2410 * fxp_report_link *
2411 *===========================================================================*/
2412 static void fxp_report_link(fp)
2413 fxp_t *fp;
2415 port_t port;
2416 u16_t mii_ctrl, mii_status, mii_id1, mii_id2,
2417 mii_ana, mii_anlpa, mii_ane, mii_extstat,
2418 mii_ms_ctrl, mii_ms_status, scr;
2419 u32_t oui;
2420 int model, rev;
2421 int f, link_up, ms_regs;
2423 /* Assume an 82555 (compatible) PHY. The should be changed for
2424 * 82557 NICs with different PHYs
2426 ms_regs= 0; /* No master/slave registers. */
2428 fp->fxp_report_link= FALSE;
2429 port= fp->fxp_base_port;
2431 scr= mii_read(fp, MII_SCR);
2432 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
2433 fp->fxp_mii_scr= scr;
2435 mii_ctrl= mii_read(fp, MII_CTRL);
2436 mii_read(fp, MII_STATUS); /* Read the status register twice, why? */
2437 mii_status= mii_read(fp, MII_STATUS);
2438 mii_id1= mii_read(fp, MII_PHYID_H);
2439 mii_id2= mii_read(fp, MII_PHYID_L);
2440 mii_ana= mii_read(fp, MII_ANA);
2441 mii_anlpa= mii_read(fp, MII_ANLPA);
2442 mii_ane= mii_read(fp, MII_ANE);
2443 if (mii_status & MII_STATUS_EXT_STAT)
2444 mii_extstat= mii_read(fp, MII_EXT_STATUS);
2445 else
2446 mii_extstat= 0;
2447 if (ms_regs)
2449 mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
2450 mii_ms_status= mii_read(fp, MII_MS_STATUS);
2452 else
2454 mii_ms_ctrl= 0;
2455 mii_ms_status= 0;
2458 /* How do we know about the link status? */
2459 link_up= !!(mii_status & MII_STATUS_LS);
2461 fp->fxp_link_up= link_up;
2462 if (!link_up)
2464 #if VERBOSE
2465 printf("%s: link down\n", fp->fxp_name);
2466 #endif
2467 return;
2470 oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) |
2471 ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
2472 model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
2473 rev= (mii_id2 & MII_PL_REV_MASK);
2475 #if VERBOSE
2476 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
2477 #endif
2479 if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
2481 printf("%s: PHY: ", fp->fxp_name);
2482 f= 1;
2483 if (mii_ctrl & MII_CTRL_LB)
2485 printf("loopback mode");
2486 f= 0;
2488 if (mii_ctrl & MII_CTRL_PD)
2490 if (!f) printf(", ");
2491 f= 0;
2492 printf("powered down");
2494 if (mii_ctrl & MII_CTRL_ISO)
2496 if (!f) printf(", ");
2497 f= 0;
2498 printf("isolated");
2500 printf("\n");
2501 return;
2503 if (!(mii_ctrl & MII_CTRL_ANE))
2505 printf("%s: manual config: ", fp->fxp_name);
2506 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
2508 case MII_CTRL_SP_10: printf("10 Mbps"); break;
2509 case MII_CTRL_SP_100: printf("100 Mbps"); break;
2510 case MII_CTRL_SP_1000: printf("1000 Mbps"); break;
2511 case MII_CTRL_SP_RES: printf("reserved speed"); break;
2513 if (mii_ctrl & MII_CTRL_DM)
2514 printf(", full duplex");
2515 else
2516 printf(", half duplex");
2517 printf("\n");
2518 return;
2521 if (!debug) goto resspeed;
2523 printf("%s: ", fp->fxp_name);
2524 mii_print_stat_speed(mii_status, mii_extstat);
2525 printf("\n");
2527 if (!(mii_status & MII_STATUS_ANC))
2528 printf("%s: auto-negotiation not complete\n", fp->fxp_name);
2529 if (mii_status & MII_STATUS_RF)
2530 printf("%s: remote fault detected\n", fp->fxp_name);
2531 if (!(mii_status & MII_STATUS_ANA))
2533 printf("%s: local PHY has no auto-negotiation ability\n",
2534 fp->fxp_name);
2536 if (!(mii_status & MII_STATUS_LS))
2537 printf("%s: link down\n", fp->fxp_name);
2538 if (mii_status & MII_STATUS_JD)
2539 printf("%s: jabber condition detected\n", fp->fxp_name);
2540 if (!(mii_status & MII_STATUS_EC))
2542 printf("%s: no extended register set\n", fp->fxp_name);
2543 goto resspeed;
2545 if (!(mii_status & MII_STATUS_ANC))
2546 goto resspeed;
2548 printf("%s: local cap.: ", fp->fxp_name);
2549 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
2551 printf("1000 Mbps: T-");
2552 switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
2554 case MII_MSC_1000T_FD: printf("FD"); break;
2555 case MII_MSC_1000T_HD: printf("HD"); break;
2556 default: printf("FD/HD"); break;
2558 if (mii_ana)
2559 printf(", ");
2561 mii_print_techab(mii_ana);
2562 printf("\n");
2564 if (mii_ane & MII_ANE_PDF)
2565 printf("%s: parallel detection fault\n", fp->fxp_name);
2566 if (!(mii_ane & MII_ANE_LPANA))
2568 printf("%s: link-partner does not support auto-negotiation\n",
2569 fp->fxp_name);
2570 goto resspeed;
2573 printf("%s: remote cap.: ", fp->fxp_name);
2574 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
2575 if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
2577 printf("1000 Mbps: T-");
2578 switch(mii_ms_status &
2579 (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
2581 case MII_MSS_LP1000T_FD: printf("FD"); break;
2582 case MII_MSS_LP1000T_HD: printf("HD"); break;
2583 default: printf("FD/HD"); break;
2585 if (mii_anlpa)
2586 printf(", ");
2588 mii_print_techab(mii_anlpa);
2589 printf("\n");
2591 if (ms_regs)
2593 printf("%s: ", fp->fxp_name);
2594 if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
2596 printf("manual %s",
2597 (mii_ms_ctrl & MII_MSC_MS_VAL) ?
2598 "MASTER" : "SLAVE");
2600 else
2602 printf("%s device",
2603 (mii_ms_ctrl & MII_MSC_MULTIPORT) ?
2604 "multiport" : "single-port");
2606 if (mii_ms_ctrl & MII_MSC_RES)
2607 printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
2608 printf(": ");
2609 if (mii_ms_status & MII_MSS_FAULT)
2610 printf("M/S config fault");
2611 else if (mii_ms_status & MII_MSS_MASTER)
2612 printf("MASTER");
2613 else
2614 printf("SLAVE");
2615 printf("\n");
2618 if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
2620 if (!(mii_ms_status & MII_MSS_LOCREC))
2622 printf("%s: local receiver not OK\n",
2623 fp->fxp_name);
2625 if (!(mii_ms_status & MII_MSS_REMREC))
2627 printf("%s: remote receiver not OK\n",
2628 fp->fxp_name);
2631 if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
2633 printf("%s", fp->fxp_name);
2634 if (mii_ms_status & MII_MSS_RES)
2635 printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
2636 if (mii_ms_status & MII_MSS_IDLE_ERR)
2638 printf(" idle error %d",
2639 mii_ms_status & MII_MSS_IDLE_ERR);
2641 printf("\n");
2644 resspeed:
2645 #if VERBOSE
2646 printf("%s: link up, %d Mbps, %s duplex\n",
2647 fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
2648 (scr & MII_SCR_FD) ? "full" : "half");
2649 #endif
2653 /*===========================================================================*
2654 * fxp_stop *
2655 *===========================================================================*/
2656 static void fxp_stop()
2658 int i;
2659 port_t port;
2660 fxp_t *fp;
2662 for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
2664 if (fp->fxp_mode != FM_ENABLED)
2665 continue;
2666 if (!(fp->fxp_flags & FF_ENABLED))
2667 continue;
2668 port= fp->fxp_base_port;
2670 /* Reset device */
2671 if (debug)
2672 printf("%s: resetting device\n", fp->fxp_name);
2673 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
2675 exit(0);
2678 /*===========================================================================*
2679 * reply *
2680 *===========================================================================*/
2681 static void reply(fp, err, may_block)
2682 fxp_t *fp;
2683 int err;
2684 int may_block;
2686 message reply;
2687 int status;
2688 int r;
2690 status = 0;
2691 if (fp->fxp_flags & FF_PACK_SENT)
2692 status |= DL_PACK_SEND;
2693 if (fp->fxp_flags & FF_PACK_RECV)
2694 status |= DL_PACK_RECV;
2696 reply.m_type = DL_TASK_REPLY;
2697 reply.DL_PORT = fp - fxp_table;
2698 reply.DL_PROC = fp->fxp_client;
2699 reply.DL_STAT = status | ((u32_t) err << 16);
2700 reply.DL_COUNT = fp->fxp_read_s;
2701 #if 0
2702 reply.DL_CLCK = get_uptime();
2703 #else
2704 reply.DL_CLCK = 0;
2705 #endif
2707 r= send(fp->fxp_client, &reply);
2709 if (r == ELOCKED && may_block)
2711 #if 0
2712 printW(); printf("send locked\n");
2713 #endif
2714 return;
2717 if (r < 0)
2718 panic("FXP","fxp: send failed:", r);
2720 fp->fxp_read_s = 0;
2721 fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
2724 /*===========================================================================*
2725 * mess_reply *
2726 *===========================================================================*/
2727 static void mess_reply(req, reply_mess)
2728 message *req;
2729 message *reply_mess;
2731 if (send(req->m_source, reply_mess) != OK)
2732 panic("FXP","fxp: unable to mess_reply", NO_NUM);
2735 /*===========================================================================*
2736 * eeprom_read *
2737 *===========================================================================*/
2738 PRIVATE u16_t eeprom_read(fp, reg)
2739 fxp_t *fp;
2740 int reg;
2742 port_t port;
2743 u16_t v;
2744 int b, i, alen;
2746 alen= fp->fxp_ee_addrlen;
2747 if (!alen)
2749 eeprom_addrsize(fp);
2750 alen= fp->fxp_ee_addrlen;
2751 assert(alen == 6 || alen == 8);
2754 port= fp->fxp_base_port;
2756 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
2757 v= EEPROM_READ_PREFIX;
2758 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
2760 b= ((v & (1 << i)) ? CE_EEDI : 0);
2761 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2762 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2763 micro_delay(EESK_PERIOD/2+1);
2764 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2765 micro_delay(EESK_PERIOD/2+1);
2768 v= reg;
2769 for (i= alen-1; i >= 0; i--)
2771 b= ((v & (1 << i)) ? CE_EEDI : 0);
2772 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2773 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2774 micro_delay(EESK_PERIOD/2+1);
2775 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2776 micro_delay(EESK_PERIOD/2+1);
2779 v= 0;
2780 for (i= 0; i<16; i++)
2782 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2783 micro_delay(EESK_PERIOD/2+1);
2784 b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
2785 v= (v << 1) | b;
2786 fxp_outb(port, CSR_EEPROM, CE_EECS );
2787 micro_delay(EESK_PERIOD/2+1);
2789 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2790 micro_delay(EECS_DELAY);
2792 return v;
2795 /*===========================================================================*
2796 * eeprom_addrsize *
2797 *===========================================================================*/
2798 PRIVATE void eeprom_addrsize(fp)
2799 fxp_t *fp;
2801 port_t port;
2802 u16_t v;
2803 int b, i;
2805 port= fp->fxp_base_port;
2807 /* Try to find out the size of the EEPROM */
2808 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
2809 v= EEPROM_READ_PREFIX;
2810 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
2812 b= ((v & (1 << i)) ? CE_EEDI : 0);
2813 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2814 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2815 micro_delay(EESK_PERIOD/2+1);
2816 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2817 micro_delay(EESK_PERIOD/2+1);
2820 for (i= 0; i<32; i++)
2822 b= 0;
2823 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2824 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2825 micro_delay(EESK_PERIOD/2+1);
2826 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2827 micro_delay(EESK_PERIOD/2+1);
2828 v= fxp_inb(port, CSR_EEPROM);
2829 if (!(v & CE_EEDO))
2830 break;
2832 if (i >= 32)
2833 panic("FXP","eeprom_addrsize: failed", NO_NUM);
2834 fp->fxp_ee_addrlen= i+1;
2836 /* Discard 16 data bits */
2837 for (i= 0; i<16; i++)
2839 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2840 micro_delay(EESK_PERIOD/2+1);
2841 fxp_outb(port, CSR_EEPROM, CE_EECS );
2842 micro_delay(EESK_PERIOD/2+1);
2844 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2845 micro_delay(EECS_DELAY);
2847 #if VERBOSE
2848 printf("%s EEPROM address length: %d\n",
2849 fp->fxp_name, fp->fxp_ee_addrlen);
2850 #endif
2853 /*===========================================================================*
2854 * mii_read *
2855 *===========================================================================*/
2856 PRIVATE u16_t mii_read(fp, reg)
2857 fxp_t *fp;
2858 int reg;
2860 clock_t t0,t1;
2861 port_t port;
2862 u32_t v;
2864 port= fp->fxp_base_port;
2866 assert(!fp->fxp_mii_busy);
2867 fp->fxp_mii_busy++;
2869 if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
2870 panic("FXP","mii_read: MDI not ready", NO_NUM);
2871 fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
2872 (reg << CM_REG_SHIFT));
2874 getuptime(&t0);
2875 do {
2876 v= fxp_inl(port, CSR_MDI_CTL);
2877 if (v & CM_READY)
2878 break;
2879 } while (getuptime(&t1)==OK && (t1-t0) < micros_to_ticks(100000));
2881 if (!(v & CM_READY))
2882 panic("FXP","mii_read: MDI not ready after command", NO_NUM);
2884 fp->fxp_mii_busy--;
2885 assert(!fp->fxp_mii_busy);
2887 return v & CM_DATA_MASK;
2890 /*===========================================================================*
2891 * fxp_set_timer *
2892 *===========================================================================*/
2893 PRIVATE void fxp_set_timer(tp, delta, watchdog)
2894 timer_t *tp; /* timer to be set */
2895 clock_t delta; /* in how many ticks */
2896 tmr_func_t watchdog; /* watchdog function to be called */
2898 clock_t now; /* current time */
2899 int r;
2901 /* Get the current time. */
2902 r= getuptime(&now);
2903 if (r != OK)
2904 panic("FXP","unable to get uptime from clock", r);
2906 /* Add the timer to the local timer queue. */
2907 tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
2909 /* Possibly reschedule an alarm call. This happens when a new timer
2910 * is added in front.
2912 if (fxp_next_timeout == 0 ||
2913 fxp_timers->tmr_exp_time < fxp_next_timeout)
2915 fxp_next_timeout= fxp_timers->tmr_exp_time;
2916 #if VERBOSE
2917 printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
2918 fxp_next_timeout, fxp_next_timeout-now);
2919 #endif
2920 r= sys_setalarm(fxp_next_timeout, 1);
2921 if (r != OK)
2922 panic("FXP","unable to set synchronous alarm", r);
2926 /*===========================================================================*
2927 * fxp_expire_tmrs *
2928 *===========================================================================*/
2929 PRIVATE void fxp_expire_timers()
2931 /* A synchronous alarm message was received. Check if there are any expired
2932 * timers. Possibly reschedule the next alarm.
2934 clock_t now; /* current time */
2935 int r;
2937 /* Get the current time to compare the timers against. */
2938 r= getuptime(&now);
2939 if (r != OK)
2940 panic("FXP","Unable to get uptime from clock.", r);
2942 /* Scan the timers queue for expired timers. Dispatch the watchdog function
2943 * for each expired timers. Possibly a new alarm call must be scheduled.
2945 tmrs_exptimers(&fxp_timers, now, NULL);
2946 if (fxp_timers == NULL)
2947 fxp_next_timeout= TMR_NEVER;
2948 else
2949 { /* set new alarm */
2950 fxp_next_timeout = fxp_timers->tmr_exp_time;
2951 r= sys_setalarm(fxp_next_timeout, 1);
2952 if (r != OK)
2953 panic("FXP","Unable to set synchronous alarm.", r);
2957 static u8_t do_inb(port_t port)
2959 int r;
2960 u32_t value;
2962 r= sys_inb(port, &value);
2963 if (r != OK)
2964 panic("FXP","sys_inb failed", r);
2965 return value;
2968 static u32_t do_inl(port_t port)
2970 int r;
2971 u32_t value;
2973 r= sys_inl(port, &value);
2974 if (r != OK)
2975 panic("FXP","sys_inl failed", r);
2976 return value;
2979 static void do_outb(port_t port, u8_t value)
2981 int r;
2983 r= sys_outb(port, value);
2984 if (r != OK)
2985 panic("FXP","sys_outb failed", r);
2988 static void do_outl(port_t port, u32_t value)
2990 int r;
2992 r= sys_outl(port, value);
2993 if (r != OK)
2994 panic("FXP","sys_outl failed", r);
2997 PRIVATE void tell_dev(buf, size, pci_bus, pci_dev, pci_func)
2998 vir_bytes buf;
2999 size_t size;
3000 int pci_bus;
3001 int pci_dev;
3002 int pci_func;
3004 int r;
3005 endpoint_t dev_e;
3006 u32_t u32;
3007 message m;
3009 r= ds_retrieve_label_num("amddev", &u32);
3010 if (r != OK)
3012 #if 0
3013 printf(
3014 "fxp`tell_dev: ds_retrieve_label_num failed for 'amddev': %d\n",
3016 #endif
3017 return;
3020 dev_e= u32;
3022 m.m_type= IOMMU_MAP;
3023 m.m2_i1= pci_bus;
3024 m.m2_i2= pci_dev;
3025 m.m2_i3= pci_func;
3026 m.m2_l1= buf;
3027 m.m2_l2= size;
3029 r= sendrec(dev_e, &m);
3030 if (r != OK)
3032 printf("fxp`tell_dev: sendrec to %d failed: %d\n",
3033 dev_e, r);
3034 return;
3036 if (m.m_type != OK)
3038 printf("fxp`tell_dev: dma map request failed: %d\n",
3039 m.m_type);
3040 return;
3045 * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $