memory: use sys_safememset() for /dev/zero
[minix.git] / drivers / fxp / fxp.c
blobbc752527d3505d6f02c11261c825977a90b5937f
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 debug 0
24 #define RAND_UPDATE /**/
25 #define printW() ((void)0)
27 #include "assert.h"
28 #include "fxp.h"
29 #include "mii.h"
31 /* Number of receive buffers */
32 #define N_RX_BUF 40
34 /* Number of transmit buffers */
35 #define N_TX_BUF 4
37 /* I/O vectors are handled IOVEC_NR entries at a time. */
38 #define IOVEC_NR 16
40 /* Configuration */
41 #define FXP_ENVVAR "FXPETH"
43 typedef int irq_hook_t;
45 /* ignore interrupt for the moment */
46 #define interrupt(x) do { } while(0)
48 static union tmpbuf
50 char pad[4096];
51 struct cbl_conf cc;
52 struct ias ias;
53 } *tmpbufp;
55 typedef struct fxp
57 port_t fxp_base_port;
58 int fxp_mode;
59 int fxp_got_int;
60 int fxp_send_int;
61 int fxp_flags;
62 int fxp_client;
63 int fxp_features; /* Needed? */
64 int fxp_irq;
65 int fxp_type; /* What kind of hardware */
66 int fxp_ms_regs; /* Master/slave registers */
67 int fxp_ee_addrlen; /* #EEPROM address bits */
68 int fxp_tx_alive;
69 int fxp_need_reset;
71 /* Rx */
72 vir_bytes fxp_read_s;
73 int fxp_rx_nbuf;
74 int fxp_rx_bufsize;
75 struct rfd *fxp_rx_buf;
76 phys_bytes fxp_rx_busaddr;
77 int fxp_rx_head;
78 int fxp_rx_need_restart;
79 int fxp_need_conf; /* Re-configure after draining send
80 * queue
83 /* Tx */
84 int fxp_tx_nbuf;
85 int fxp_tx_bufsize;
86 struct tx *fxp_tx_buf;
87 phys_bytes fxp_tx_busaddr;
88 int fxp_tx_idle;
89 int fxp_tx_head;
90 int fxp_tx_tail;
91 int fxp_tx_threshold;
93 /* Link status */
94 int fxp_report_link;
95 int fxp_link_up;
96 int fxp_mii_busy;
97 u16_t fxp_mii_scr;
99 /* PCI related */
100 int fxp_seen; /* TRUE iff device available */
102 /* 'large' items */
103 irq_hook_t fxp_hook;
104 ether_addr_t fxp_address;
105 message fxp_rx_mess;
106 message fxp_tx_mess;
107 struct sc fxp_stat;
108 u8_t fxp_conf_bytes[CC_BYTES_NR];
109 char fxp_name[sizeof("fxp#n")];
110 iovec_t fxp_iovec[IOVEC_NR];
111 iovec_s_t fxp_iovec_s[IOVEC_NR];
113 fxp_t;
115 /* fxp_mode */
116 #define FM_DISABLED 0x0
117 #define FM_ENABLED 0x1
119 /* fxp_flags */
120 #define FF_EMPTY 0x000
121 #define FF_PACK_SENT 0x001
122 #define FF_PACK_RECV 0x002
123 #define FF_SEND_AVAIL 0x004
124 #define FF_READING 0x010
125 #define FF_PROMISC 0x040
126 #define FF_MULTI 0x080
127 #define FF_BROAD 0x100
128 #define FF_ENABLED 0x200
130 /* fxp_features */
131 #define FFE_NONE 0x0
133 /* fxp_type */
134 #define FT_UNKNOWN 0x0
135 #define FT_82557 0x1
136 #define FT_82558A 0x2
137 #define FT_82559 0x4
138 #define FT_82801 0x8
140 static int fxp_instance;
142 static fxp_t *fxp_state;
144 static timer_t fxp_watchdog;
146 static u32_t system_hz;
148 #define fxp_inb(port, offset) (do_inb((port) + (offset)))
149 #define fxp_inl(port, offset) (do_inl((port) + (offset)))
150 #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
151 #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
153 static void fxp_init(message *mp);
154 static void fxp_pci_conf(void);
155 static int fxp_probe(fxp_t *fp, int skip);
156 static void fxp_conf_hw(fxp_t *fp);
157 static void fxp_init_hw(fxp_t *fp);
158 static void fxp_init_buf(fxp_t *fp);
159 static void fxp_reset_hw(fxp_t *fp);
160 static void fxp_confaddr(fxp_t *fp);
161 static void fxp_rec_mode(fxp_t *fp);
162 static void fxp_writev_s(const message *mp, int from_int);
163 static void fxp_readv_s(message *mp, int from_int);
164 static void fxp_do_conf(fxp_t *fp);
165 static void fxp_cu_ptr_cmd(fxp_t *fp, int cmd, phys_bytes bus_addr, int
166 check_idle);
167 static void fxp_ru_ptr_cmd(fxp_t *fp, int cmd, phys_bytes bus_addr, int
168 check_idle);
169 static void fxp_restart_ru(fxp_t *fp);
170 static void fxp_getstat_s(message *mp);
171 static void fxp_handler(fxp_t *fp);
172 static void fxp_check_ints(fxp_t *fp);
173 static void fxp_watchdog_f(timer_t *tp);
174 static int fxp_link_changed(fxp_t *fp);
175 static void fxp_report_link(fxp_t *fp);
176 static void reply(fxp_t *fp);
177 static void mess_reply(message *req, message *reply);
178 static u16_t eeprom_read(fxp_t *fp, int reg);
179 static void eeprom_addrsize(fxp_t *fp);
180 static u16_t mii_read(fxp_t *fp, int reg);
181 static u8_t do_inb(port_t port);
182 static u32_t do_inl(port_t port);
183 static void do_outb(port_t port, u8_t v);
184 static void do_outl(port_t port, u32_t v);
185 static void tell_dev(vir_bytes start, size_t size, int pci_bus, int
186 pci_dev, int pci_func);
188 static void handle_hw_intr(void)
190 int r;
191 fxp_t *fp;
193 fp= fxp_state;
195 if (fp->fxp_mode != FM_ENABLED)
196 return;
197 fxp_handler(fp);
199 r= sys_irqenable(&fp->fxp_hook);
200 if (r != OK) {
201 panic("unable enable interrupts: %d", r);
204 if (!fp->fxp_got_int)
205 return;
206 fp->fxp_got_int= 0;
207 assert(fp->fxp_flags & FF_ENABLED);
208 fxp_check_ints(fp);
211 /* SEF functions and variables. */
212 static void sef_local_startup(void);
213 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
214 static void sef_cb_signal_handler(int signo);
216 /*===========================================================================*
217 * main *
218 *===========================================================================*/
219 int main(int argc, char *argv[])
221 message m;
222 int ipc_status;
223 int r;
225 /* SEF local startup. */
226 env_setargs(argc, argv);
227 sef_local_startup();
229 while (TRUE)
231 if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK)
232 panic("netdriver_receive failed: %d", r);
234 if (is_ipc_notify(ipc_status)) {
235 switch (_ENDPOINT_P(m.m_source)) {
236 case HARDWARE:
237 handle_hw_intr();
238 break;
239 case CLOCK:
240 expire_timers(m.NOTIFY_TIMESTAMP);
241 break;
242 default:
243 panic(" illegal notify from: %d", m.m_source);
246 /* get new message */
247 continue;
250 switch (m.m_type)
252 case DL_WRITEV_S: fxp_writev_s(&m, FALSE); break;
253 case DL_READV_S: fxp_readv_s(&m, FALSE); break;
254 case DL_CONF: fxp_init(&m); break;
255 case DL_GETSTAT_S: fxp_getstat_s(&m); break;
256 default:
257 panic(" illegal message: %d", m.m_type);
262 /*===========================================================================*
263 * sef_local_startup *
264 *===========================================================================*/
265 static void sef_local_startup()
267 /* Register init callbacks. */
268 sef_setcb_init_fresh(sef_cb_init_fresh);
269 sef_setcb_init_lu(sef_cb_init_fresh);
270 sef_setcb_init_restart(sef_cb_init_fresh);
272 /* Register live update callbacks. */
273 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
274 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
276 /* Register signal callbacks. */
277 sef_setcb_signal_handler(sef_cb_signal_handler);
279 /* Let SEF perform startup. */
280 sef_startup();
283 /*===========================================================================*
284 * sef_cb_init_fresh *
285 *===========================================================================*/
286 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
288 /* Initialize the fxp driver. */
289 long v;
290 int r;
291 vir_bytes ft;
293 system_hz = sys_hz();
295 v = 0;
296 (void) env_parse("instance", "d", 0, &v, 0, 255);
297 fxp_instance = (int) v;
299 ft = sizeof(*fxp_state);
301 if(!(fxp_state = alloc_contig(ft, 0, NULL)))
302 panic("couldn't allocate table: %d", ENOMEM);
304 memset(fxp_state, 0, ft);
306 if((r=tsc_calibrate()) != OK)
307 panic("tsc_calibrate failed: %d", r);
309 /* Announce we are up! */
310 netdriver_announce();
312 return(OK);
315 /*===========================================================================*
316 * sef_cb_signal_handler *
317 *===========================================================================*/
318 static void sef_cb_signal_handler(int signo)
320 port_t port;
321 fxp_t *fp;
323 /* Only check for termination signal, ignore anything else. */
324 if (signo != SIGTERM) return;
326 fp= fxp_state;
328 if (fp->fxp_mode == FM_ENABLED && (fp->fxp_flags & FF_ENABLED)) {
329 port= fp->fxp_base_port;
331 /* Reset device */
332 if (debug)
333 printf("%s: resetting device\n", fp->fxp_name);
334 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
337 exit(0);
340 /*===========================================================================*
341 * fxp_init *
342 *===========================================================================*/
343 static void fxp_init(mp)
344 message *mp;
346 static int first_time= 1;
348 fxp_t *fp;
349 message reply_mess;
351 if (first_time)
353 first_time= 0;
354 fxp_pci_conf(); /* Configure PCI devices. */
356 init_timer(&fxp_watchdog);
357 set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f, 0);
360 fp= fxp_state;
361 if (fp->fxp_mode == FM_DISABLED)
363 /* This is the default, try to (re)locate the device. */
364 fxp_conf_hw(fp);
365 if (fp->fxp_mode == FM_DISABLED)
367 /* Probe failed, or the device is configured off. */
368 reply_mess.m_type= DL_CONF_REPLY;
369 reply_mess.DL_STAT= ENXIO;
370 mess_reply(mp, &reply_mess);
371 return;
373 if (fp->fxp_mode == FM_ENABLED)
374 fxp_init_hw(fp);
375 fxp_report_link(fp);
378 assert(fp->fxp_mode == FM_ENABLED);
379 assert(fp->fxp_flags & FF_ENABLED);
381 fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
383 if (mp->DL_MODE & DL_PROMISC_REQ)
384 fp->fxp_flags |= FF_PROMISC;
385 if (mp->DL_MODE & DL_MULTI_REQ)
386 fp->fxp_flags |= FF_MULTI;
387 if (mp->DL_MODE & DL_BROAD_REQ)
388 fp->fxp_flags |= FF_BROAD;
390 fxp_rec_mode(fp);
392 reply_mess.m_type = DL_CONF_REPLY;
393 reply_mess.DL_STAT = OK;
394 *(ether_addr_t *) reply_mess.DL_HWADDR = fp->fxp_address;
396 mess_reply(mp, &reply_mess);
399 /*===========================================================================*
400 * fxp_pci_conf *
401 *===========================================================================*/
402 static void fxp_pci_conf()
404 fxp_t *fp;
406 fp= fxp_state;
408 strlcpy(fp->fxp_name, "fxp#0", sizeof(fp->fxp_name));
409 fp->fxp_name[4] += fxp_instance;
410 fp->fxp_seen= FALSE;
411 fp->fxp_features= FFE_NONE;
413 pci_init();
415 if (fxp_probe(fp, fxp_instance))
416 fp->fxp_seen= TRUE;
419 /*===========================================================================*
420 * fxp_probe *
421 *===========================================================================*/
422 static int fxp_probe(fxp_t *fp, int skip)
424 int r, devind;
425 u16_t vid, did;
426 u32_t bar;
427 u8_t ilr, rev;
428 char *str;
429 #if VERBOSE
430 char *dname;
431 #endif
433 r= pci_first_dev(&devind, &vid, &did);
434 if (r == 0)
435 return FALSE;
437 while (skip--)
439 r= pci_next_dev(&devind, &vid, &did);
440 if (!r)
441 return FALSE;
444 #if VERBOSE
445 dname= pci_dev_name(vid, did);
446 if (!dname)
447 dname= "unknown device";
448 printf("%s: %s (%04x/%04x) at %s\n",
449 fp->fxp_name, dname, vid, did, pci_slot_name(devind));
450 #endif
451 pci_reserve(devind);
453 bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
454 if (bar < 0x400) {
455 panic("fxp_probe: base address is not properly configured");
457 fp->fxp_base_port= bar;
459 ilr= pci_attr_r8(devind, PCI_ILR);
460 fp->fxp_irq= ilr;
461 if (debug)
463 printf("%s: using I/O address 0x%lx, IRQ %d\n",
464 fp->fxp_name, (unsigned long)bar, ilr);
467 rev= pci_attr_r8(devind, PCI_REV);
468 str= NULL;
469 fp->fxp_type= FT_UNKNOWN;
470 switch(rev)
472 case FXP_REV_82557A: str= "82557A"; /* 0x01 */
473 fp->fxp_type= FT_82557;
474 break;
475 case FXP_REV_82557B: str= "82557B"; break; /* 0x02 */
476 case FXP_REV_82557C: str= "82557C"; break; /* 0x03 */
477 case FXP_REV_82558A: str= "82558A"; /* 0x04 */
478 fp->fxp_type= FT_82558A;
479 break;
480 case FXP_REV_82558B: str= "82558B"; /* 0x05 */
481 fp->fxp_type= FT_82559;
482 break;
483 case FXP_REV_82559A: str= "82559A"; break; /* 0x06 */
484 case FXP_REV_82559B: str= "82559B"; break; /* 0x07 */
485 case FXP_REV_82559C: str= "82559C"; /* 0x08 */
486 fp->fxp_type= FT_82559;
487 break;
488 case FXP_REV_82559ERA: str= "82559ER-A"; /* 0x09 */
489 fp->fxp_type= FT_82559;
490 break;
491 case FXP_REV_82550_1: str= "82550(1)"; /* 0x0C */
492 fp->fxp_type= FT_82559;
493 break;
494 case FXP_REV_82550_2: str= "82550(2)"; /* 0x0D */
495 fp->fxp_type= FT_82559;
496 break;
497 case FXP_REV_82550_3: str= "82550(3)"; /* 0x0E */
498 fp->fxp_type= FT_82559;
499 break;
500 case FXP_REV_82551_1: str= "82551(1)"; /* 0x0F */
501 fp->fxp_type= FT_82559;
502 break;
503 case FXP_REV_82551_2: str= "82551(2)"; /* 0x10 */
504 fp->fxp_type= FT_82559;
505 break;
506 case FXP_REV_82801CAM: str= "82801CAM"; /* 0x42 */
507 fp->fxp_type= FT_82801;
508 break;
509 case FXP_REV_82801DB: str= "82801DB"; /* 0x81 */
510 fp->fxp_type= FT_82801;
511 break;
514 #if VERBOSE
515 if (str)
516 printf("%s: device revision: %s\n", fp->fxp_name, str);
517 else
518 printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
519 #endif
521 if (fp->fxp_type == FT_UNKNOWN)
523 printf("fxp_probe: device is not supported by this driver\n");
524 return FALSE;
527 return TRUE;
530 /*===========================================================================*
531 * fxp_conf_hw *
532 *===========================================================================*/
533 static void fxp_conf_hw(fxp_t *fp)
535 #if VERBOSE
536 int i;
537 #endif
539 fp->fxp_mode= FM_DISABLED; /* Superfluous */
541 if (!fp->fxp_seen)
542 return;
544 /* PCI device is present */
545 fp->fxp_mode= FM_ENABLED;
547 fp->fxp_flags= FF_EMPTY;
548 fp->fxp_got_int= 0;
549 fp->fxp_send_int= 0;
550 fp->fxp_ee_addrlen= 0; /* Unknown */
551 fp->fxp_need_reset= 0;
552 fp->fxp_report_link= 0;
553 fp->fxp_link_up= -1; /* Unknown */
554 fp->fxp_mii_busy= 0;
555 fp->fxp_read_s= 0;
556 fp->fxp_rx_need_restart= 0;
557 fp->fxp_need_conf= 0;
558 fp->fxp_tx_head= 0;
559 fp->fxp_tx_tail= 0;
560 fp->fxp_tx_alive= 0;
561 fp->fxp_tx_threshold= TXTT_MIN;
563 /* Try to come up with a sensible configuration for the current
564 * device. Unfortunately every device is different, defaults are
565 * not always zero, and some fields are re-used with a completely
566 * different interpretation. We start out with a sensible default
567 * for all devices and then add device specific changes.
569 fp->fxp_conf_bytes[0]= CC_BYTES_NR;
570 fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
571 fp->fxp_conf_bytes[2]= CAI_DEFAULT;
572 fp->fxp_conf_bytes[3]= 0;
573 fp->fxp_conf_bytes[4]= 0;
574 fp->fxp_conf_bytes[5]= 0;
575 fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
576 fp->fxp_conf_bytes[7]= CUR_1;
577 fp->fxp_conf_bytes[8]= CCB8_503_MII;
578 fp->fxp_conf_bytes[9]= 0;
579 fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
580 CCB10_RES1;
581 fp->fxp_conf_bytes[11]= 0;
582 fp->fxp_conf_bytes[12]= CIS_DEFAULT;
583 fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
584 fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
585 fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
586 fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
587 fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
588 fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
589 fp->fxp_conf_bytes[19]= CCB19_FDPE;
590 fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
591 fp->fxp_conf_bytes[21]= CCB21_RES21;
593 #if VERBOSE
594 for (i= 0; i<CC_BYTES_NR; i++)
595 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
596 printf("\n");
597 #endif
599 switch(fp->fxp_type)
601 case FT_82557:
602 break;
603 case FT_82558A:
604 case FT_82559:
605 case FT_82801:
606 fp->fxp_conf_bytes[18] |= CCB18_LROK;
608 if (fp->fxp_type == FT_82801)
610 fp->fxp_conf_bytes[6] = 0xba; /* ctrl 1 */
611 fp->fxp_conf_bytes[15] = 0x48; /* promiscuous */
612 fp->fxp_conf_bytes[21] = 0x05; /* mc_all */
614 break;
615 default:
616 panic("fxp_conf_hw: bad device type: %d", fp->fxp_type);
619 /* Assume an 82555 (compatible) PHY. The should be changed for
620 * 82557 NICs with different PHYs
622 fp->fxp_ms_regs = 0; /* No master/slave registers. */
624 #if VERBOSE
625 for (i= 0; i<CC_BYTES_NR; i++)
626 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
627 printf("\n");
628 #endif
631 /*===========================================================================*
632 * fxp_init_hw *
633 *===========================================================================*/
634 static void fxp_init_hw(fp)
635 fxp_t *fp;
637 int i, r, isr;
638 port_t port;
639 phys_bytes bus_addr;
641 port= fp->fxp_base_port;
643 fxp_init_buf(fp);
645 fp->fxp_flags = FF_EMPTY;
646 fp->fxp_flags |= FF_ENABLED;
648 /* Set the interrupt handler and policy. Do not automatically
649 * reenable interrupts. Return the IRQ line number on interrupts.
651 fp->fxp_hook = fp->fxp_irq;
652 r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
653 if (r != OK)
654 panic("sys_irqsetpolicy failed: %d", r);
656 fxp_reset_hw(fp);
658 r= sys_irqenable(&fp->fxp_hook);
659 if (r != OK)
660 panic("sys_irqenable failed: %d", r);
662 /* Reset PHY? */
664 fxp_do_conf(fp);
666 /* Set pointer to statistical counters */
667 r= sys_umap(SELF, VM_D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
668 &bus_addr);
669 if (r != OK)
670 panic("sys_umap failed: %d", r);
671 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);
673 /* Ack previous interrupts */
674 isr= fxp_inb(port, SCB_INT_STAT);
675 fxp_outb(port, SCB_INT_STAT, isr);
677 /* Enable interrupts */
678 fxp_outb(port, SCB_INT_MASK, 0);
680 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
681 TRUE /* check idle */);
683 fxp_confaddr(fp);
684 if (debug)
686 printf("%s: Ethernet address ", fp->fxp_name);
687 for (i= 0; i < 6; i++)
689 printf("%x%c", fp->fxp_address.ea_addr[i],
690 i < 5 ? ':' : '\n');
695 /*===========================================================================*
696 * fxp_init_buf *
697 *===========================================================================*/
698 static void fxp_init_buf(fp)
699 fxp_t *fp;
701 size_t rx_totbufsize, tx_totbufsize, tot_bufsize, alloc_bufsize;
702 char *alloc_buf;
703 phys_bytes buf, bus_addr;
704 int i, r;
705 struct rfd *rfdp;
706 struct tx *txp;
707 phys_bytes ph;
709 fp->fxp_rx_nbuf= N_RX_BUF;
710 rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
711 fp->fxp_rx_bufsize= rx_totbufsize;
713 fp->fxp_tx_nbuf= N_TX_BUF;
714 tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
715 fp->fxp_tx_bufsize= tx_totbufsize;
717 tot_bufsize= sizeof(*tmpbufp) + tx_totbufsize + rx_totbufsize;
718 if (tot_bufsize % 4096)
719 tot_bufsize += 4096 - (tot_bufsize % 4096);
720 alloc_bufsize= tot_bufsize;
721 alloc_buf= alloc_contig(alloc_bufsize, AC_ALIGN4K, &ph);
722 if (alloc_buf == NULL) {
723 panic("fxp_init_buf: unable to alloc_contig size: %d", alloc_bufsize);
726 buf= (phys_bytes)alloc_buf;
728 tell_dev((vir_bytes)buf, tot_bufsize, 0, 0, 0);
730 tmpbufp= (union tmpbuf *)buf;
732 fp->fxp_rx_buf= (struct rfd *)&tmpbufp[1];
733 r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_rx_buf, rx_totbufsize,
734 &bus_addr);
735 if (r != OK)
736 panic("sys_umap failed: %d", r);
737 fp->fxp_rx_busaddr= bus_addr;
739 #if 0
740 printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n",
741 fp->fxp_rx_busaddr, fp->fxp_rx_buf);
742 #endif
744 for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
746 rfdp->rfd_status= 0;
747 rfdp->rfd_command= 0;
748 if (i != fp->fxp_rx_nbuf-1)
750 r= sys_umap(SELF, VM_D, (vir_bytes)&rfdp[1],
751 sizeof(rfdp[1]), &bus_addr);
752 if (r != OK)
753 panic("sys_umap failed: %d", r);
754 rfdp->rfd_linkaddr= bus_addr;
756 else
758 rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
759 rfdp->rfd_command |= RFDC_EL;
761 rfdp->rfd_reserved= 0;
762 rfdp->rfd_res= 0;
763 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
766 fp->fxp_rx_head= 0;
768 fp->fxp_tx_buf= (struct tx *)((char *)fp->fxp_rx_buf+rx_totbufsize);
769 r= sys_umap(SELF, VM_D, (vir_bytes)fp->fxp_tx_buf,
770 (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
771 if (r != OK)
772 panic("sys_umap failed: %d", r);
774 for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
776 txp->tx_status= 0;
777 txp->tx_command= TXC_EL | CBL_NOP; /* Just in case */
778 if (i != fp->fxp_tx_nbuf-1)
780 r= sys_umap(SELF, VM_D, (vir_bytes)&txp[1],
781 (phys_bytes)sizeof(txp[1]), &bus_addr);
782 if (r != OK)
783 panic("sys_umap failed: %d", r);
784 txp->tx_linkaddr= bus_addr;
786 else
788 txp->tx_linkaddr= fp->fxp_tx_busaddr;
790 txp->tx_tbda= TX_TBDA_NIL;
791 txp->tx_size= 0;
792 txp->tx_tthresh= fp->fxp_tx_threshold;
793 txp->tx_ntbd= 0;
795 fp->fxp_tx_idle= 1;
798 /*===========================================================================*
799 * fxp_reset_hw *
800 *===========================================================================*/
801 static void fxp_reset_hw(fp)
802 fxp_t *fp;
804 /* Inline the function in init? */
805 port_t port;
807 port= fp->fxp_base_port;
809 /* Reset device */
810 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
811 tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY));
813 /* Disable interrupts */
814 fxp_outb(port, SCB_INT_MASK, SIM_M);
816 /* Set CU base to zero */
817 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
819 /* Set RU base to zero */
820 fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
823 /*===========================================================================*
824 * fxp_confaddr *
825 *===========================================================================*/
826 static void fxp_confaddr(fxp_t *fp)
828 static char eakey[]= FXP_ENVVAR "#_EA";
829 static char eafmt[]= "x:x:x:x:x:x";
830 int i, r;
831 phys_bytes bus_addr;
832 long v;
834 /* User defined ethernet address? */
835 eakey[sizeof(FXP_ENVVAR)-1]= '0' + fxp_instance;
837 for (i= 0; i < 6; i++)
839 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
840 break;
841 fp->fxp_address.ea_addr[i]= v;
844 if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
846 if (i == 0)
848 /* Get ethernet address from EEPROM */
849 for (i= 0; i<3; i++)
851 v= eeprom_read(fp, i);
852 fp->fxp_address.ea_addr[i*2]= (v & 0xff);
853 fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
857 /* Tell NIC about ethernet address */
858 tmpbufp->ias.ias_status= 0;
859 tmpbufp->ias.ias_command= CBL_C_EL | CBL_AIS;
860 tmpbufp->ias.ias_linkaddr= 0;
861 memcpy(tmpbufp->ias.ias_ethaddr, fp->fxp_address.ea_addr,
862 sizeof(tmpbufp->ias.ias_ethaddr));
863 r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->ias,
864 (phys_bytes)sizeof(tmpbufp->ias), &bus_addr);
865 if (r != OK)
866 panic("sys_umap failed: %d", r);
868 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
870 /* Wait for CU command to complete */
871 SPIN_UNTIL(tmpbufp->ias.ias_status & CBL_F_C, 1000);
873 if (!(tmpbufp->ias.ias_status & CBL_F_C))
874 panic("fxp_confaddr: CU command failed to complete");
875 if (!(tmpbufp->ias.ias_status & CBL_F_OK))
876 panic("fxp_confaddr: CU command failed");
878 #if VERBOSE
879 printf("%s: hardware ethernet address: ", fp->fxp_name);
880 for (i= 0; i<6; i++)
882 printf("%02x%s", fp->fxp_address.ea_addr[i],
883 i < 5 ? ":" : "");
885 printf("\n");
886 #endif
889 /*===========================================================================*
890 * fxp_rec_mode *
891 *===========================================================================*/
892 static void fxp_rec_mode(fp)
893 fxp_t *fp;
895 fp->fxp_conf_bytes[0]= CC_BYTES_NR; /* Just to be sure */
896 fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
897 fp->fxp_conf_bytes[21] &= ~CCB21_MA;
899 if (fp->fxp_flags & FF_PROMISC)
900 fp->fxp_conf_bytes[15] |= CCB15_PM;
901 if (fp->fxp_flags & FF_MULTI)
902 fp->fxp_conf_bytes[21] |= CCB21_MA;
904 if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
905 fp->fxp_conf_bytes[15] |= CCB15_BD;
907 /* Queue request if not idle */
908 if (fp->fxp_tx_idle)
910 fxp_do_conf(fp);
912 else
914 printf("fxp_rec_mode: setting fxp_need_conf\n");
915 fp->fxp_need_conf= TRUE;
919 /*===========================================================================*
920 * fxp_writev_s *
921 *===========================================================================*/
922 static void fxp_writev_s(const message *mp, int from_int)
924 endpoint_t iov_endpt;
925 cp_grant_id_t iov_grant;
926 vir_bytes iov_offset;
927 int i, j, n, o, r, s, count, size, prev_head;
928 int fxp_tx_nbuf, fxp_tx_head;
929 u16_t tx_command;
930 fxp_t *fp;
931 iovec_s_t *iovp;
932 struct tx *txp, *prev_txp;
934 fp= fxp_state;
936 count = mp->DL_COUNT;
937 fp->fxp_client= mp->m_source;
939 assert(fp->fxp_mode == FM_ENABLED);
940 assert(fp->fxp_flags & FF_ENABLED);
942 if (from_int)
944 assert(fp->fxp_flags & FF_SEND_AVAIL);
945 fp->fxp_flags &= ~FF_SEND_AVAIL;
946 fp->fxp_tx_alive= TRUE;
949 if (fp->fxp_tx_idle)
951 txp= fp->fxp_tx_buf;
952 fxp_tx_head= 0; /* lint */
953 prev_txp= NULL; /* lint */
955 else
957 fxp_tx_nbuf= fp->fxp_tx_nbuf;
958 prev_head= fp->fxp_tx_head;
959 fxp_tx_head= prev_head+1;
960 if (fxp_tx_head == fxp_tx_nbuf)
961 fxp_tx_head= 0;
962 assert(fxp_tx_head < fxp_tx_nbuf);
964 if (fxp_tx_head == fp->fxp_tx_tail)
966 /* Send queue is full */
967 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
968 fp->fxp_flags |= FF_SEND_AVAIL;
969 goto suspend;
972 prev_txp= &fp->fxp_tx_buf[prev_head];
973 txp= &fp->fxp_tx_buf[fxp_tx_head];
976 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
977 assert(!(fp->fxp_flags & FF_PACK_SENT));
979 iov_endpt= mp->m_source;
980 iov_grant= mp->DL_GRANT;
982 size= 0;
983 o= 0;
984 iov_offset= 0;
985 for (i= 0; i<count; i += IOVEC_NR,
986 iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
988 n= IOVEC_NR;
989 if (i+n > count)
990 n= count-i;
991 r= sys_safecopyfrom(iov_endpt, iov_grant, iov_offset,
992 (vir_bytes)fp->fxp_iovec_s,
993 n * sizeof(fp->fxp_iovec_s[0]));
994 if (r != OK)
995 panic("fxp_writev: sys_safecopyfrom failed: %d", r);
997 for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
999 s= iovp->iov_size;
1000 if (size + s > ETH_MAX_PACK_SIZE_TAGGED) {
1001 panic("fxp_writev: invalid packet size: %d", size + s);
1004 r= sys_safecopyfrom(iov_endpt, iovp->iov_grant,
1005 0, (vir_bytes)(txp->tx_buf+o), s);
1006 if (r != OK) {
1007 panic("fxp_writev_s: sys_safecopyfrom failed: %d", r);
1009 size += s;
1010 o += s;
1013 if (size < ETH_MIN_PACK_SIZE)
1014 panic("fxp_writev: invalid packet size: %d", size);
1016 txp->tx_status= 0;
1017 txp->tx_command= TXC_EL | CBL_XMIT;
1018 txp->tx_tbda= TX_TBDA_NIL;
1019 txp->tx_size= TXSZ_EOF | size;
1020 txp->tx_tthresh= fp->fxp_tx_threshold;
1021 txp->tx_ntbd= 0;
1022 if (fp->fxp_tx_idle)
1024 fp->fxp_tx_idle= 0;
1025 fp->fxp_tx_head= fp->fxp_tx_tail= 0;
1027 fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
1028 TRUE /* check idle */);
1030 else
1032 /* Link new request in transmit list */
1033 tx_command= prev_txp->tx_command;
1034 assert(tx_command == (TXC_EL | CBL_XMIT));
1035 prev_txp->tx_command= CBL_XMIT;
1036 fp->fxp_tx_head= fxp_tx_head;
1039 fp->fxp_flags |= FF_PACK_SENT;
1041 /* If the interrupt handler called, don't send a reply. The reply
1042 * will be sent after all interrupts are handled.
1044 if (from_int)
1045 return;
1046 reply(fp);
1047 return;
1049 suspend:
1050 if (from_int)
1051 panic("fxp: should not be sending");
1053 fp->fxp_tx_mess= *mp;
1054 reply(fp);
1057 /*===========================================================================*
1058 * fxp_readv_s *
1059 *===========================================================================*/
1060 static void fxp_readv_s(mp, from_int)
1061 message *mp;
1062 int from_int;
1064 int i, j, n, o, r, s, count, size, fxp_rx_head, fxp_rx_nbuf;
1065 endpoint_t iov_endpt;
1066 cp_grant_id_t iov_grant;
1067 port_t port;
1068 unsigned packlen;
1069 vir_bytes iov_offset;
1070 u16_t rfd_status;
1071 u16_t rfd_res;
1072 u8_t scb_status;
1073 fxp_t *fp;
1074 iovec_s_t *iovp;
1075 struct rfd *rfdp, *prev_rfdp;
1077 fp= fxp_state;
1079 count = mp->DL_COUNT;
1080 fp->fxp_client= mp->m_source;
1082 assert(fp->fxp_mode == FM_ENABLED);
1083 assert(fp->fxp_flags & FF_ENABLED);
1085 port= fp->fxp_base_port;
1087 fxp_rx_head= fp->fxp_rx_head;
1088 rfdp= &fp->fxp_rx_buf[fxp_rx_head];
1090 rfd_status= rfdp->rfd_status;
1091 if (!(rfd_status & RFDS_C))
1093 /* Receive buffer is empty, suspend */
1094 goto suspend;
1097 if (!(rfd_status & RFDS_OK))
1099 /* Not OK? What happened? */
1100 assert(0);
1102 else
1104 assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
1105 RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
1106 RFDS_RXERR)));
1108 rfd_res= rfdp->rfd_res;
1109 assert(rfd_res & RFDR_EOF);
1110 assert(rfd_res & RFDR_F);
1112 packlen= rfd_res & RFDSZ_SIZE;
1114 iov_endpt = mp->m_source;
1115 iov_grant = mp->DL_GRANT;
1117 size= 0;
1118 o= 0;
1119 iov_offset= 0;
1120 for (i= 0; i<count; i += IOVEC_NR,
1121 iov_offset += IOVEC_NR * sizeof(fp->fxp_iovec_s[0]))
1123 n= IOVEC_NR;
1124 if (i+n > count)
1125 n= count-i;
1126 r= sys_safecopyfrom(iov_endpt, iov_grant, iov_offset,
1127 (vir_bytes)fp->fxp_iovec_s,
1128 n * sizeof(fp->fxp_iovec_s[0]));
1129 if (r != OK)
1130 panic("fxp_readv_s: sys_safecopyfrom failed: %d", r);
1132 for (j= 0, iovp= fp->fxp_iovec_s; j<n; j++, iovp++)
1134 s= iovp->iov_size;
1135 if (size + s > packlen)
1137 assert(packlen > size);
1138 s= packlen-size;
1141 r= sys_safecopyto(iov_endpt, iovp->iov_grant,
1142 0, (vir_bytes)(rfdp->rfd_buf+o), s);
1143 if (r != OK)
1145 panic("fxp_readv: sys_safecopyto failed: %d", r);
1148 size += s;
1149 if (size == packlen)
1150 break;
1151 o += s;
1153 if (size == packlen)
1154 break;
1156 if (size < packlen)
1158 assert(0);
1161 fp->fxp_read_s= packlen;
1162 fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
1164 /* Re-init the current buffer */
1165 rfdp->rfd_status= 0;
1166 rfdp->rfd_command= RFDC_EL;
1167 rfdp->rfd_reserved= 0;
1168 rfdp->rfd_res= 0;
1169 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1171 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1172 if (fxp_rx_head == 0)
1174 prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
1176 else
1177 prev_rfdp= &rfdp[-1];
1179 assert(prev_rfdp->rfd_command & RFDC_EL);
1180 prev_rfdp->rfd_command &= ~RFDC_EL;
1182 fxp_rx_head++;
1183 if (fxp_rx_head == fxp_rx_nbuf)
1184 fxp_rx_head= 0;
1185 assert(fxp_rx_head < fxp_rx_nbuf);
1186 fp->fxp_rx_head= fxp_rx_head;
1188 if (!from_int)
1189 reply(fp);
1191 return;
1193 suspend:
1194 if (fp->fxp_rx_need_restart)
1196 fp->fxp_rx_need_restart= 0;
1198 /* Check the status of the RU */
1199 scb_status= fxp_inb(port, SCB_STATUS);
1200 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
1202 /* Race condition? */
1203 printf("fxp_readv: restart race: 0x%x\n",
1204 scb_status);
1205 assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
1207 else
1209 fxp_restart_ru(fp);
1212 if (from_int)
1214 assert(fp->fxp_flags & FF_READING);
1216 /* No need to store any state */
1217 return;
1220 fp->fxp_rx_mess= *mp;
1221 assert(!(fp->fxp_flags & FF_READING));
1222 fp->fxp_flags |= FF_READING;
1224 reply(fp);
1227 /*===========================================================================*
1228 * fxp_do_conf *
1229 *===========================================================================*/
1230 static void fxp_do_conf(fp)
1231 fxp_t *fp;
1233 int r;
1234 phys_bytes bus_addr;
1236 /* Configure device */
1237 tmpbufp->cc.cc_status= 0;
1238 tmpbufp->cc.cc_command= CBL_C_EL | CBL_CONF;
1239 tmpbufp->cc.cc_linkaddr= 0;
1240 memcpy(tmpbufp->cc.cc_bytes, fp->fxp_conf_bytes,
1241 sizeof(tmpbufp->cc.cc_bytes));
1243 r= sys_umap(SELF, VM_D, (vir_bytes)&tmpbufp->cc,
1244 (phys_bytes)sizeof(tmpbufp->cc), &bus_addr);
1245 if (r != OK)
1246 panic("sys_umap failed: %d", r);
1248 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
1250 /* Wait for CU command to complete */
1251 SPIN_UNTIL(tmpbufp->cc.cc_status & CBL_F_C, 100000);
1253 if (!(tmpbufp->cc.cc_status & CBL_F_C))
1254 panic("fxp_do_conf: CU command failed to complete");
1255 if (!(tmpbufp->cc.cc_status & CBL_F_OK))
1256 panic("fxp_do_conf: CU command failed");
1260 /*===========================================================================*
1261 * fxp_cu_ptr_cmd *
1262 *===========================================================================*/
1263 static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
1264 fxp_t *fp;
1265 int cmd;
1266 phys_bytes bus_addr;
1267 int check_idle;
1269 spin_t spin;
1270 port_t port;
1271 u8_t scb_cmd;
1273 port= fp->fxp_base_port;
1275 if (check_idle)
1277 /* Consistency check. Make sure that CU is idle */
1278 if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
1279 panic("fxp_cu_ptr_cmd: CU is not idle");
1282 fxp_outl(port, SCB_POINTER, bus_addr);
1283 fxp_outb(port, SCB_CMD, cmd);
1285 /* What is a reasonable time-out? There is nothing in the
1286 * documentation. 1 ms should be enough. We use 100 ms.
1288 spin_init(&spin, 100000);
1289 do {
1290 /* Wait for CU command to be accepted */
1291 scb_cmd= fxp_inb(port, SCB_CMD);
1292 if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
1293 break;
1294 } while (spin_check(&spin));
1296 if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
1297 panic("fxp_cu_ptr_cmd: CU does not accept command");
1300 /*===========================================================================*
1301 * fxp_ru_ptr_cmd *
1302 *===========================================================================*/
1303 static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
1304 fxp_t *fp;
1305 int cmd;
1306 phys_bytes bus_addr;
1307 int check_idle;
1309 spin_t spin;
1310 port_t port;
1311 u8_t scb_cmd;
1313 port= fp->fxp_base_port;
1315 if (check_idle)
1317 /* Consistency check, make sure that RU is idle */
1318 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
1319 panic("fxp_ru_ptr_cmd: RU is not idle");
1322 fxp_outl(port, SCB_POINTER, bus_addr);
1323 fxp_outb(port, SCB_CMD, cmd);
1325 spin_init(&spin, 1000);
1326 do {
1327 /* Wait for RU command to be accepted */
1328 scb_cmd= fxp_inb(port, SCB_CMD);
1329 if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
1330 break;
1331 } while (spin_check(&spin));
1333 if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
1334 panic("fxp_ru_ptr_cmd: RU does not accept command");
1337 /*===========================================================================*
1338 * fxp_restart_ru *
1339 *===========================================================================*/
1340 static void fxp_restart_ru(fp)
1341 fxp_t *fp;
1343 int i, fxp_rx_nbuf;
1344 port_t port;
1345 struct rfd *rfdp;
1347 port= fp->fxp_base_port;
1349 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1350 for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
1352 rfdp->rfd_status= 0;
1353 rfdp->rfd_command= 0;
1354 if (i == fp->fxp_rx_nbuf-1)
1355 rfdp->rfd_command= RFDC_EL;
1356 rfdp->rfd_reserved= 0;
1357 rfdp->rfd_res= 0;
1358 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1360 fp->fxp_rx_head= 0;
1362 /* Make sure that RU is in the 'No resources' state */
1363 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
1364 panic("fxp_restart_ru: RU is in an unexpected state");
1366 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
1367 FALSE /* do not check idle */);
1370 /*===========================================================================*
1371 * fxp_getstat_s *
1372 *===========================================================================*/
1373 static void fxp_getstat_s(message *mp)
1375 int r;
1376 fxp_t *fp;
1377 u32_t *p;
1378 eth_stat_t stats;
1380 fp= fxp_state;
1382 assert(fp->fxp_mode == FM_ENABLED);
1383 assert(fp->fxp_flags & FF_ENABLED);
1385 p= &fp->fxp_stat.sc_tx_fcp;
1386 *p= 0;
1388 /* The dump commmand doesn't take a pointer. Setting a pointer
1389 * doesn't hurt though.
1391 fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
1393 /* Wait for CU command to complete */
1394 SPIN_UNTIL(*p != 0, 1000);
1396 if (*p == 0)
1397 panic("fxp_getstat: CU command failed to complete");
1398 if (*p != SCM_DSC)
1399 panic("fxp_getstat: bad magic");
1401 stats.ets_recvErr=
1402 fp->fxp_stat.sc_rx_crc +
1403 fp->fxp_stat.sc_rx_align +
1404 fp->fxp_stat.sc_rx_resource +
1405 fp->fxp_stat.sc_rx_overrun +
1406 fp->fxp_stat.sc_rx_cd +
1407 fp->fxp_stat.sc_rx_short;
1408 stats.ets_sendErr=
1409 fp->fxp_stat.sc_tx_maxcol +
1410 fp->fxp_stat.sc_tx_latecol +
1411 fp->fxp_stat.sc_tx_crs;
1412 stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
1413 stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
1414 stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
1415 stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
1416 stats.ets_packetR= fp->fxp_stat.sc_rx_good;
1417 stats.ets_packetT= fp->fxp_stat.sc_tx_good;
1418 stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
1419 stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
1420 stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
1421 stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
1422 stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
1423 stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
1424 stats.ets_CDheartbeat= 0;
1425 stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
1427 r= sys_safecopyto(mp->m_source, mp->DL_GRANT, 0, (vir_bytes)&stats,
1428 sizeof(stats));
1429 if (r != OK)
1430 panic("fxp_getstat_s: sys_safecopyto failed: %d", r);
1432 mp->m_type= DL_STAT_REPLY;
1433 r= send(mp->m_source, mp);
1434 if (r != OK)
1435 panic("fxp_getstat_s: send failed: %d", r);
1438 /*===========================================================================*
1439 * fxp_handler *
1440 *===========================================================================*/
1441 static void fxp_handler(fxp_t *fp)
1443 int port;
1444 u16_t isr;
1446 RAND_UPDATE
1448 port= fp->fxp_base_port;
1450 /* Ack interrupt */
1451 isr= fxp_inb(port, SCB_INT_STAT);
1452 fxp_outb(port, SCB_INT_STAT, isr);
1454 if (isr & SIS_FR)
1456 isr &= ~SIS_FR;
1458 if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
1460 fp->fxp_got_int= TRUE;
1461 interrupt(fxp_tasknr);
1464 if (isr & SIS_CNA)
1466 isr &= ~SIS_CNA;
1467 if (!fp->fxp_tx_idle)
1469 fp->fxp_send_int= TRUE;
1470 if (!fp->fxp_got_int)
1472 fp->fxp_got_int= TRUE;
1473 interrupt(fxp_tasknr);
1477 if (isr & SIS_RNR)
1479 isr &= ~SIS_RNR;
1481 /* Assume that receive buffer is full of packets. fxp_readv
1482 * will restart the RU.
1484 fp->fxp_rx_need_restart= 1;
1486 if (isr)
1488 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
1489 isr);
1493 /*===========================================================================*
1494 * fxp_check_ints *
1495 *===========================================================================*/
1496 static void fxp_check_ints(fxp_t *fp)
1498 int n, fxp_flags, prev_tail;
1499 int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
1500 port_t port;
1501 u32_t busaddr;
1502 u16_t tx_status;
1503 u8_t scb_status;
1504 struct tx *txp;
1506 fxp_flags= fp->fxp_flags;
1508 if (fxp_flags & FF_READING)
1510 if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
1511 ; /* Nothing */
1512 else
1514 fxp_readv_s(&fp->fxp_rx_mess, TRUE /* from int */);
1517 if (fp->fxp_tx_idle)
1518 ; /* Nothing to do */
1519 else if (fp->fxp_send_int)
1521 fp->fxp_send_int= FALSE;
1522 fxp_tx_tail= fp->fxp_tx_tail;
1523 fxp_tx_nbuf= fp->fxp_tx_nbuf;
1524 n= 0;
1525 for (;;)
1527 txp= &fp->fxp_tx_buf[fxp_tx_tail];
1528 tx_status= txp->tx_status;
1529 if (!(tx_status & TXS_C))
1530 break;
1532 n++;
1534 assert(tx_status & TXS_OK);
1535 if (tx_status & TXS_U)
1537 fxp_tx_threshold= fp->fxp_tx_threshold;
1538 if (fxp_tx_threshold < TXTT_MAX)
1540 fxp_tx_threshold++;
1541 fp->fxp_tx_threshold= fxp_tx_threshold;
1543 printf(
1544 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
1545 fxp_tx_threshold);
1548 if (txp->tx_command & TXC_EL)
1550 fp->fxp_tx_idle= 1;
1551 break;
1554 fxp_tx_tail++;
1555 if (fxp_tx_tail == fxp_tx_nbuf)
1556 fxp_tx_tail= 0;
1557 assert(fxp_tx_tail < fxp_tx_nbuf);
1560 if (fp->fxp_need_conf)
1562 /* Check the status of the CU */
1563 port= fp->fxp_base_port;
1564 scb_status= fxp_inb(port, SCB_STATUS);
1565 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
1567 /* Nothing to do */
1568 printf("scb_status = 0x%x\n", scb_status);
1570 else
1572 printf("fxp_check_ints: fxp_need_conf\n");
1573 fp->fxp_need_conf= FALSE;
1574 fxp_do_conf(fp);
1578 if (n)
1580 if (!fp->fxp_tx_idle)
1582 fp->fxp_tx_tail= fxp_tx_tail;
1584 /* Check the status of the CU */
1585 port= fp->fxp_base_port;
1586 scb_status= fxp_inb(port, SCB_STATUS);
1587 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
1589 /* Nothing to do */
1590 printf("scb_status = 0x%x\n",
1591 scb_status);
1594 else
1596 if (fxp_tx_tail == 0)
1597 prev_tail= fxp_tx_nbuf-1;
1598 else
1599 prev_tail= fxp_tx_tail-1;
1600 busaddr= fp->fxp_tx_buf[prev_tail].
1601 tx_linkaddr;
1603 fxp_cu_ptr_cmd(fp, SC_CU_START,
1604 busaddr, 1 /* check idle */);
1608 if (fp->fxp_flags & FF_SEND_AVAIL)
1610 fxp_writev_s(&fp->fxp_tx_mess,
1611 TRUE /* from int */);
1616 if (fp->fxp_report_link)
1617 fxp_report_link(fp);
1619 if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
1620 reply(fp);
1623 /*===========================================================================*
1624 * fxp_watchdog_f *
1625 *===========================================================================*/
1626 static void fxp_watchdog_f(tp)
1627 timer_t *tp;
1629 fxp_t *fp;
1631 set_timer(&fxp_watchdog, system_hz, fxp_watchdog_f, 0);
1633 fp= fxp_state;
1634 if (fp->fxp_mode != FM_ENABLED)
1635 return;
1637 /* Handle race condition, MII interface might be busy */
1638 if(!fp->fxp_mii_busy)
1640 /* Check the link status. */
1641 if (fxp_link_changed(fp))
1643 #if VERBOSE
1644 printf("fxp_watchdog_f: link changed\n");
1645 #endif
1646 fp->fxp_report_link= TRUE;
1647 fp->fxp_got_int= TRUE;
1648 interrupt(fxp_tasknr);
1652 if (!(fp->fxp_flags & FF_SEND_AVAIL))
1654 /* Assume that an idle system is alive */
1655 fp->fxp_tx_alive= TRUE;
1656 return;
1658 if (fp->fxp_tx_alive)
1660 fp->fxp_tx_alive= FALSE;
1661 return;
1664 fp->fxp_need_reset= TRUE;
1665 fp->fxp_got_int= TRUE;
1666 interrupt(fxp_tasknr);
1669 /*===========================================================================*
1670 * fxp_link_changed *
1671 *===========================================================================*/
1672 static int fxp_link_changed(fp)
1673 fxp_t *fp;
1675 u16_t scr;
1677 scr= mii_read(fp, MII_SCR);
1678 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
1680 return (fp->fxp_mii_scr != scr);
1683 /*===========================================================================*
1684 * fxp_report_link *
1685 *===========================================================================*/
1686 static void fxp_report_link(fxp_t *fp)
1688 u16_t mii_ctrl, mii_status, mii_id1, mii_id2,
1689 mii_ana, mii_anlpa, mii_ane, mii_extstat,
1690 mii_ms_ctrl, mii_ms_status, scr;
1691 u32_t oui;
1692 int model, rev;
1693 int f, link_up;
1695 fp->fxp_report_link= FALSE;
1697 scr= mii_read(fp, MII_SCR);
1698 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
1699 fp->fxp_mii_scr= scr;
1701 mii_ctrl= mii_read(fp, MII_CTRL);
1702 mii_read(fp, MII_STATUS); /* The status reg is latched, read twice */
1703 mii_status= mii_read(fp, MII_STATUS);
1704 mii_id1= mii_read(fp, MII_PHYID_H);
1705 mii_id2= mii_read(fp, MII_PHYID_L);
1706 mii_ana= mii_read(fp, MII_ANA);
1707 mii_anlpa= mii_read(fp, MII_ANLPA);
1708 mii_ane= mii_read(fp, MII_ANE);
1709 if (mii_status & MII_STATUS_EXT_STAT)
1710 mii_extstat= mii_read(fp, MII_EXT_STATUS);
1711 else
1712 mii_extstat= 0;
1713 if (fp->fxp_ms_regs)
1715 mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
1716 mii_ms_status= mii_read(fp, MII_MS_STATUS);
1718 else
1720 mii_ms_ctrl= 0;
1721 mii_ms_status= 0;
1724 /* How do we know about the link status? */
1725 link_up= !!(mii_status & MII_STATUS_LS);
1727 fp->fxp_link_up= link_up;
1728 if (!link_up)
1730 #if VERBOSE
1731 printf("%s: link down\n", fp->fxp_name);
1732 #endif
1733 return;
1736 oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) |
1737 ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
1738 model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
1739 rev= (mii_id2 & MII_PL_REV_MASK);
1741 #if VERBOSE
1742 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
1743 #endif
1745 if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
1747 printf("%s: PHY: ", fp->fxp_name);
1748 f= 1;
1749 if (mii_ctrl & MII_CTRL_LB)
1751 printf("loopback mode");
1752 f= 0;
1754 if (mii_ctrl & MII_CTRL_PD)
1756 if (!f) printf(", ");
1757 f= 0;
1758 printf("powered down");
1760 if (mii_ctrl & MII_CTRL_ISO)
1762 if (!f) printf(", ");
1763 f= 0;
1764 printf("isolated");
1766 printf("\n");
1767 return;
1769 if (!(mii_ctrl & MII_CTRL_ANE))
1771 printf("%s: manual config: ", fp->fxp_name);
1772 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
1774 case MII_CTRL_SP_10: printf("10 Mbps"); break;
1775 case MII_CTRL_SP_100: printf("100 Mbps"); break;
1776 case MII_CTRL_SP_1000: printf("1000 Mbps"); break;
1777 case MII_CTRL_SP_RES: printf("reserved speed"); break;
1779 if (mii_ctrl & MII_CTRL_DM)
1780 printf(", full duplex");
1781 else
1782 printf(", half duplex");
1783 printf("\n");
1784 return;
1787 if (!debug) goto resspeed;
1789 printf("%s: ", fp->fxp_name);
1790 mii_print_stat_speed(mii_status, mii_extstat);
1791 printf("\n");
1793 if (!(mii_status & MII_STATUS_ANC))
1794 printf("%s: auto-negotiation not complete\n", fp->fxp_name);
1795 if (mii_status & MII_STATUS_RF)
1796 printf("%s: remote fault detected\n", fp->fxp_name);
1797 if (!(mii_status & MII_STATUS_ANA))
1799 printf("%s: local PHY has no auto-negotiation ability\n",
1800 fp->fxp_name);
1802 if (!(mii_status & MII_STATUS_LS))
1803 printf("%s: link down\n", fp->fxp_name);
1804 if (mii_status & MII_STATUS_JD)
1805 printf("%s: jabber condition detected\n", fp->fxp_name);
1806 if (!(mii_status & MII_STATUS_EC))
1808 printf("%s: no extended register set\n", fp->fxp_name);
1809 goto resspeed;
1811 if (!(mii_status & MII_STATUS_ANC))
1812 goto resspeed;
1814 printf("%s: local cap.: ", fp->fxp_name);
1815 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
1817 printf("1000 Mbps: T-");
1818 switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
1820 case MII_MSC_1000T_FD: printf("FD"); break;
1821 case MII_MSC_1000T_HD: printf("HD"); break;
1822 default: printf("FD/HD"); break;
1824 if (mii_ana)
1825 printf(", ");
1827 mii_print_techab(mii_ana);
1828 printf("\n");
1830 if (mii_ane & MII_ANE_PDF)
1831 printf("%s: parallel detection fault\n", fp->fxp_name);
1832 if (!(mii_ane & MII_ANE_LPANA))
1834 printf("%s: link-partner does not support auto-negotiation\n",
1835 fp->fxp_name);
1836 goto resspeed;
1839 printf("%s: remote cap.: ", fp->fxp_name);
1840 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
1841 if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
1843 printf("1000 Mbps: T-");
1844 switch(mii_ms_status &
1845 (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
1847 case MII_MSS_LP1000T_FD: printf("FD"); break;
1848 case MII_MSS_LP1000T_HD: printf("HD"); break;
1849 default: printf("FD/HD"); break;
1851 if (mii_anlpa)
1852 printf(", ");
1854 mii_print_techab(mii_anlpa);
1855 printf("\n");
1857 if (fp->fxp_ms_regs)
1859 printf("%s: ", fp->fxp_name);
1860 if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
1862 printf("manual %s",
1863 (mii_ms_ctrl & MII_MSC_MS_VAL) ?
1864 "MASTER" : "SLAVE");
1866 else
1868 printf("%s device",
1869 (mii_ms_ctrl & MII_MSC_MULTIPORT) ?
1870 "multiport" : "single-port");
1872 if (mii_ms_ctrl & MII_MSC_RES)
1873 printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
1874 printf(": ");
1875 if (mii_ms_status & MII_MSS_FAULT)
1876 printf("M/S config fault");
1877 else if (mii_ms_status & MII_MSS_MASTER)
1878 printf("MASTER");
1879 else
1880 printf("SLAVE");
1881 printf("\n");
1884 if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
1886 if (!(mii_ms_status & MII_MSS_LOCREC))
1888 printf("%s: local receiver not OK\n",
1889 fp->fxp_name);
1891 if (!(mii_ms_status & MII_MSS_REMREC))
1893 printf("%s: remote receiver not OK\n",
1894 fp->fxp_name);
1897 if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
1899 printf("%s", fp->fxp_name);
1900 if (mii_ms_status & MII_MSS_RES)
1901 printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
1902 if (mii_ms_status & MII_MSS_IDLE_ERR)
1904 printf(" idle error %d",
1905 mii_ms_status & MII_MSS_IDLE_ERR);
1907 printf("\n");
1910 resspeed:
1911 #if VERBOSE
1912 printf("%s: link up, %d Mbps, %s duplex\n",
1913 fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
1914 (scr & MII_SCR_FD) ? "full" : "half");
1915 #endif
1919 /*===========================================================================*
1920 * reply *
1921 *===========================================================================*/
1922 static void reply(fp)
1923 fxp_t *fp;
1925 message reply;
1926 int flags;
1927 int r;
1929 flags = DL_NOFLAGS;
1930 if (fp->fxp_flags & FF_PACK_SENT)
1931 flags |= DL_PACK_SEND;
1932 if (fp->fxp_flags & FF_PACK_RECV)
1933 flags |= DL_PACK_RECV;
1935 reply.m_type = DL_TASK_REPLY;
1936 reply.DL_FLAGS = flags;
1937 reply.DL_COUNT = fp->fxp_read_s;
1939 r= send(fp->fxp_client, &reply);
1941 if (r < 0)
1942 panic("fxp: send failed: %d", r);
1944 fp->fxp_read_s = 0;
1945 fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
1948 /*===========================================================================*
1949 * mess_reply *
1950 *===========================================================================*/
1951 static void mess_reply(req, reply_mess)
1952 message *req;
1953 message *reply_mess;
1955 if (send(req->m_source, reply_mess) != OK)
1956 panic("fxp: unable to mess_reply");
1959 /*===========================================================================*
1960 * eeprom_read *
1961 *===========================================================================*/
1962 static u16_t eeprom_read(fp, reg)
1963 fxp_t *fp;
1964 int reg;
1966 port_t port;
1967 u16_t v;
1968 int b, i, alen;
1970 alen= fp->fxp_ee_addrlen;
1971 if (!alen)
1973 eeprom_addrsize(fp);
1974 alen= fp->fxp_ee_addrlen;
1975 assert(alen == 6 || alen == 8);
1978 port= fp->fxp_base_port;
1980 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
1981 v= EEPROM_READ_PREFIX;
1982 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
1984 b= ((v & (1 << i)) ? CE_EEDI : 0);
1985 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
1986 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
1987 micro_delay(EESK_PERIOD/2+1);
1988 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
1989 micro_delay(EESK_PERIOD/2+1);
1992 v= reg;
1993 for (i= alen-1; i >= 0; i--)
1995 b= ((v & (1 << i)) ? CE_EEDI : 0);
1996 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
1997 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
1998 micro_delay(EESK_PERIOD/2+1);
1999 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2000 micro_delay(EESK_PERIOD/2+1);
2003 v= 0;
2004 for (i= 0; i<16; i++)
2006 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2007 micro_delay(EESK_PERIOD/2+1);
2008 b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
2009 v= (v << 1) | b;
2010 fxp_outb(port, CSR_EEPROM, CE_EECS );
2011 micro_delay(EESK_PERIOD/2+1);
2013 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2014 micro_delay(EECS_DELAY);
2016 return v;
2019 /*===========================================================================*
2020 * eeprom_addrsize *
2021 *===========================================================================*/
2022 static void eeprom_addrsize(fp)
2023 fxp_t *fp;
2025 port_t port;
2026 u16_t v;
2027 int b, i;
2029 port= fp->fxp_base_port;
2031 /* Try to find out the size of the EEPROM */
2032 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
2033 v= EEPROM_READ_PREFIX;
2034 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
2036 b= ((v & (1 << i)) ? CE_EEDI : 0);
2037 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2038 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2039 micro_delay(EESK_PERIOD/2+1);
2040 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2041 micro_delay(EESK_PERIOD/2+1);
2044 for (i= 0; i<32; i++)
2046 b= 0;
2047 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2048 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2049 micro_delay(EESK_PERIOD/2+1);
2050 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2051 micro_delay(EESK_PERIOD/2+1);
2052 v= fxp_inb(port, CSR_EEPROM);
2053 if (!(v & CE_EEDO))
2054 break;
2056 if (i >= 32)
2057 panic("eeprom_addrsize: failed");
2058 fp->fxp_ee_addrlen= i+1;
2060 /* Discard 16 data bits */
2061 for (i= 0; i<16; i++)
2063 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2064 micro_delay(EESK_PERIOD/2+1);
2065 fxp_outb(port, CSR_EEPROM, CE_EECS );
2066 micro_delay(EESK_PERIOD/2+1);
2068 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2069 micro_delay(EECS_DELAY);
2071 #if VERBOSE
2072 printf("%s EEPROM address length: %d\n",
2073 fp->fxp_name, fp->fxp_ee_addrlen);
2074 #endif
2077 /*===========================================================================*
2078 * mii_read *
2079 *===========================================================================*/
2080 static u16_t mii_read(fp, reg)
2081 fxp_t *fp;
2082 int reg;
2084 spin_t spin;
2085 port_t port;
2086 u32_t v;
2088 port= fp->fxp_base_port;
2090 assert(!fp->fxp_mii_busy);
2091 fp->fxp_mii_busy++;
2093 if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
2094 panic("mii_read: MDI not ready");
2095 fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
2096 (reg << CM_REG_SHIFT));
2098 spin_init(&spin, 100000);
2099 do {
2100 v= fxp_inl(port, CSR_MDI_CTL);
2101 if (v & CM_READY)
2102 break;
2103 } while (spin_check(&spin));
2105 if (!(v & CM_READY))
2106 panic("mii_read: MDI not ready after command");
2108 fp->fxp_mii_busy--;
2109 assert(!fp->fxp_mii_busy);
2111 return v & CM_DATA_MASK;
2114 static u8_t do_inb(port_t port)
2116 int r;
2117 u32_t value;
2119 r= sys_inb(port, &value);
2120 if (r != OK)
2121 panic("sys_inb failed: %d", r);
2122 return value;
2125 static u32_t do_inl(port_t port)
2127 int r;
2128 u32_t value;
2130 r= sys_inl(port, &value);
2131 if (r != OK)
2132 panic("sys_inl failed: %d", r);
2133 return value;
2136 static void do_outb(port_t port, u8_t value)
2138 int r;
2140 r= sys_outb(port, value);
2141 if (r != OK)
2142 panic("sys_outb failed: %d", r);
2145 static void do_outl(port_t port, u32_t value)
2147 int r;
2149 r= sys_outl(port, value);
2150 if (r != OK)
2151 panic("sys_outl failed: %d", r);
2154 static void tell_dev(buf, size, pci_bus, pci_dev, pci_func)
2155 vir_bytes buf;
2156 size_t size;
2157 int pci_bus;
2158 int pci_dev;
2159 int pci_func;
2161 int r;
2162 endpoint_t dev_e;
2163 message m;
2165 r= ds_retrieve_label_endpt("amddev", &dev_e);
2166 if (r != OK)
2168 #if 0
2169 printf(
2170 "fxp`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n",
2172 #endif
2173 return;
2176 m.m_type= IOMMU_MAP;
2177 m.m2_i1= pci_bus;
2178 m.m2_i2= pci_dev;
2179 m.m2_i3= pci_func;
2180 m.m2_l1= buf;
2181 m.m2_l2= size;
2183 r= sendrec(dev_e, &m);
2184 if (r != OK)
2186 printf("fxp`tell_dev: sendrec to %d failed: %d\n",
2187 dev_e, r);
2188 return;
2190 if (m.m_type != OK)
2192 printf("fxp`tell_dev: dma map request failed: %d\n",
2193 m.m_type);
2194 return;
2199 * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $