source: trunk/minix/drivers/fxp/fxp.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 60.1 KB
Line 
1/*
2 * fxp.c
3 *
4 * This file contains an ethernet device driver for Intel 82557, 82558,
5 * 82559, 82550, and 82562 fast ethernet controllers.
6 *
7 * The valid messages and their parameters are:
8 *
9 * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
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_READ | port nr | proc nr | count | | address |
18 * |------------|----------|---------|----------|---------|---------|
19 * | DL_READV | port nr | proc nr | count | | address |
20 * |------------|----------|---------|----------|---------|---------|
21 * | DL_INIT | port nr | proc nr | mode | | address |
22 * |------------|----------|---------|----------|---------|---------|
23 * | DL_GETSTAT | port nr | proc nr | | | address |
24 * |------------|----------|---------|----------|---------|---------|
25 * | DL_STOP | port_nr | | | | |
26 * |------------|----------|---------|----------|---------|---------|
27 *
28 * The messages sent are:
29 *
30 * m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
31 * |-------------+----------+---------+----------+---------+---------|
32 * |DL_TASK_REPLY| port nr | proc nr | rd-count | err|stat| clock |
33 * |-------------+----------+---------+----------+---------+---------|
34 *
35 * m_type m3_i1 m3_i2 m3_ca1
36 * |-------------+---------+-----------+---------------|
37 * |DL_INIT_REPLY| port nr | last port | ethernet addr |
38 * |-------------+---------+-----------+---------------|
39 *
40 * Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
41 */
42
43#include "../drivers.h"
44
45#include <stdlib.h>
46#include <net/hton.h>
47#include <net/gen/ether.h>
48#include <net/gen/eth_io.h>
49#include <ibm/pci.h>
50
51#include <timers.h>
52
53#define tmra_ut timer_t
54#define tmra_inittimer(tp) tmr_inittimer(tp)
55#define Proc_number(p) proc_number(p)
56#define debug 0
57#define RAND_UPDATE /**/
58#define printW() ((void)0)
59#define vm_1phys2bus(p) (p)
60
61#include "assert.h"
62#include "fxp.h"
63#include "mii.h"
64
65/* Number of receive buffers */
66#define N_RX_BUF 40
67
68/* Number of transmit buffers */
69#define N_TX_BUF 4
70
71/* I/O vectors are handled IOVEC_NR entries at a time. */
72#define IOVEC_NR 16
73
74/* Configuration */
75#define FXP_ENVVAR "FXPETH"
76
77struct pcitab
78{
79 u16_t vid;
80 u16_t did;
81 int checkclass;
82};
83
84PRIVATE struct pcitab pcitab_fxp[]=
85{
86 { 0x8086, 0x1229, 0 }, /* Intel 82557, etc. */
87 { 0x8086, 0x2449, 0 }, /* Intel 82801BA/BAM/CA/CAM */
88
89 { 0x0000, 0x0000, 0 }
90};
91
92#define FXP_PORT_NR 1 /* Minix */
93
94typedef int irq_hook_t;
95
96/* Translate a pointer to a field in a structure to a pointer to the structure
97 * itself. So it translates '&struct_ptr->field' back to 'struct_ptr'.
98 */
99#define structof(type, field, ptr) \
100 ((type *) (((char *) (ptr)) - offsetof(type, field)))
101
102#define MICROS_TO_TICKS(m) (((m)*HZ/1000000)+1)
103
104static timer_t *fxp_timers= NULL;
105static clock_t fxp_next_timeout= 0;
106
107static void micro_delay(unsigned long usecs);
108
109/* ignore interrupt for the moment */
110#define interrupt(x) 0
111
112char buffer[70*1024];
113
114typedef struct fxp
115{
116 port_t fxp_base_port;
117 int fxp_mode;
118 int fxp_got_int;
119 int fxp_send_int;
120 int fxp_flags;
121 int fxp_client;
122 int fxp_features; /* Needed? */
123 int fxp_irq;
124 int fxp_type; /* What kind of hardware */
125 int fxp_ee_addrlen; /* #EEPROM address bits */
126 int fxp_tx_alive;
127 int fxp_need_reset;
128
129 /* Rx */
130 vir_bytes fxp_read_s;
131 int fxp_rx_nbuf;
132 int fxp_rx_bufsize;
133 struct rfd *fxp_rx_buf;
134 phys_bytes fxp_rx_busaddr;
135 int fxp_rx_head;
136 int fxp_rx_need_restart;
137 int fxp_need_conf; /* Re-configure after draining send
138 * queue
139 */
140
141 /* Tx */
142 int fxp_tx_nbuf;
143 int fxp_tx_bufsize;
144 struct tx *fxp_tx_buf;
145 phys_bytes fxp_tx_busaddr;
146 int fxp_tx_idle;
147 int fxp_tx_head;
148 int fxp_tx_tail;
149 int fxp_tx_threshold;
150
151 /* Link status */
152 int fxp_report_link;
153 int fxp_link_up;
154 int fxp_mii_busy;
155 u16_t fxp_mii_scr;
156
157 /* PCI related */
158 int fxp_seen; /* TRUE iff device available */
159 u8_t fxp_pcibus;
160 u8_t fxp_pcidev;
161 u8_t fxp_pcifunc;
162
163 /* 'large' items */
164 irq_hook_t fxp_hook;
165 ether_addr_t fxp_address;
166 message fxp_rx_mess;
167 message fxp_tx_mess;
168 struct sc fxp_stat;
169 u8_t fxp_conf_bytes[CC_BYTES_NR];
170 char fxp_name[sizeof("fxp#n")];
171 iovec_t fxp_iovec[IOVEC_NR];
172}
173fxp_t;
174
175/* fxp_mode */
176#define FM_DISABLED 0x0
177#define FM_ENABLED 0x1
178
179/* fxp_flags */
180#define FF_EMPTY 0x000
181#define FF_PACK_SENT 0x001
182#define FF_PACK_RECV 0x002
183#define FF_SEND_AVAIL 0x004
184#define FF_READING 0x010
185#define FF_PROMISC 0x040
186#define FF_MULTI 0x080
187#define FF_BROAD 0x100
188#define FF_ENABLED 0x200
189
190/* fxp_features */
191#define FFE_NONE 0x0
192
193/* fxp_type */
194#define FT_UNKNOWN 0x0
195#define FT_82557 0x1
196#define FT_82558A 0x2
197#define FT_82559 0x4
198
199static fxp_t fxp_table[FXP_PORT_NR];
200
201static int fxp_tasknr= ANY;
202static u16_t eth_ign_proto;
203static tmra_ut fxp_watchdog;
204static char *progname;
205
206extern int errno;
207
208#define fxp_inb(port, offset) (do_inb((port) + (offset)))
209#define fxp_inw(port, offset) (do_inw((port) + (offset)))
210#define fxp_inl(port, offset) (do_inl((port) + (offset)))
211#define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
212#define fxp_outw(port, offset, value) (do_outw((port) + (offset), (value)))
213#define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
214
215_PROTOTYPE( static void fxp_init, (message *mp) );
216_PROTOTYPE( static void fxp_pci_conf, (void) );
217_PROTOTYPE( static int fxp_probe, (fxp_t *fp) );
218_PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp) );
219_PROTOTYPE( static void fxp_init_hw, (fxp_t *fp) );
220_PROTOTYPE( static void fxp_init_buf, (fxp_t *fp) );
221_PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp) );
222_PROTOTYPE( static void fxp_confaddr, (fxp_t *fp) );
223_PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp) );
224_PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
225 int vectored) );
226_PROTOTYPE( static void fxp_readv, (message *mp, int from_int,
227 int vectored) );
228_PROTOTYPE( static void fxp_do_conf, (fxp_t *fp) );
229_PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
230 phys_bytes bus_addr, int check_idle) );
231_PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
232 phys_bytes bus_addr, int check_idle) );
233_PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp) );
234_PROTOTYPE( static void fxp_getstat, (message *mp) );
235_PROTOTYPE( static void fxp_getname, (message *mp) );
236_PROTOTYPE( static int fxp_handler, (fxp_t *fp) );
237_PROTOTYPE( static void fxp_check_ints, (fxp_t *fp) );
238_PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp) );
239_PROTOTYPE( static int fxp_link_changed, (fxp_t *fp) );
240_PROTOTYPE( static void fxp_report_link, (fxp_t *fp) );
241_PROTOTYPE( static void fxp_stop, (void));
242_PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block) );
243_PROTOTYPE( static void mess_reply, (message *req, message *reply) );
244_PROTOTYPE( static void put_userdata, (int user_proc,
245 vir_bytes user_addr, vir_bytes count, void *loc_addr) );
246_PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg) );
247_PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp) );
248_PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg) );
249_PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,
250 tmr_func_t watchdog) );
251_PROTOTYPE( static void fxp_expire_timers,(void) );
252_PROTOTYPE( static u8_t do_inb, (port_t port) );
253_PROTOTYPE( static u32_t do_inl, (port_t port) );
254_PROTOTYPE( static void do_outb, (port_t port, u8_t v) );
255_PROTOTYPE( static void do_outl, (port_t port, u32_t v) );
256
257/*===========================================================================*
258 * main *
259 *===========================================================================*/
260int main(int argc, char *argv[])
261{
262 message m;
263 int i, r, tasknr;
264 fxp_t *fp;
265 long v;
266
267 if ((fxp_tasknr= getprocnr())<0)
268 panic("FXP", "couldn't get proc nr", errno);
269
270 if (argc < 1)
271 panic("FXP", "A head which at this time has no name", NO_NUM);
272 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
273
274 v= 0;
275#if 0
276 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
277#endif
278 eth_ign_proto= htons((u16_t) v);
279
280#if 0 /* What about memory allocation? */
281 /* Claim buffer memory now under Minix, before MM takes it all. */
282 for (fp= &fxp_table[0]; fp < fxp_table+FXP_PORT_NR; fp++)
283 fxp_init_buf(fp);
284#endif
285
286 /* Try to notify inet that we are present (again) */
287 r = _pm_findproc("inet", &tasknr);
288 if (r == OK)
289 notify(tasknr);
290
291 while (TRUE)
292 {
293 if ((r= receive(ANY, &m)) != OK)
294 panic("FXP","receive failed", r);
295
296 switch (m.m_type)
297 {
298 case DEV_PING: notify(m.m_source); continue;
299 case DL_WRITEV: fxp_writev(&m, FALSE, TRUE); break;
300 case DL_WRITE: fxp_writev(&m, FALSE, FALSE); break;
301#if 0
302 case DL_READ: fxp_vread(&m, FALSE); break;
303#endif
304 case DL_READV: fxp_readv(&m, FALSE, TRUE); break;
305 case DL_INIT: fxp_init(&m); break;
306 case DL_GETSTAT: fxp_getstat(&m); break;
307 case DL_GETNAME: fxp_getname(&m); break;
308 case HARD_INT:
309 for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
310 {
311 if (fp->fxp_mode != FM_ENABLED)
312 continue;
313 fxp_handler(fp);
314
315 r= sys_irqenable(&fp->fxp_hook);
316 if (r != OK)
317 panic("FXP","unable enable interrupts", r);
318
319 if (!fp->fxp_got_int)
320 continue;
321 fp->fxp_got_int= 0;
322 assert(fp->fxp_flags & FF_ENABLED);
323 fxp_check_ints(fp);
324 }
325 break;
326 case SYS_SIG: {
327 sigset_t sigset = m.NOTIFY_ARG;
328 if (sigismember(&sigset, SIGKSTOP)) fxp_stop();
329 break;
330 }
331 case PROC_EVENT: break;
332 case SYN_ALARM: fxp_expire_timers(); break;
333 default:
334 panic("FXP"," illegal message", m.m_type);
335 }
336 }
337}
338
339/*===========================================================================*
340 * fxp_init *
341 *===========================================================================*/
342static void fxp_init(mp)
343message *mp;
344{
345 static int first_time= 1;
346
347 int port;
348 fxp_t *fp;
349 message reply_mess;
350
351 if (first_time)
352 {
353 first_time= 0;
354 fxp_pci_conf(); /* Configure PCI devices. */
355
356 tmra_inittimer(&fxp_watchdog);
357 tmr_arg(&fxp_watchdog)->ta_int= 0;
358 fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
359 }
360
361 port = mp->DL_PORT;
362 if (port < 0 || port >= FXP_PORT_NR)
363 {
364 reply_mess.m_type= DL_INIT_REPLY;
365 reply_mess.m3_i1= ENXIO;
366 mess_reply(mp, &reply_mess);
367 return;
368 }
369 fp= &fxp_table[port];
370 if (fp->fxp_mode == FM_DISABLED)
371 {
372 /* This is the default, try to (re)locate the device. */
373 fxp_conf_hw(fp);
374 if (fp->fxp_mode == FM_DISABLED)
375 {
376 /* Probe failed, or the device is configured off. */
377 reply_mess.m_type= DL_INIT_REPLY;
378 reply_mess.m3_i1= ENXIO;
379 mess_reply(mp, &reply_mess);
380 return;
381 }
382 if (fp->fxp_mode == FM_ENABLED)
383 fxp_init_hw(fp);
384 fxp_report_link(fp);
385 }
386
387 assert(fp->fxp_mode == FM_ENABLED);
388 assert(fp->fxp_flags & FF_ENABLED);
389
390 fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
391
392 if (mp->DL_MODE & DL_PROMISC_REQ)
393 fp->fxp_flags |= FF_PROMISC;
394 if (mp->DL_MODE & DL_MULTI_REQ)
395 fp->fxp_flags |= FF_MULTI;
396 if (mp->DL_MODE & DL_BROAD_REQ)
397 fp->fxp_flags |= FF_BROAD;
398
399 fp->fxp_client = mp->m_source;
400 fxp_rec_mode(fp);
401
402 reply_mess.m_type = DL_INIT_REPLY;
403 reply_mess.m3_i1 = mp->DL_PORT;
404 reply_mess.m3_i2 = FXP_PORT_NR;
405 *(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
406
407 mess_reply(mp, &reply_mess);
408}
409
410/*===========================================================================*
411 * fxp_pci_conf *
412 *===========================================================================*/
413static void fxp_pci_conf()
414{
415 static char envvar[] = FXP_ENVVAR "#";
416 static char envfmt[] = "*:d.d.d";
417
418 int i, h;
419 fxp_t *fp;
420 long v;
421
422 for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
423 {
424 strcpy(fp->fxp_name, "fxp#0");
425 fp->fxp_name[4] += i;
426 fp->fxp_seen= FALSE;
427 fp->fxp_features= FFE_NONE;
428 envvar[sizeof(FXP_ENVVAR)-1]= '0'+i;
429#if 0
430 if (getenv(envvar) != NULL)
431 {
432 if (strcmp(getenv(envvar), "off") == 0)
433 {
434 fp->fxp_pcibus= 255;
435 continue;
436 }
437 if (!env_prefix(envvar, "pci"))
438 env_panic(envvar);
439 }
440#endif
441
442 v= 0;
443#if 0
444 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
445#endif
446 fp->fxp_pcibus= v;
447 v= 0;
448#if 0
449 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
450#endif
451 fp->fxp_pcidev= v;
452 v= 0;
453#if 0
454 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
455#endif
456 fp->fxp_pcifunc= v;
457 }
458
459 pci_init();
460
461 for (h= 1; h >= 0; h--) {
462 for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
463 {
464 if (fp->fxp_pcibus == 255)
465 continue;
466 if (((fp->fxp_pcibus | fp->fxp_pcidev |
467 fp->fxp_pcifunc) != 0) != h)
468 {
469 continue;
470 }
471 if (fxp_probe(fp))
472 fp->fxp_seen= TRUE;
473 }
474 }
475}
476
477/*===========================================================================*
478 * fxp_probe *
479 *===========================================================================*/
480static int fxp_probe(fp)
481fxp_t *fp;
482{
483 int i, r, devind, just_one;
484 u16_t vid, did;
485 u32_t bar;
486 u8_t ilr, rev;
487 char *dname, *str;
488
489 if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)
490 {
491 /* Look for specific PCI device */
492 r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,
493 fp->fxp_pcifunc, &devind);
494 if (r == 0)
495 {
496 printf("%s: no PCI device found at %d.%d.%d\n",
497 fp->fxp_name, fp->fxp_pcibus,
498 fp->fxp_pcidev, fp->fxp_pcifunc);
499 return FALSE;
500 }
501 pci_ids(devind, &vid, &did);
502 just_one= TRUE;
503 }
504 else
505 {
506 r= pci_first_dev(&devind, &vid, &did);
507 if (r == 0)
508 return FALSE;
509 just_one= FALSE;
510 }
511
512 for(;;)
513 {
514 for (i= 0; pcitab_fxp[i].vid != 0; i++)
515 {
516 if (pcitab_fxp[i].vid != vid)
517 continue;
518 if (pcitab_fxp[i].did != did)
519 continue;
520 if (pcitab_fxp[i].checkclass)
521 {
522 panic("FXP","fxp_probe: class check not implemented",
523 NO_NUM);
524 }
525 break;
526 }
527 if (pcitab_fxp[i].vid != 0)
528 break;
529
530 if (just_one)
531 {
532 printf(
533 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
534 fp->fxp_name, vid, did,
535 fp->fxp_pcibus,
536 fp->fxp_pcidev, fp->fxp_pcifunc);
537 return FALSE;
538 }
539
540 r= pci_next_dev(&devind, &vid, &did);
541 if (!r)
542 return FALSE;
543 }
544
545 dname= pci_dev_name(vid, did);
546#if VERBOSE
547 if (!dname)
548 dname= "unknown device";
549 printf("%s: %s (%04x/%04x) at %s\n",
550 fp->fxp_name, dname, vid, did, pci_slot_name(devind));
551#endif
552 pci_reserve(devind);
553
554 bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
555 if (bar < 0x400)
556 {
557 panic("FXP","fxp_probe: base address is not properly configured",
558 NO_NUM);
559 }
560 fp->fxp_base_port= bar;
561
562 ilr= pci_attr_r8(devind, PCI_ILR);
563 fp->fxp_irq= ilr;
564 if (debug)
565 {
566 printf("%s: using I/O address 0x%lx, IRQ %d\n",
567 fp->fxp_name, (unsigned long)bar, ilr);
568 }
569
570 rev= pci_attr_r8(devind, PCI_REV);
571 str= NULL;
572 fp->fxp_type= FT_UNKNOWN;
573 switch(rev)
574 {
575 case FXP_REV_82557A: str= "82557A"; /* 0x01 */
576 fp->fxp_type= FT_82557;
577 break;
578 case FXP_REV_82557B: str= "82557B"; break; /* 0x02 */
579 case FXP_REV_82557C: str= "82557C"; break; /* 0x03 */
580 case FXP_REV_82558A: str= "82558A"; /* 0x04 */
581 fp->fxp_type= FT_82558A;
582 break;
583 case FXP_REV_82558B: str= "82558B"; break; /* 0x05 */
584 case FXP_REV_82559A: str= "82559A"; break; /* 0x06 */
585 case FXP_REV_82559B: str= "82559B"; break; /* 0x07 */
586 case FXP_REV_82559C: str= "82559C"; /* 0x08 */
587 fp->fxp_type= FT_82559;
588 break;
589 case FXP_REV_82559ERA: str= "82559ER-A"; /* 0x09 */
590 fp->fxp_type= FT_82559;
591 break;
592 case FXP_REV_82550_1: str= "82550(1)"; /* 0x0C */
593 fp->fxp_type= FT_82559;
594 break;
595 case FXP_REV_82550_2: str= "82550(2)"; /* 0x0D */
596 fp->fxp_type= FT_82559;
597 break;
598 case FXP_REV_82550_3: str= "82550(3)"; /* 0x0E */
599 fp->fxp_type= FT_82559;
600 break;
601 case FXP_REV_82551_1: str= "82551(1)"; /* 0x0F */
602 fp->fxp_type= FT_82559;
603 break;
604 case FXP_REV_82551_2: str= "82551(2)"; /* 0x10 */
605 fp->fxp_type= FT_82559;
606 break;
607 }
608
609#if VERBOSE
610 if (str)
611 printf("%s: device revision: %s\n", fp->fxp_name, str);
612 else
613 printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
614#endif
615
616 if (fp->fxp_type == FT_UNKNOWN)
617 {
618 printf("fxp_probe: device is not supported by this driver\n");
619 return FALSE;
620 }
621
622 return TRUE;
623}
624
625/*===========================================================================*
626 * fxp_conf_hw *
627 *===========================================================================*/
628static void fxp_conf_hw(fp)
629fxp_t *fp;
630{
631 int i;
632 int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;
633
634 fp->fxp_mode= FM_DISABLED; /* Superfluous */
635
636 if (!fp->fxp_seen)
637 return;
638
639 /* PCI device is present */
640 fp->fxp_mode= FM_ENABLED;
641
642 fp->fxp_flags= FF_EMPTY;
643 fp->fxp_got_int= 0;
644 fp->fxp_send_int= 0;
645 fp->fxp_ee_addrlen= 0; /* Unknown */
646 fp->fxp_need_reset= 0;
647 fp->fxp_report_link= 0;
648 fp->fxp_link_up= -1; /* Unknown */
649 fp->fxp_mii_busy= 0;
650 fp->fxp_read_s= 0;
651 fp->fxp_rx_need_restart= 0;
652 fp->fxp_need_conf= 0;
653 fp->fxp_tx_head= 0;
654 fp->fxp_tx_tail= 0;
655 fp->fxp_tx_alive= 0;
656 fp->fxp_tx_threshold= TXTT_MIN;
657
658 /* Try to come up with a sensible configuration for the current
659 * device. Unfortunately every device is different, defaults are
660 * not always zero, and some fields are re-used with a completely
661 * different interpretation. We start out with a sensible default
662 * for all devices and then add device specific changes.
663 */
664 fp->fxp_conf_bytes[0]= CC_BYTES_NR;
665 fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
666 fp->fxp_conf_bytes[2]= CAI_DEFAULT;
667 fp->fxp_conf_bytes[3]= 0;
668 fp->fxp_conf_bytes[4]= 0;
669 fp->fxp_conf_bytes[5]= 0;
670 fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
671 fp->fxp_conf_bytes[7]= CUR_1;
672 fp->fxp_conf_bytes[8]= CCB8_503_MII;
673 fp->fxp_conf_bytes[9]= 0;
674 fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
675 CCB10_RES1;
676 fp->fxp_conf_bytes[11]= 0;
677 fp->fxp_conf_bytes[12]= CIS_DEFAULT;
678 fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
679 fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
680 fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
681 fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
682 fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
683 fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
684 fp->fxp_conf_bytes[19]= CCB19_FDPE;
685 fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
686 fp->fxp_conf_bytes[21]= CCB21_RES21;
687
688#if VERBOSE
689 for (i= 0; i<CC_BYTES_NR; i++)
690 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
691 printf("\n");
692#endif
693
694 mwi= 0; /* Do we want "Memory Write and Invalidate"? */
695 ext_stat1= 0; /* Do we want extended statistical counters? */
696 ext_stat2= 0; /* Do we want even more statistical counters? */
697 lim_fifo= 0; /* Limit number of frame in TX FIFO */
698 i82503= 0; /* Older 10 Mbps interface on the 82557 */
699 fc= 0; /* Flow control */
700
701 switch(fp->fxp_type)
702 {
703 case FT_82557:
704 if (i82503)
705 {
706 fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;
707 fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;
708 }
709 break;
710 case FT_82558A:
711 case FT_82559:
712 if (mwi)
713 fp->fxp_conf_bytes[3] |= CCB3_MWIE;
714 if (ext_stat1)
715 fp->fxp_conf_bytes[6] &= ~CCB6_ESC;
716 if (ext_stat2)
717 fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;
718 if (lim_fifo)
719 fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;
720 if (fc)
721 {
722 /* From FreeBSD driver */
723 fp->fxp_conf_bytes[16]= 0x1f;
724 fp->fxp_conf_bytes[17]= 0x01;
725
726 fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |
727 CCB19_FDRSTOFC;
728 }
729
730 fp->fxp_conf_bytes[18] |= CCB18_LROK;
731 break;
732 default:
733 panic("FXP","fxp_conf_hw: bad device type", fp->fxp_type);
734 }
735
736#if VERBOSE
737 for (i= 0; i<CC_BYTES_NR; i++)
738 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
739 printf("\n");
740#endif
741}
742
743/*===========================================================================*
744 * fxp_init_hw *
745 *===========================================================================*/
746static void fxp_init_hw(fp)
747fxp_t *fp;
748{
749 int i, r, isr;
750 port_t port;
751 u32_t bus_addr;
752
753 port= fp->fxp_base_port;
754
755 fxp_init_buf(fp);
756
757 fp->fxp_flags = FF_EMPTY;
758 fp->fxp_flags |= FF_ENABLED;
759
760 /* Set the interrupt handler and policy. Do not automatically
761 * reenable interrupts. Return the IRQ line number on interrupts.
762 */
763 fp->fxp_hook = fp->fxp_irq;
764 r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
765 if (r != OK)
766 panic("FXP","sys_irqsetpolicy failed", r);
767
768 fxp_reset_hw(fp);
769
770 r= sys_irqenable(&fp->fxp_hook);
771 if (r != OK)
772 panic("FXP","sys_irqenable failed", r);
773
774 /* Reset PHY? */
775
776 fxp_do_conf(fp);
777
778 /* Set pointer to statistical counters */
779 r= sys_umap(SELF, D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
780 &bus_addr);
781 if (r != OK)
782 panic("FXP","sys_umap failed", r);
783 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);
784
785 /* Ack previous interrupts */
786 isr= fxp_inb(port, SCB_INT_STAT);
787 fxp_outb(port, SCB_INT_STAT, isr);
788
789 /* Enable interrupts */
790 fxp_outb(port, SCB_INT_MASK, 0);
791
792 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
793 TRUE /* check idle */);
794
795 fxp_confaddr(fp);
796 if (debug)
797 {
798 printf("%s: Ethernet address ", fp->fxp_name);
799 for (i= 0; i < 6; i++)
800 {
801 printf("%x%c", fp->fxp_address.ea_addr[i],
802 i < 5 ? ':' : '\n');
803 }
804 }
805}
806
807/*===========================================================================*
808 * fxp_init_buf *
809 *===========================================================================*/
810static void fxp_init_buf(fp)
811fxp_t *fp;
812{
813 size_t rx_totbufsize, tx_totbufsize, tot_bufsize;
814 phys_bytes buf;
815 int i, r;
816 struct rfd *rfdp;
817 struct tx *txp;
818
819 fp->fxp_rx_nbuf= N_RX_BUF;
820 rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
821 fp->fxp_rx_bufsize= rx_totbufsize;
822
823 fp->fxp_tx_nbuf= N_TX_BUF;
824 tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
825 fp->fxp_tx_bufsize= tx_totbufsize;
826
827 tot_bufsize= tx_totbufsize + rx_totbufsize;
828
829 /* What about memory allocation? */
830 {
831 static int first_time= 1;
832
833 assert(first_time);
834 first_time= 0;
835
836#define BUFALIGN 4096
837 assert(tot_bufsize <= sizeof(buffer)-BUFALIGN);
838 buf= (phys_bytes)buffer;
839 buf += BUFALIGN - (buf % BUFALIGN);
840 }
841
842 fp->fxp_rx_buf= (struct rfd *)buf;
843 r= sys_umap(SELF, D, (vir_bytes)buf, rx_totbufsize,
844 &fp->fxp_rx_busaddr);
845 if (r != OK)
846 panic("FXP","sys_umap failed", r);
847 for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
848 {
849 rfdp->rfd_status= 0;
850 rfdp->rfd_command= 0;
851 if (i != fp->fxp_rx_nbuf-1)
852 {
853 r= sys_umap(SELF, D, (vir_bytes)&rfdp[1],
854 sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
855 if (r != OK)
856 panic("FXP","sys_umap failed", r);
857 }
858 else
859 {
860 rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
861 rfdp->rfd_command |= RFDC_EL;
862 }
863 rfdp->rfd_reserved= 0;
864 rfdp->rfd_res= 0;
865 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
866
867 }
868 fp->fxp_rx_head= 0;
869
870 fp->fxp_tx_buf= (struct tx *)(buf+rx_totbufsize);
871 r= sys_umap(SELF, D, (vir_bytes)fp->fxp_tx_buf,
872 (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
873 if (r != OK)
874 panic("FXP","sys_umap failed", r);
875
876 for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
877 {
878 txp->tx_status= 0;
879 txp->tx_command= TXC_EL | CBL_NOP; /* Just in case */
880 if (i != fp->fxp_tx_nbuf-1)
881 {
882 r= sys_umap(SELF, D, (vir_bytes)&txp[1],
883 (phys_bytes)sizeof(txp[1]),
884 &txp->tx_linkaddr);
885 if (r != OK)
886 panic("FXP","sys_umap failed", r);
887 }
888 else
889 {
890 txp->tx_linkaddr= fp->fxp_tx_busaddr;
891 }
892 txp->tx_tbda= TX_TBDA_NIL;
893 txp->tx_size= 0;
894 txp->tx_tthresh= fp->fxp_tx_threshold;
895 txp->tx_ntbd= 0;
896 }
897 fp->fxp_tx_idle= 1;
898}
899
900/*===========================================================================*
901 * fxp_reset_hw *
902 *===========================================================================*/
903static void fxp_reset_hw(fp)
904fxp_t *fp;
905{
906/* Inline the function in init? */
907 port_t port;
908
909 port= fp->fxp_base_port;
910
911 /* Reset device */
912 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
913 tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));
914
915 /* Disable interrupts */
916 fxp_outb(port, SCB_INT_MASK, SIM_M);
917
918 /* Set CU base to zero */
919 fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
920
921 /* Set RU base to zero */
922 fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
923}
924
925/*===========================================================================*
926 * fxp_confaddr *
927 *===========================================================================*/
928static void fxp_confaddr(fp)
929fxp_t *fp;
930{
931 static char eakey[]= FXP_ENVVAR "#_EA";
932 static char eafmt[]= "x:x:x:x:x:x";
933 clock_t t0,t1;
934 int i, r;
935 port_t port;
936 u32_t bus_addr;
937 long v;
938 struct ias ias;
939
940 port= fp->fxp_base_port;
941
942 /* User defined ethernet address? */
943 eakey[sizeof(FXP_ENVVAR)-1]= '0' + (fp-fxp_table);
944
945#if 0
946 for (i= 0; i < 6; i++)
947 {
948 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
949 break;
950 fp->fxp_address.ea_addr[i]= v;
951 }
952#else
953 i= 0;
954#endif
955
956#if 0
957 if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
958#endif
959
960 if (i == 0)
961 {
962 /* Get ethernet address from EEPROM */
963 for (i= 0; i<3; i++)
964 {
965 v= eeprom_read(fp, i);
966 fp->fxp_address.ea_addr[i*2]= (v & 0xff);
967 fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
968 }
969 }
970
971 /* Tell NIC about ethernet address */
972 ias.ias_status= 0;
973 ias.ias_command= CBL_C_EL | CBL_AIS;
974 ias.ias_linkaddr= 0;
975 memcpy(ias.ias_ethaddr, fp->fxp_address.ea_addr,
976 sizeof(ias.ias_ethaddr));
977 r= sys_umap(SELF, D, (vir_bytes)&ias, (phys_bytes)sizeof(ias),
978 &bus_addr);
979 if (r != OK)
980 panic("FXP","sys_umap failed", r);
981
982 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
983
984 getuptime(&t0);
985 do {
986 /* Wait for CU command to complete */
987 if (ias.ias_status & CBL_F_C)
988 break;
989 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
990
991 if (!(ias.ias_status & CBL_F_C))
992 panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);
993 if (!(ias.ias_status & CBL_F_OK))
994 panic("FXP","fxp_confaddr: CU command failed", NO_NUM);
995
996#if VERBOSE
997 printf("%s: hardware ethernet address: ", fp->fxp_name);
998 for (i= 0; i<6; i++)
999 {
1000 printf("%02x%s", fp->fxp_address.ea_addr[i],
1001 i < 5 ? ":" : "");
1002 }
1003 printf("\n");
1004#endif
1005}
1006
1007/*===========================================================================*
1008 * fxp_rec_mode *
1009 *===========================================================================*/
1010static void fxp_rec_mode(fp)
1011fxp_t *fp;
1012{
1013 fp->fxp_conf_bytes[0]= CC_BYTES_NR; /* Just to be sure */
1014 fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
1015 fp->fxp_conf_bytes[21] &= ~CCB21_MA;
1016
1017 if (fp->fxp_flags & FF_PROMISC)
1018 fp->fxp_conf_bytes[15] |= CCB15_PM;
1019 if (fp->fxp_flags & FF_MULTI)
1020 fp->fxp_conf_bytes[21] |= CCB21_MA;
1021
1022 if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
1023 fp->fxp_conf_bytes[15] |= CCB15_BD;
1024
1025 /* Queue request if not idle */
1026 if (fp->fxp_tx_idle)
1027 {
1028 fxp_do_conf(fp);
1029 }
1030 else
1031 {
1032 printf("fxp_rec_mode: setting fxp_need_conf\n");
1033 fp->fxp_need_conf= TRUE;
1034 }
1035}
1036
1037/*===========================================================================*
1038 * fxp_writev *
1039 *===========================================================================*/
1040static void fxp_writev(mp, from_int, vectored)
1041message *mp;
1042int from_int;
1043int vectored;
1044{
1045 vir_bytes iov_src;
1046 int i, j, n, o, r, s, dl_port, count, size, prev_head;
1047 int fxp_client, fxp_tx_nbuf, fxp_tx_head;
1048 u16_t tx_command;
1049 fxp_t *fp;
1050 iovec_t *iovp;
1051 struct tx *txp, *prev_txp;
1052
1053 dl_port = mp->DL_PORT;
1054 count = mp->DL_COUNT;
1055 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1056 panic("FXP","fxp_writev: illegal port", dl_port);
1057 fp= &fxp_table[dl_port];
1058 fxp_client= mp->DL_PROC;
1059 fp->fxp_client= fxp_client;
1060
1061 assert(fp->fxp_mode == FM_ENABLED);
1062 assert(fp->fxp_flags & FF_ENABLED);
1063
1064 if (from_int)
1065 {
1066 assert(fp->fxp_flags & FF_SEND_AVAIL);
1067 fp->fxp_flags &= ~FF_SEND_AVAIL;
1068 fp->fxp_tx_alive= TRUE;
1069 }
1070
1071 if (fp->fxp_tx_idle)
1072 {
1073 txp= fp->fxp_tx_buf;
1074 fxp_tx_head= 0; /* lint */
1075 prev_txp= NULL; /* lint */
1076 }
1077 else
1078 {
1079 fxp_tx_nbuf= fp->fxp_tx_nbuf;
1080 prev_head= fp->fxp_tx_head;
1081 fxp_tx_head= prev_head+1;
1082 if (fxp_tx_head == fxp_tx_nbuf)
1083 fxp_tx_head= 0;
1084 assert(fxp_tx_head < fxp_tx_nbuf);
1085
1086 if (fxp_tx_head == fp->fxp_tx_tail)
1087 {
1088 /* Send queue is full */
1089 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1090 fp->fxp_flags |= FF_SEND_AVAIL;
1091 goto suspend;
1092 }
1093
1094 prev_txp= &fp->fxp_tx_buf[prev_head];
1095 txp= &fp->fxp_tx_buf[fxp_tx_head];
1096 }
1097
1098 assert(!(fp->fxp_flags & FF_SEND_AVAIL));
1099 assert(!(fp->fxp_flags & FF_PACK_SENT));
1100
1101 if (vectored)
1102 {
1103
1104 iov_src = (vir_bytes)mp->DL_ADDR;
1105
1106 size= 0;
1107 o= 0;
1108 for (i= 0; i<count; i += IOVEC_NR,
1109 iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
1110 {
1111 n= IOVEC_NR;
1112 if (i+n > count)
1113 n= count-i;
1114 r= sys_vircopy(fxp_client, D, iov_src,
1115 SELF, D, (vir_bytes)fp->fxp_iovec,
1116 n * sizeof(fp->fxp_iovec[0]));
1117 if (r != OK)
1118 panic("FXP","fxp_writev: sys_vircopy failed", r);
1119
1120 for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
1121 {
1122 s= iovp->iov_size;
1123 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
1124 {
1125 panic("FXP","fxp_writev: invalid packet size",
1126 NO_NUM);
1127 }
1128
1129 r= sys_vircopy(fxp_client, D, iovp->iov_addr,
1130 SELF, D, (vir_bytes)(txp->tx_buf+o),
1131 s);
1132 if (r != OK)
1133 {
1134 panic("FXP","fxp_writev: sys_vircopy failed",
1135 r);
1136 }
1137 size += s;
1138 o += s;
1139 }
1140 }
1141 if (size < ETH_MIN_PACK_SIZE)
1142 panic("FXP","fxp_writev: invalid packet size", size);
1143 }
1144 else
1145 {
1146 size= mp->DL_COUNT;
1147 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
1148 panic("FXP","fxp_writev: invalid packet size", size);
1149
1150 r= sys_vircopy(fxp_client, D, (vir_bytes)mp->DL_ADDR,
1151 SELF, D, (vir_bytes)txp->tx_buf, size);
1152 if (r != OK)
1153 panic("FXP","fxp_writev: sys_vircopy failed", r);
1154 }
1155
1156 txp->tx_status= 0;
1157 txp->tx_command= TXC_EL | CBL_XMIT;
1158 txp->tx_tbda= TX_TBDA_NIL;
1159 txp->tx_size= TXSZ_EOF | size;
1160 txp->tx_tthresh= fp->fxp_tx_threshold;
1161 txp->tx_ntbd= 0;
1162 if (fp->fxp_tx_idle)
1163 {
1164 fp->fxp_tx_idle= 0;
1165 fp->fxp_tx_head= fp->fxp_tx_tail= 0;
1166
1167 fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
1168 TRUE /* check idle */);
1169 }
1170 else
1171 {
1172 /* Link new request in transmit list */
1173 tx_command= prev_txp->tx_command;
1174 assert(tx_command == (TXC_EL | CBL_XMIT));
1175 prev_txp->tx_command= CBL_XMIT;
1176 fp->fxp_tx_head= fxp_tx_head;
1177 }
1178
1179 fp->fxp_flags |= FF_PACK_SENT;
1180
1181 /* If the interrupt handler called, don't send a reply. The reply
1182 * will be sent after all interrupts are handled.
1183 */
1184 if (from_int)
1185 return;
1186 reply(fp, OK, FALSE);
1187 return;
1188
1189suspend:
1190 if (from_int)
1191 panic("FXP","fxp: should not be sending\n", NO_NUM);
1192
1193 fp->fxp_tx_mess= *mp;
1194 reply(fp, OK, FALSE);
1195}
1196
1197/*===========================================================================*
1198 * fxp_readv *
1199 *===========================================================================*/
1200static void fxp_readv(mp, from_int, vectored)
1201message *mp;
1202int from_int;
1203int vectored;
1204{
1205 int i, j, n, o, r, s, dl_port, fxp_client, count, size,
1206 fxp_rx_head, fxp_rx_nbuf;
1207 port_t port;
1208 unsigned packlen;
1209 vir_bytes iov_src;
1210 u16_t rfd_status;
1211 u16_t rfd_res;
1212 u8_t scb_status;
1213 fxp_t *fp;
1214 iovec_t *iovp;
1215 struct rfd *rfdp, *prev_rfdp;
1216
1217 dl_port = mp->DL_PORT;
1218 count = mp->DL_COUNT;
1219 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1220 panic("FXP","fxp_readv: illegal port", dl_port);
1221 fp= &fxp_table[dl_port];
1222 fxp_client= mp->DL_PROC;
1223 fp->fxp_client= fxp_client;
1224
1225 assert(fp->fxp_mode == FM_ENABLED);
1226 assert(fp->fxp_flags & FF_ENABLED);
1227
1228 port= fp->fxp_base_port;
1229
1230 fxp_rx_head= fp->fxp_rx_head;
1231 rfdp= &fp->fxp_rx_buf[fxp_rx_head];
1232
1233 rfd_status= rfdp->rfd_status;
1234 if (!(rfd_status & RFDS_C))
1235 {
1236 /* Receive buffer is empty, suspend */
1237 goto suspend;
1238 }
1239
1240 if (!rfd_status & RFDS_OK)
1241 {
1242 /* Not OK? What happened? */
1243 assert(0);
1244 }
1245 else
1246 {
1247 assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
1248 RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT |
1249 RFDS_RXERR)));
1250 }
1251 rfd_res= rfdp->rfd_res;
1252 assert(rfd_res & RFDR_EOF);
1253 assert(rfd_res & RFDR_F);
1254
1255 packlen= rfd_res & RFDSZ_SIZE;
1256
1257 if (vectored)
1258 {
1259 iov_src = (vir_bytes)mp->DL_ADDR;
1260
1261 size= 0;
1262 o= 0;
1263 for (i= 0; i<count; i += IOVEC_NR,
1264 iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
1265 {
1266 n= IOVEC_NR;
1267 if (i+n > count)
1268 n= count-i;
1269 r= sys_vircopy(fxp_client, D, iov_src,
1270 SELF, D, (vir_bytes)fp->fxp_iovec,
1271 n * sizeof(fp->fxp_iovec[0]));
1272 if (r != OK)
1273 panic("FXP","fxp_readv: sys_vircopy failed", r);
1274
1275 for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
1276 {
1277 s= iovp->iov_size;
1278 if (size + s > packlen)
1279 {
1280 assert(packlen > size);
1281 s= packlen-size;
1282 }
1283
1284 r= sys_vircopy(SELF, D,
1285 (vir_bytes)(rfdp->rfd_buf+o),
1286 fxp_client, D, iovp->iov_addr, s);
1287 if (r != OK)
1288 {
1289 panic("FXP","fxp_readv: sys_vircopy failed",
1290 r);
1291 }
1292
1293 size += s;
1294 if (size == packlen)
1295 break;
1296 o += s;
1297 }
1298 if (size == packlen)
1299 break;
1300 }
1301 if (size < packlen)
1302 {
1303 assert(0);
1304 }
1305 }
1306 else
1307 {
1308 assert(0);
1309 }
1310
1311 fp->fxp_read_s= packlen;
1312 fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
1313
1314 /* Re-init the current buffer */
1315 rfdp->rfd_status= 0;
1316 rfdp->rfd_command= RFDC_EL;
1317 rfdp->rfd_reserved= 0;
1318 rfdp->rfd_res= 0;
1319 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1320
1321 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1322 if (fxp_rx_head == 0)
1323 {
1324 prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
1325 }
1326 else
1327 prev_rfdp= &rfdp[-1];
1328
1329 assert(prev_rfdp->rfd_command & RFDC_EL);
1330 prev_rfdp->rfd_command &= ~RFDC_EL;
1331
1332 fxp_rx_head++;
1333 if (fxp_rx_head == fxp_rx_nbuf)
1334 fxp_rx_head= 0;
1335 assert(fxp_rx_head < fxp_rx_nbuf);
1336 fp->fxp_rx_head= fxp_rx_head;
1337
1338 if (!from_int)
1339 reply(fp, OK, FALSE);
1340
1341 return;
1342
1343suspend:
1344 if (fp->fxp_rx_need_restart)
1345 {
1346 fp->fxp_rx_need_restart= 0;
1347
1348 /* Check the status of the RU */
1349 scb_status= fxp_inb(port, SCB_STATUS);
1350 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
1351 {
1352 /* Race condition? */
1353 printf("fxp_readv: restart race: 0x%x\n",
1354 scb_status);
1355 assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
1356 }
1357 else
1358 {
1359 fxp_restart_ru(fp);
1360 }
1361 }
1362 if (from_int)
1363 {
1364 assert(fp->fxp_flags & FF_READING);
1365
1366 /* No need to store any state */
1367 return;
1368 }
1369
1370 fp->fxp_rx_mess= *mp;
1371 assert(!(fp->fxp_flags & FF_READING));
1372 fp->fxp_flags |= FF_READING;
1373
1374 reply(fp, OK, FALSE);
1375}
1376
1377/*===========================================================================*
1378 * fxp_do_conf *
1379 *===========================================================================*/
1380static void fxp_do_conf(fp)
1381fxp_t *fp;
1382{
1383 int r;
1384 u32_t bus_addr;
1385 struct cbl_conf cc;
1386 clock_t t0,t1;
1387
1388 /* Configure device */
1389 cc.cc_status= 0;
1390 cc.cc_command= CBL_C_EL | CBL_CONF;
1391 cc.cc_linkaddr= 0;
1392 memcpy(cc.cc_bytes, fp->fxp_conf_bytes, sizeof(cc.cc_bytes));
1393
1394 r= sys_umap(SELF, D, (vir_bytes)&cc, (phys_bytes)sizeof(cc),
1395 &bus_addr);
1396 if (r != OK)
1397 panic("FXP","sys_umap failed", r);
1398
1399 fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
1400
1401 getuptime(&t0);
1402 do {
1403 /* Wait for CU command to complete */
1404 if (cc.cc_status & CBL_F_C)
1405 break;
1406 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
1407
1408 if (!(cc.cc_status & CBL_F_C))
1409 panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);
1410 if (!(cc.cc_status & CBL_F_OK))
1411 panic("FXP","fxp_do_conf: CU command failed", NO_NUM);
1412
1413}
1414
1415/*===========================================================================*
1416 * fxp_cu_ptr_cmd *
1417 *===========================================================================*/
1418static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
1419fxp_t *fp;
1420int cmd;
1421phys_bytes bus_addr;
1422int check_idle;
1423{
1424 clock_t t0,t1;
1425 port_t port;
1426 u8_t scb_cmd;
1427
1428 port= fp->fxp_base_port;
1429
1430 if (check_idle)
1431 {
1432 /* Consistency check. Make sure that CU is idle */
1433 if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
1434 panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM);
1435 }
1436
1437 fxp_outl(port, SCB_POINTER, bus_addr);
1438 fxp_outb(port, SCB_CMD, cmd);
1439
1440 /* What is a reasonable time-out? There is nothing in the
1441 * documentation. 1 ms should be enough.
1442 */
1443 getuptime(&t0);
1444 do {
1445 /* Wait for CU command to be accepted */
1446 scb_cmd= fxp_inb(port, SCB_CMD);
1447 if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
1448 break;
1449 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
1450
1451 if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
1452 panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);
1453}
1454
1455/*===========================================================================*
1456 * fxp_ru_ptr_cmd *
1457 *===========================================================================*/
1458static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
1459fxp_t *fp;
1460int cmd;
1461phys_bytes bus_addr;
1462int check_idle;
1463{
1464 clock_t t0,t1;
1465 port_t port;
1466 u8_t scb_cmd;
1467
1468 port= fp->fxp_base_port;
1469
1470 if (check_idle)
1471 {
1472 /* Consistency check, make sure that RU is idle */
1473 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
1474 panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM);
1475 }
1476
1477 fxp_outl(port, SCB_POINTER, bus_addr);
1478 fxp_outb(port, SCB_CMD, cmd);
1479
1480 getuptime(&t0);
1481 do {
1482 /* Wait for RU command to be accepted */
1483 scb_cmd= fxp_inb(port, SCB_CMD);
1484 if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
1485 break;
1486 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
1487
1488 if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
1489 panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);
1490}
1491
1492/*===========================================================================*
1493 * fxp_restart_ru *
1494 *===========================================================================*/
1495static void fxp_restart_ru(fp)
1496fxp_t *fp;
1497{
1498 int i, fxp_rx_nbuf;
1499 port_t port;
1500 struct rfd *rfdp;
1501
1502 port= fp->fxp_base_port;
1503
1504 fxp_rx_nbuf= fp->fxp_rx_nbuf;
1505 for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
1506 {
1507 rfdp->rfd_status= 0;
1508 rfdp->rfd_command= 0;
1509 if (i == fp->fxp_rx_nbuf-1)
1510 rfdp->rfd_command= RFDC_EL;
1511 rfdp->rfd_reserved= 0;
1512 rfdp->rfd_res= 0;
1513 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
1514 }
1515 fp->fxp_rx_head= 0;
1516
1517 /* Make sure that RU is in the 'No resources' state */
1518 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
1519 panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM);
1520
1521 fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
1522 FALSE /* do not check idle */);
1523}
1524
1525/*===========================================================================*
1526 * fxp_getstat *
1527 *===========================================================================*/
1528static void fxp_getstat(mp)
1529message *mp;
1530{
1531 clock_t t0,t1;
1532 int dl_port;
1533 port_t port;
1534 fxp_t *fp;
1535 u32_t *p;
1536 eth_stat_t stats;
1537
1538 dl_port = mp->DL_PORT;
1539 if (dl_port < 0 || dl_port >= FXP_PORT_NR)
1540 panic("FXP","fxp_getstat: illegal port", dl_port);
1541 fp= &fxp_table[dl_port];
1542 fp->fxp_client= mp->DL_PROC;
1543
1544 assert(fp->fxp_mode == FM_ENABLED);
1545 assert(fp->fxp_flags & FF_ENABLED);
1546
1547 port= fp->fxp_base_port;
1548
1549 p= &fp->fxp_stat.sc_tx_fcp;
1550 *p= 0;
1551
1552 /* The dump commmand doesn't take a pointer. Setting a pointer
1553 * doesn't hard though.
1554 */
1555 fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
1556
1557 getuptime(&t0);
1558 do {
1559 /* Wait for CU command to complete */
1560 if (*p != 0)
1561 break;
1562 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
1563
1564 if (*p == 0)
1565 panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
1566 if (*p != SCM_DSC)
1567 panic("FXP","fxp_getstat: bad magic", NO_NUM);
1568
1569 stats.ets_recvErr=
1570 fp->fxp_stat.sc_rx_crc +
1571 fp->fxp_stat.sc_rx_align +
1572 fp->fxp_stat.sc_rx_resource +
1573 fp->fxp_stat.sc_rx_overrun +
1574 fp->fxp_stat.sc_rx_cd +
1575 fp->fxp_stat.sc_rx_short;
1576 stats.ets_sendErr=
1577 fp->fxp_stat.sc_tx_maxcol +
1578 fp->fxp_stat.sc_tx_latecol +
1579 fp->fxp_stat.sc_tx_crs;
1580 stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
1581 stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
1582 stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
1583 stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
1584 stats.ets_packetR= fp->fxp_stat.sc_rx_good;
1585 stats.ets_packetT= fp->fxp_stat.sc_tx_good;
1586 stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
1587 stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
1588 stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
1589 stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
1590 stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
1591 stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
1592 stats.ets_CDheartbeat= 0;
1593 stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
1594
1595 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
1596 (vir_bytes) sizeof(stats), &stats);
1597 reply(fp, OK, FALSE);
1598}
1599
1600
1601/*===========================================================================*
1602 * fxp_getname *
1603 *===========================================================================*/
1604static void fxp_getname(mp)
1605message *mp;
1606{
1607 int r;
1608
1609 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
1610 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
1611 mp->m_type= DL_NAME_REPLY;
1612 r= send(mp->m_source, mp);
1613 if (r != OK)
1614 panic("FXP", "fxp_getname: send failed", r);
1615}
1616
1617/*===========================================================================*
1618 * fxp_handler *
1619 *===========================================================================*/
1620static int fxp_handler(fp)
1621fxp_t *fp;
1622{
1623 int port;
1624 u16_t isr;
1625
1626 RAND_UPDATE
1627
1628 port= fp->fxp_base_port;
1629
1630 /* Ack interrupt */
1631 isr= fxp_inb(port, SCB_INT_STAT);
1632 fxp_outb(port, SCB_INT_STAT, isr);
1633
1634 if (isr & SIS_FR)
1635 {
1636 isr &= ~SIS_FR;
1637
1638 if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
1639 {
1640 fp->fxp_got_int= TRUE;
1641 interrupt(fxp_tasknr);
1642 }
1643 }
1644 if (isr & SIS_CNA)
1645 {
1646 isr &= ~SIS_CNA;
1647 if (!fp->fxp_tx_idle)
1648 {
1649 fp->fxp_send_int= TRUE;
1650 if (!fp->fxp_got_int)
1651 {
1652 fp->fxp_got_int= TRUE;
1653 interrupt(fxp_tasknr);
1654 }
1655 }
1656 }
1657 if (isr & SIS_RNR)
1658 {
1659 isr &= ~SIS_RNR;
1660
1661 /* Assume that receive buffer is full of packets. fxp_readv
1662 * will restart the RU.
1663 */
1664 fp->fxp_rx_need_restart= 1;
1665 }
1666 if (isr)
1667 {
1668 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
1669 isr);
1670 }
1671
1672 return 1;
1673}
1674
1675/*===========================================================================*
1676 * fxp_check_ints *
1677 *===========================================================================*/
1678static void fxp_check_ints(fp)
1679fxp_t *fp;
1680{
1681 int n, fxp_flags, prev_tail;
1682 int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
1683 port_t port;
1684 u32_t busaddr;
1685 u16_t tx_status;
1686 u8_t scb_status;
1687 struct tx *txp;
1688
1689 fxp_flags= fp->fxp_flags;
1690
1691 if (fxp_flags & FF_READING)
1692 {
1693 if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
1694 ; /* Nothing */
1695 else if (fp->fxp_rx_mess.m_type == DL_READV)
1696 {
1697 fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
1698 TRUE /* vectored */);
1699 }
1700 else
1701 {
1702 assert(fp->fxp_rx_mess.m_type == DL_READ);
1703 fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
1704 FALSE /* !vectored */);
1705 }
1706 }
1707 if (fp->fxp_tx_idle)
1708 ; /* Nothing to do */
1709 else if (fp->fxp_send_int)
1710 {
1711 fp->fxp_send_int= FALSE;
1712 fxp_tx_tail= fp->fxp_tx_tail;
1713 fxp_tx_nbuf= fp->fxp_tx_nbuf;
1714 n= 0;
1715 for (;;)
1716 {
1717 txp= &fp->fxp_tx_buf[fxp_tx_tail];
1718 tx_status= txp->tx_status;
1719 if (!(tx_status & TXS_C))
1720 break;
1721
1722 n++;
1723
1724 assert(tx_status & TXS_OK);
1725 if (tx_status & TXS_U)
1726 {
1727 fxp_tx_threshold= fp->fxp_tx_threshold;
1728 if (fxp_tx_threshold < TXTT_MAX)
1729 {
1730 fxp_tx_threshold++;
1731 fp->fxp_tx_threshold= fxp_tx_threshold;
1732 }
1733 printf(
1734 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
1735 fxp_tx_threshold);
1736 }
1737
1738 if (txp->tx_command & TXC_EL)
1739 {
1740 fp->fxp_tx_idle= 1;
1741 break;
1742 }
1743
1744 fxp_tx_tail++;
1745 if (fxp_tx_tail == fxp_tx_nbuf)
1746 fxp_tx_tail= 0;
1747 assert(fxp_tx_tail < fxp_tx_nbuf);
1748 }
1749
1750 if (fp->fxp_need_conf)
1751 {
1752 /* Check the status of the CU */
1753 port= fp->fxp_base_port;
1754 scb_status= fxp_inb(port, SCB_STATUS);
1755 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
1756 {
1757 /* Nothing to do */
1758 printf("scb_status = 0x%x\n", scb_status);
1759 }
1760 else
1761 {
1762 printf("fxp_check_ints: fxp_need_conf\n");
1763 fp->fxp_need_conf= FALSE;
1764 fxp_do_conf(fp);
1765 }
1766 }
1767
1768 if (n)
1769 {
1770 if (!fp->fxp_tx_idle)
1771 {
1772 fp->fxp_tx_tail= fxp_tx_tail;
1773
1774 /* Check the status of the CU */
1775 port= fp->fxp_base_port;
1776 scb_status= fxp_inb(port, SCB_STATUS);
1777 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
1778 {
1779 /* Nothing to do */
1780 printf("scb_status = 0x%x\n",
1781 scb_status);
1782
1783 }
1784 else
1785 {
1786 if (fxp_tx_tail == 0)
1787 prev_tail= fxp_tx_nbuf-1;
1788 else
1789 prev_tail= fxp_tx_tail-1;
1790 busaddr= fp->fxp_tx_buf[prev_tail].
1791 tx_linkaddr;
1792
1793 fxp_cu_ptr_cmd(fp, SC_CU_START,
1794 busaddr, 1 /* check idle */);
1795 }
1796 }
1797
1798 if (fp->fxp_flags & FF_SEND_AVAIL)
1799 {
1800 if (fp->fxp_tx_mess.m_type == DL_WRITEV)
1801 {
1802 fxp_writev(&fp->fxp_tx_mess,
1803 TRUE /* from int */,
1804 TRUE /* vectored */);
1805 }
1806 else
1807 {
1808 assert(fp->fxp_tx_mess.m_type ==
1809 DL_WRITE);
1810 fxp_writev(&fp->fxp_tx_mess,
1811 TRUE /* from int */,
1812 FALSE /* !vectored */);
1813 }
1814 }
1815 }
1816
1817 }
1818 if (fp->fxp_report_link)
1819 fxp_report_link(fp);
1820
1821 if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
1822 reply(fp, OK, TRUE);
1823}
1824
1825/*===========================================================================*
1826 * fxp_watchdog_f *
1827 *===========================================================================*/
1828static void fxp_watchdog_f(tp)
1829timer_t *tp;
1830{
1831 int i;
1832 fxp_t *fp;
1833
1834 tmr_arg(&fxp_watchdog)->ta_int= 0;
1835 fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
1836
1837 for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
1838 {
1839 if (fp->fxp_mode != FM_ENABLED)
1840 continue;
1841
1842 /* Handle race condition, MII interface mgith be busy */
1843 if(!fp->fxp_mii_busy)
1844 {
1845 /* Check the link status. */
1846 if (fxp_link_changed(fp))
1847 {
1848#if VERBOSE
1849 printf("fxp_watchdog_f: link changed\n");
1850#endif
1851 fp->fxp_report_link= TRUE;
1852 fp->fxp_got_int= TRUE;
1853 interrupt(fxp_tasknr);
1854 }
1855 }
1856
1857 if (!(fp->fxp_flags & FF_SEND_AVAIL))
1858 {
1859 /* Assume that an idle system is alive */
1860 fp->fxp_tx_alive= TRUE;
1861 continue;
1862 }
1863 if (fp->fxp_tx_alive)
1864 {
1865 fp->fxp_tx_alive= FALSE;
1866 continue;
1867 }
1868
1869 fp->fxp_need_reset= TRUE;
1870 fp->fxp_got_int= TRUE;
1871 interrupt(fxp_tasknr);
1872 }
1873}
1874
1875/*===========================================================================*
1876 * fxp_link_changed *
1877 *===========================================================================*/
1878static int fxp_link_changed(fp)
1879fxp_t *fp;
1880{
1881 u16_t scr;
1882
1883 scr= mii_read(fp, MII_SCR);
1884 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
1885
1886 return (fp->fxp_mii_scr != scr);
1887}
1888
1889/*===========================================================================*
1890 * fxp_report_link *
1891 *===========================================================================*/
1892static void fxp_report_link(fp)
1893fxp_t *fp;
1894{
1895 port_t port;
1896 u16_t mii_ctrl, mii_status, mii_id1, mii_id2,
1897 mii_ana, mii_anlpa, mii_ane, mii_extstat,
1898 mii_ms_ctrl, mii_ms_status, scr;
1899 u32_t oui;
1900 int model, rev;
1901 int f, link_up, ms_regs;
1902
1903 /* Assume an 82555 (compatible) PHY. The should be changed for
1904 * 82557 NICs with different PHYs
1905 */
1906 ms_regs= 0; /* No master/slave registers. */
1907
1908 fp->fxp_report_link= FALSE;
1909 port= fp->fxp_base_port;
1910
1911 scr= mii_read(fp, MII_SCR);
1912 scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
1913 fp->fxp_mii_scr= scr;
1914
1915 mii_ctrl= mii_read(fp, MII_CTRL);
1916 mii_read(fp, MII_STATUS); /* Read the status register twice, why? */
1917 mii_status= mii_read(fp, MII_STATUS);
1918 mii_id1= mii_read(fp, MII_PHYID_H);
1919 mii_id2= mii_read(fp, MII_PHYID_L);
1920 mii_ana= mii_read(fp, MII_ANA);
1921 mii_anlpa= mii_read(fp, MII_ANLPA);
1922 mii_ane= mii_read(fp, MII_ANE);
1923 if (mii_status & MII_STATUS_EXT_STAT)
1924 mii_extstat= mii_read(fp, MII_EXT_STATUS);
1925 else
1926 mii_extstat= 0;
1927 if (ms_regs)
1928 {
1929 mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
1930 mii_ms_status= mii_read(fp, MII_MS_STATUS);
1931 }
1932 else
1933 {
1934 mii_ms_ctrl= 0;
1935 mii_ms_status= 0;
1936 }
1937
1938 /* How do we know about the link status? */
1939 link_up= !!(mii_status & MII_STATUS_LS);
1940
1941 fp->fxp_link_up= link_up;
1942 if (!link_up)
1943 {
1944#if VERBOSE
1945 printf("%s: link down\n", fp->fxp_name);
1946#endif
1947 return;
1948 }
1949
1950 oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) |
1951 ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
1952 model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
1953 rev= (mii_id2 & MII_PL_REV_MASK);
1954
1955#if VERBOSE
1956 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
1957#endif
1958
1959 if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
1960 {
1961 printf("%s: PHY: ", fp->fxp_name);
1962 f= 1;
1963 if (mii_ctrl & MII_CTRL_LB)
1964 {
1965 printf("loopback mode");
1966 f= 0;
1967 }
1968 if (mii_ctrl & MII_CTRL_PD)
1969 {
1970 if (!f) printf(", ");
1971 f= 0;
1972 printf("powered down");
1973 }
1974 if (mii_ctrl & MII_CTRL_ISO)
1975 {
1976 if (!f) printf(", ");
1977 f= 0;
1978 printf("isolated");
1979 }
1980 printf("\n");
1981 return;
1982 }
1983 if (!(mii_ctrl & MII_CTRL_ANE))
1984 {
1985 printf("%s: manual config: ", fp->fxp_name);
1986 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
1987 {
1988 case MII_CTRL_SP_10: printf("10 Mbps"); break;
1989 case MII_CTRL_SP_100: printf("100 Mbps"); break;
1990 case MII_CTRL_SP_1000: printf("1000 Mbps"); break;
1991 case MII_CTRL_SP_RES: printf("reserved speed"); break;
1992 }
1993 if (mii_ctrl & MII_CTRL_DM)
1994 printf(", full duplex");
1995 else
1996 printf(", half duplex");
1997 printf("\n");
1998 return;
1999 }
2000
2001 if (!debug) goto resspeed;
2002
2003 printf("%s: ", fp->fxp_name);
2004 mii_print_stat_speed(mii_status, mii_extstat);
2005 printf("\n");
2006
2007 if (!(mii_status & MII_STATUS_ANC))
2008 printf("%s: auto-negotiation not complete\n", fp->fxp_name);
2009 if (mii_status & MII_STATUS_RF)
2010 printf("%s: remote fault detected\n", fp->fxp_name);
2011 if (!(mii_status & MII_STATUS_ANA))
2012 {
2013 printf("%s: local PHY has no auto-negotiation ability\n",
2014 fp->fxp_name);
2015 }
2016 if (!(mii_status & MII_STATUS_LS))
2017 printf("%s: link down\n", fp->fxp_name);
2018 if (mii_status & MII_STATUS_JD)
2019 printf("%s: jabber condition detected\n", fp->fxp_name);
2020 if (!(mii_status & MII_STATUS_EC))
2021 {
2022 printf("%s: no extended register set\n", fp->fxp_name);
2023 goto resspeed;
2024 }
2025 if (!(mii_status & MII_STATUS_ANC))
2026 goto resspeed;
2027
2028 printf("%s: local cap.: ", fp->fxp_name);
2029 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
2030 {
2031 printf("1000 Mbps: T-");
2032 switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
2033 {
2034 case MII_MSC_1000T_FD: printf("FD"); break;
2035 case MII_MSC_1000T_HD: printf("HD"); break;
2036 default: printf("FD/HD"); break;
2037 }
2038 if (mii_ana)
2039 printf(", ");
2040 }
2041 mii_print_techab(mii_ana);
2042 printf("\n");
2043
2044 if (mii_ane & MII_ANE_PDF)
2045 printf("%s: parallel detection fault\n", fp->fxp_name);
2046 if (!(mii_ane & MII_ANE_LPANA))
2047 {
2048 printf("%s: link-partner does not support auto-negotiation\n",
2049 fp->fxp_name);
2050 goto resspeed;
2051 }
2052
2053 printf("%s: remote cap.: ", fp->fxp_name);
2054 if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
2055 if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
2056 {
2057 printf("1000 Mbps: T-");
2058 switch(mii_ms_status &
2059 (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
2060 {
2061 case MII_MSS_LP1000T_FD: printf("FD"); break;
2062 case MII_MSS_LP1000T_HD: printf("HD"); break;
2063 default: printf("FD/HD"); break;
2064 }
2065 if (mii_anlpa)
2066 printf(", ");
2067 }
2068 mii_print_techab(mii_anlpa);
2069 printf("\n");
2070
2071 if (ms_regs)
2072 {
2073 printf("%s: ", fp->fxp_name);
2074 if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
2075 {
2076 printf("manual %s",
2077 (mii_ms_ctrl & MII_MSC_MS_VAL) ?
2078 "MASTER" : "SLAVE");
2079 }
2080 else
2081 {
2082 printf("%s device",
2083 (mii_ms_ctrl & MII_MSC_MULTIPORT) ?
2084 "multiport" : "single-port");
2085 }
2086 if (mii_ms_ctrl & MII_MSC_RES)
2087 printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
2088 printf(": ");
2089 if (mii_ms_status & MII_MSS_FAULT)
2090 printf("M/S config fault");
2091 else if (mii_ms_status & MII_MSS_MASTER)
2092 printf("MASTER");
2093 else
2094 printf("SLAVE");
2095 printf("\n");
2096 }
2097
2098 if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
2099 {
2100 if (!(mii_ms_status & MII_MSS_LOCREC))
2101 {
2102 printf("%s: local receiver not OK\n",
2103 fp->fxp_name);
2104 }
2105 if (!(mii_ms_status & MII_MSS_REMREC))
2106 {
2107 printf("%s: remote receiver not OK\n",
2108 fp->fxp_name);
2109 }
2110 }
2111 if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
2112 {
2113 printf("%s", fp->fxp_name);
2114 if (mii_ms_status & MII_MSS_RES)
2115 printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
2116 if (mii_ms_status & MII_MSS_IDLE_ERR)
2117 {
2118 printf(" idle error %d",
2119 mii_ms_status & MII_MSS_IDLE_ERR);
2120 }
2121 printf("\n");
2122 }
2123
2124resspeed:
2125#if VERBOSE
2126 printf("%s: link up, %d Mbps, %s duplex\n",
2127 fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
2128 (scr & MII_SCR_FD) ? "full" : "half");
2129#endif
2130 ;
2131}
2132
2133/*===========================================================================*
2134 * fxp_stop *
2135 *===========================================================================*/
2136static void fxp_stop()
2137{
2138 int i;
2139 port_t port;
2140 fxp_t *fp;
2141
2142 for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
2143 {
2144 if (fp->fxp_mode != FM_ENABLED)
2145 continue;
2146 if (!(fp->fxp_flags & FF_ENABLED))
2147 continue;
2148 port= fp->fxp_base_port;
2149
2150 /* Reset device */
2151 if (debug)
2152 printf("%s: resetting device\n", fp->fxp_name);
2153 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
2154 }
2155 sys_exit(0);
2156}
2157
2158/*===========================================================================*
2159 * reply *
2160 *===========================================================================*/
2161static void reply(fp, err, may_block)
2162fxp_t *fp;
2163int err;
2164int may_block;
2165{
2166 message reply;
2167 int status;
2168 int r;
2169
2170 status = 0;
2171 if (fp->fxp_flags & FF_PACK_SENT)
2172 status |= DL_PACK_SEND;
2173 if (fp->fxp_flags & FF_PACK_RECV)
2174 status |= DL_PACK_RECV;
2175
2176 reply.m_type = DL_TASK_REPLY;
2177 reply.DL_PORT = fp - fxp_table;
2178 reply.DL_PROC = fp->fxp_client;
2179 reply.DL_STAT = status | ((u32_t) err << 16);
2180 reply.DL_COUNT = fp->fxp_read_s;
2181#if 0
2182 reply.DL_CLCK = get_uptime();
2183#else
2184 reply.DL_CLCK = 0;
2185#endif
2186
2187 r= send(fp->fxp_client, &reply);
2188
2189 if (r == ELOCKED && may_block)
2190 {
2191#if 0
2192 printW(); printf("send locked\n");
2193#endif
2194 return;
2195 }
2196
2197 if (r < 0)
2198 panic("FXP","fxp: send failed:", r);
2199
2200 fp->fxp_read_s = 0;
2201 fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
2202}
2203
2204/*===========================================================================*
2205 * mess_reply *
2206 *===========================================================================*/
2207static void mess_reply(req, reply_mess)
2208message *req;
2209message *reply_mess;
2210{
2211 if (send(req->m_source, reply_mess) != OK)
2212 panic("FXP","fxp: unable to mess_reply", NO_NUM);
2213}
2214
2215/*===========================================================================*
2216 * put_userdata *
2217 *===========================================================================*/
2218static void put_userdata(user_proc, user_addr, count, loc_addr)
2219int user_proc;
2220vir_bytes user_addr;
2221vir_bytes count;
2222void *loc_addr;
2223{
2224 int r;
2225
2226 r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
2227 user_proc, D, user_addr, count);
2228 if (r != OK)
2229 panic("FXP","put_userdata: sys_vircopy failed", r);
2230}
2231
2232/*===========================================================================*
2233 * eeprom_read *
2234 *===========================================================================*/
2235PRIVATE u16_t eeprom_read(fp, reg)
2236fxp_t *fp;
2237int reg;
2238{
2239 port_t port;
2240 u16_t v;
2241 int b, i, alen;
2242
2243 alen= fp->fxp_ee_addrlen;
2244 if (!alen)
2245 {
2246 eeprom_addrsize(fp);
2247 alen= fp->fxp_ee_addrlen;
2248 assert(alen == 6 || alen == 8);
2249 }
2250
2251 port= fp->fxp_base_port;
2252
2253 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
2254 v= EEPROM_READ_PREFIX;
2255 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
2256 {
2257 b= ((v & (1 << i)) ? CE_EEDI : 0);
2258 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2259 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2260 micro_delay(EESK_PERIOD/2+1);
2261 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2262 micro_delay(EESK_PERIOD/2+1);
2263 }
2264
2265 v= reg;
2266 for (i= alen-1; i >= 0; i--)
2267 {
2268 b= ((v & (1 << i)) ? CE_EEDI : 0);
2269 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2270 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2271 micro_delay(EESK_PERIOD/2+1);
2272 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2273 micro_delay(EESK_PERIOD/2+1);
2274 }
2275
2276 v= 0;
2277 for (i= 0; i<16; i++)
2278 {
2279 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2280 micro_delay(EESK_PERIOD/2+1);
2281 b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
2282 v= (v << 1) | b;
2283 fxp_outb(port, CSR_EEPROM, CE_EECS );
2284 micro_delay(EESK_PERIOD/2+1);
2285 }
2286 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2287 micro_delay(EECS_DELAY);
2288
2289 return v;
2290}
2291
2292/*===========================================================================*
2293 * eeprom_addrsize *
2294 *===========================================================================*/
2295PRIVATE void eeprom_addrsize(fp)
2296fxp_t *fp;
2297{
2298 port_t port;
2299 u16_t v;
2300 int b, i;
2301
2302 port= fp->fxp_base_port;
2303
2304 /* Try to find out the size of the EEPROM */
2305 fxp_outb(port, CSR_EEPROM, CE_EECS); /* Enable EEPROM */
2306 v= EEPROM_READ_PREFIX;
2307 for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
2308 {
2309 b= ((v & (1 << i)) ? CE_EEDI : 0);
2310 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2311 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2312 micro_delay(EESK_PERIOD/2+1);
2313 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2314 micro_delay(EESK_PERIOD/2+1);
2315 }
2316
2317 for (i= 0; i<32; i++)
2318 {
2319 b= 0;
2320 fxp_outb(port, CSR_EEPROM, CE_EECS | b); /* bit */
2321 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
2322 micro_delay(EESK_PERIOD/2+1);
2323 fxp_outb(port, CSR_EEPROM, CE_EECS | b);
2324 micro_delay(EESK_PERIOD/2+1);
2325 v= fxp_inb(port, CSR_EEPROM);
2326 if (!(v & CE_EEDO))
2327 break;
2328 }
2329 if (i >= 32)
2330 panic("FXP","eeprom_addrsize: failed", NO_NUM);
2331 fp->fxp_ee_addrlen= i+1;
2332
2333 /* Discard 16 data bits */
2334 for (i= 0; i<16; i++)
2335 {
2336 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
2337 micro_delay(EESK_PERIOD/2+1);
2338 fxp_outb(port, CSR_EEPROM, CE_EECS );
2339 micro_delay(EESK_PERIOD/2+1);
2340 }
2341 fxp_outb(port, CSR_EEPROM, 0); /* Disable EEPROM */
2342 micro_delay(EECS_DELAY);
2343
2344#if VERBOSE
2345 printf("%s EEPROM address length: %d\n",
2346 fp->fxp_name, fp->fxp_ee_addrlen);
2347#endif
2348}
2349
2350/*===========================================================================*
2351 * mii_read *
2352 *===========================================================================*/
2353PRIVATE u16_t mii_read(fp, reg)
2354fxp_t *fp;
2355int reg;
2356{
2357 clock_t t0,t1;
2358 port_t port;
2359 u32_t v;
2360
2361 port= fp->fxp_base_port;
2362
2363 assert(!fp->fxp_mii_busy);
2364 fp->fxp_mii_busy++;
2365
2366 if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
2367 panic("FXP","mii_read: MDI not ready", NO_NUM);
2368 fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
2369 (reg << CM_REG_SHIFT));
2370
2371 getuptime(&t0);
2372 do {
2373 v= fxp_inl(port, CSR_MDI_CTL);
2374 if (v & CM_READY)
2375 break;
2376 } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
2377
2378 if (!(v & CM_READY))
2379 panic("FXP","mii_read: MDI not ready after command", NO_NUM);
2380
2381 fp->fxp_mii_busy--;
2382 assert(!fp->fxp_mii_busy);
2383
2384 return v & CM_DATA_MASK;
2385}
2386
2387/*===========================================================================*
2388 * fxp_set_timer *
2389 *===========================================================================*/
2390PRIVATE void fxp_set_timer(tp, delta, watchdog)
2391timer_t *tp; /* timer to be set */
2392clock_t delta; /* in how many ticks */
2393tmr_func_t watchdog; /* watchdog function to be called */
2394{
2395 clock_t now; /* current time */
2396 int r;
2397
2398 /* Get the current time. */
2399 r= getuptime(&now);
2400 if (r != OK)
2401 panic("FXP","unable to get uptime from clock", r);
2402
2403 /* Add the timer to the local timer queue. */
2404 tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
2405
2406 /* Possibly reschedule an alarm call. This happens when a new timer
2407 * is added in front.
2408 */
2409 if (fxp_next_timeout == 0 ||
2410 fxp_timers->tmr_exp_time < fxp_next_timeout)
2411 {
2412 fxp_next_timeout= fxp_timers->tmr_exp_time;
2413#if VERBOSE
2414 printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
2415 fxp_next_timeout, fxp_next_timeout-now);
2416#endif
2417 r= sys_setalarm(fxp_next_timeout, 1);
2418 if (r != OK)
2419 panic("FXP","unable to set synchronous alarm", r);
2420 }
2421}
2422
2423/*===========================================================================*
2424 * fxp_expire_tmrs *
2425 *===========================================================================*/
2426PRIVATE void fxp_expire_timers()
2427{
2428/* A synchronous alarm message was received. Check if there are any expired
2429 * timers. Possibly reschedule the next alarm.
2430 */
2431 clock_t now; /* current time */
2432 timer_t *tp;
2433 int r;
2434
2435 /* Get the current time to compare the timers against. */
2436 r= getuptime(&now);
2437 if (r != OK)
2438 panic("FXP","Unable to get uptime from clock.", r);
2439
2440 /* Scan the timers queue for expired timers. Dispatch the watchdog function
2441 * for each expired timers. Possibly a new alarm call must be scheduled.
2442 */
2443 tmrs_exptimers(&fxp_timers, now, NULL);
2444 if (fxp_timers == NULL)
2445 fxp_next_timeout= TMR_NEVER;
2446 else
2447 { /* set new alarm */
2448 fxp_next_timeout = fxp_timers->tmr_exp_time;
2449 r= sys_setalarm(fxp_next_timeout, 1);
2450 if (r != OK)
2451 panic("FXP","Unable to set synchronous alarm.", r);
2452 }
2453}
2454
2455static void micro_delay(unsigned long usecs)
2456{
2457 tickdelay(MICROS_TO_TICKS(usecs));
2458}
2459
2460static u8_t do_inb(port_t port)
2461{
2462 int r;
2463 u32_t value;
2464
2465 r= sys_inb(port, &value);
2466 if (r != OK)
2467 panic("FXP","sys_inb failed", r);
2468 return value;
2469}
2470
2471static u32_t do_inl(port_t port)
2472{
2473 int r;
2474 u32_t value;
2475
2476 r= sys_inl(port, &value);
2477 if (r != OK)
2478 panic("FXP","sys_inl failed", r);
2479 return value;
2480}
2481
2482static void do_outb(port_t port, u8_t value)
2483{
2484 int r;
2485
2486 r= sys_outb(port, value);
2487 if (r != OK)
2488 panic("FXP","sys_outb failed", r);
2489}
2490
2491static void do_outl(port_t port, u32_t value)
2492{
2493 int r;
2494
2495 r= sys_outl(port, value);
2496 if (r != OK)
2497 panic("FXP","sys_outl failed", r);
2498}
2499
2500/*
2501 * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $
2502 */
2503
Note: See TracBrowser for help on using the repository browser.