4 * This file contains an ethernet device driver for Intel 82557, 82558,
5 * 82559, 82550, and 82562 fast ethernet controllers.
7 * The valid messages and their parameters are:
9 * m_type DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
10 * |------------+----------+---------+----------+---------+---------+---------|
11 * | HARDINT | | | | | | |
12 * |------------|----------|---------|----------|---------|---------|---------|
13 * | DL_WRITE | port nr | proc nr | count | mode | address | |
14 * |------------|----------|---------|----------|---------|---------|---------|
15 * | DL_WRITEV | port nr | proc nr | count | mode | address | |
16 * |------------|----------|---------|----------|---------|---------|---------|
17 * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
18 * |------------|----------|---------|----------|---------|---------|---------|
19 * | DL_READ | port nr | proc nr | count | | address | |
20 * |------------|----------|---------|----------|---------|---------|---------|
21 * | DL_READV | port nr | proc nr | count | | address | |
22 * |------------|----------|---------|----------|---------|---------|---------|
23 * | DL_READV_S | port nr | proc nr | count | | | grant |
24 * |------------|----------|---------|----------|---------|---------|---------|
25 * | DL_CONF | port nr | proc nr | | mode | address | |
26 * |------------|----------|---------|----------|---------|---------|---------|
27 * | DL_GETSTAT | port nr | proc nr | | | address | |
28 * |------------|----------|---------|----------|---------|---------|---------|
29 * |DL_GETSTAT_S| port nr | proc nr | | | | grant |
30 * |------------|----------|---------|----------|---------|---------|---------|
31 * | DL_STOP | port_nr | | | | | |
32 * |------------+----------+---------+----------+---------+---------+---------|
34 * The messages sent are:
36 * m-type DL_PORT DL_PROC DL_COUNT DL_STAT DL_CLCK
37 * |-------------+----------+---------+----------+---------+---------|
38 * |DL_TASK_REPLY| port nr | proc nr | rd-count | err|stat| clock |
39 * |-------------+----------+---------+----------+---------+---------|
41 * m_type m3_i1 m3_i2 m3_ca1
42 * |-------------+---------+-----------+---------------|
43 * |DL_CONF_REPLY| port nr | last port | ethernet addr |
44 * |-------------+---------+-----------+---------------|
46 * m_type DL_PORT DL_STAT
47 * |------------|---------|-----------|
48 * |DL_STAT_REPL| port nr | err |
49 * |------------|---------|-----------|
52 * Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
55 #include "../drivers.h"
59 #include <net/gen/ether.h>
60 #include <net/gen/eth_io.h>
63 #include <minix/endpoint.h>
67 #define tmra_ut timer_t
68 #define tmra_inittimer(tp) tmr_inittimer(tp)
69 #define Proc_number(p) proc_number(p)
71 #define RAND_UPDATE /**/
72 #define printW() ((void)0)
73 #define vm_1phys2bus(p) (p)
79 /* Number of receive buffers */
82 /* Number of transmit buffers */
85 /* I/O vectors are handled IOVEC_NR entries at a time. */
89 #define FXP_ENVVAR "FXPETH"
98 PRIVATE
struct pcitab pcitab_fxp
[]=
100 { 0x8086, 0x1229, 0 }, /* Intel 82557, etc. */
101 { 0x8086, 0x2449, 0 }, /* Intel 82801BA/BAM/CA/CAM */
102 { 0x8086, 0x103d, 0 }, /* Intel 82801DB */
103 { 0x8086, 0x1064, 0 }, /* Intel 82562 */
105 { 0x0000, 0x0000, 0 }
108 #define FXP_PORT_NR 1 /* Minix */
110 typedef int irq_hook_t
;
112 static timer_t
*fxp_timers
= NULL
;
113 static clock_t fxp_next_timeout
= 0;
115 /* ignore interrupt for the moment */
116 #define interrupt(x) 0
127 port_t fxp_base_port
;
133 int fxp_features
; /* Needed? */
135 int fxp_type
; /* What kind of hardware */
136 int fxp_ee_addrlen
; /* #EEPROM address bits */
141 vir_bytes fxp_read_s
;
144 struct rfd
*fxp_rx_buf
;
145 phys_bytes fxp_rx_busaddr
;
147 int fxp_rx_need_restart
;
148 int fxp_need_conf
; /* Re-configure after draining send
155 struct tx
*fxp_tx_buf
;
156 phys_bytes fxp_tx_busaddr
;
160 int fxp_tx_threshold
;
169 int fxp_seen
; /* TRUE iff device available */
176 ether_addr_t fxp_address
;
180 u8_t fxp_conf_bytes
[CC_BYTES_NR
];
181 char fxp_name
[sizeof("fxp#n")];
182 iovec_t fxp_iovec
[IOVEC_NR
];
183 iovec_s_t fxp_iovec_s
[IOVEC_NR
];
188 #define FM_DISABLED 0x0
189 #define FM_ENABLED 0x1
192 #define FF_EMPTY 0x000
193 #define FF_PACK_SENT 0x001
194 #define FF_PACK_RECV 0x002
195 #define FF_SEND_AVAIL 0x004
196 #define FF_READING 0x010
197 #define FF_PROMISC 0x040
198 #define FF_MULTI 0x080
199 #define FF_BROAD 0x100
200 #define FF_ENABLED 0x200
206 #define FT_UNKNOWN 0x0
208 #define FT_82558A 0x2
212 static fxp_t
*fxp_table
;
213 phys_bytes fxp_table_phys
;
215 static u16_t eth_ign_proto
;
216 static tmra_ut fxp_watchdog
;
217 static char *progname
;
223 #define fxp_inb(port, offset) (do_inb((port) + (offset)))
224 #define fxp_inw(port, offset) (do_inw((port) + (offset)))
225 #define fxp_inl(port, offset) (do_inl((port) + (offset)))
226 #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
227 #define fxp_outw(port, offset, value) (do_outw((port) + (offset), (value)))
228 #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
230 _PROTOTYPE( static void fxp_init
, (message
*mp
) );
231 _PROTOTYPE( static void fxp_pci_conf
, (void) );
232 _PROTOTYPE( static int fxp_probe
, (fxp_t
*fp
) );
233 _PROTOTYPE( static void fxp_conf_hw
, (fxp_t
*fp
) );
234 _PROTOTYPE( static void fxp_init_hw
, (fxp_t
*fp
) );
235 _PROTOTYPE( static void fxp_init_buf
, (fxp_t
*fp
) );
236 _PROTOTYPE( static void fxp_reset_hw
, (fxp_t
*fp
) );
237 _PROTOTYPE( static void fxp_confaddr
, (fxp_t
*fp
) );
238 _PROTOTYPE( static void fxp_rec_mode
, (fxp_t
*fp
) );
239 _PROTOTYPE( static void fxp_writev
, (message
*mp
, int from_int
,
241 _PROTOTYPE( static void fxp_writev_s
, (message
*mp
, int from_int
) );
242 _PROTOTYPE( static void fxp_readv
, (message
*mp
, int from_int
,
244 _PROTOTYPE( static void fxp_readv_s
, (message
*mp
, int from_int
) );
245 _PROTOTYPE( static void fxp_do_conf
, (fxp_t
*fp
) );
246 _PROTOTYPE( static void fxp_cu_ptr_cmd
, (fxp_t
*fp
, int cmd
,
247 phys_bytes bus_addr
, int check_idle
) );
248 _PROTOTYPE( static void fxp_ru_ptr_cmd
, (fxp_t
*fp
, int cmd
,
249 phys_bytes bus_addr
, int check_idle
) );
250 _PROTOTYPE( static void fxp_restart_ru
, (fxp_t
*fp
) );
251 _PROTOTYPE( static void fxp_getstat
, (message
*mp
) );
252 _PROTOTYPE( static void fxp_getstat_s
, (message
*mp
) );
253 _PROTOTYPE( static void fxp_getname
, (message
*mp
) );
254 _PROTOTYPE( static int fxp_handler
, (fxp_t
*fp
) );
255 _PROTOTYPE( static void fxp_check_ints
, (fxp_t
*fp
) );
256 _PROTOTYPE( static void fxp_watchdog_f
, (timer_t
*tp
) );
257 _PROTOTYPE( static int fxp_link_changed
, (fxp_t
*fp
) );
258 _PROTOTYPE( static void fxp_report_link
, (fxp_t
*fp
) );
259 _PROTOTYPE( static void fxp_stop
, (void));
260 _PROTOTYPE( static void reply
, (fxp_t
*fp
, int err
, int may_block
) );
261 _PROTOTYPE( static void mess_reply
, (message
*req
, message
*reply
) );
262 _PROTOTYPE( static u16_t eeprom_read
, (fxp_t
*fp
, int reg
) );
263 _PROTOTYPE( static void eeprom_addrsize
, (fxp_t
*fp
) );
264 _PROTOTYPE( static u16_t mii_read
, (fxp_t
*fp
, int reg
) );
265 _PROTOTYPE( static void fxp_set_timer
,(timer_t
*tp
, clock_t delta
,
266 tmr_func_t watchdog
) );
267 _PROTOTYPE( static void fxp_expire_timers
,(void) );
268 _PROTOTYPE( static u8_t do_inb
, (port_t port
) );
269 _PROTOTYPE( static u32_t do_inl
, (port_t port
) );
270 _PROTOTYPE( static void do_outb
, (port_t port
, u8_t v
) );
271 _PROTOTYPE( static void do_outl
, (port_t port
, u32_t v
) );
272 _PROTOTYPE( static void tell_dev
, (vir_bytes start
, size_t size
,
273 int pci_bus
, int pci_dev
, int pci_func
) );
275 PRIVATE
void handle_hw_intr(void)
280 for (i
= 0, fp
= &fxp_table
[0]; i
<FXP_PORT_NR
; i
++, fp
++) {
281 if (fp
->fxp_mode
!= FM_ENABLED
)
285 r
= sys_irqenable(&fp
->fxp_hook
);
287 panic("FXP", "unable enable interrupts", r
);
290 if (!fp
->fxp_got_int
)
293 assert(fp
->fxp_flags
& FF_ENABLED
);
298 /* SEF functions and variables. */
299 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
300 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
302 EXTERN
char **env_argv
;
304 /*===========================================================================*
306 *===========================================================================*/
307 int main(int argc
, char *argv
[])
312 /* SEF local startup. */
313 env_setargs(argc
, argv
);
318 if ((r
= sef_receive(ANY
, &m
)) != OK
)
319 panic("FXP","sef_receive failed", r
);
321 if (is_notify(m
.m_type
)) {
322 switch (_ENDPOINT_P(m
.m_source
)) {
330 if (getsigset(&set
) != 0) break;
332 if (sigismember(&set
, SIGTERM
))
341 panic("FXP"," illegal notify from", m
.m_source
);
344 /* get new message */
350 case DL_WRITEV
: fxp_writev(&m
, FALSE
, TRUE
); break;
351 case DL_WRITE
: fxp_writev(&m
, FALSE
, FALSE
); break;
352 case DL_WRITEV_S
: fxp_writev_s(&m
, FALSE
); break;
353 case DL_READ
: fxp_readv(&m
, FALSE
, FALSE
); break;
354 case DL_READV
: fxp_readv(&m
, FALSE
, TRUE
); break;
355 case DL_READV_S
: fxp_readv_s(&m
, FALSE
); break;
356 case DL_CONF
: fxp_init(&m
); break;
357 case DL_GETSTAT
: fxp_getstat(&m
); break;
358 case DL_GETSTAT_S
: fxp_getstat_s(&m
); break;
359 case DL_GETNAME
: fxp_getname(&m
); break;
361 panic("FXP"," illegal message", m
.m_type
);
366 /*===========================================================================*
367 * sef_local_startup *
368 *===========================================================================*/
369 PRIVATE
void sef_local_startup()
371 /* Register init callbacks. */
372 sef_setcb_init_fresh(sef_cb_init_fresh
);
373 sef_setcb_init_restart(sef_cb_init_fresh
);
375 /* No live update support for now. */
377 /* Let SEF perform startup. */
381 /*===========================================================================*
382 * sef_cb_init_fresh *
383 *===========================================================================*/
384 PRIVATE
int sef_cb_init_fresh(int type
, sef_init_info_t
*info
)
386 /* Initialize the fxp driver. */
392 ft
= sizeof(*fxp_table
)*FXP_PORT_NR
;
393 system_hz
= sys_hz();
396 panic("FXP", "A head which at this time has no name", NO_NUM
);
397 (progname
=strrchr(env_argv
[0],'/')) ? progname
++
398 : (progname
=env_argv
[0]);
402 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v
, 0x0000L
, 0xFFFFL
);
404 eth_ign_proto
= htons((u16_t
) v
);
406 if(!(fxp_table
= alloc_contig(ft
, 0, &fxp_table_phys
)))
407 panic("FXP","couldn't allocate table", ENOMEM
);
409 memset(fxp_table
, 0, ft
);
411 if((r
=tsc_calibrate()) != OK
)
412 panic("FXP","tsc_calibrate failed", r
);
414 /* Try to notify inet that we are present (again) */
415 r
= ds_retrieve_label_num("inet", &tasknr
);
419 printf("fxp: ds_retrieve_label_num failed for 'inet': %d\n", r
);
424 /*===========================================================================*
426 *===========================================================================*/
427 static void fxp_init(mp
)
430 static int first_time
= 1;
439 fxp_pci_conf(); /* Configure PCI devices. */
441 tmra_inittimer(&fxp_watchdog
);
442 tmr_arg(&fxp_watchdog
)->ta_int
= 0;
443 fxp_set_timer(&fxp_watchdog
, system_hz
, fxp_watchdog_f
);
447 if (port
< 0 || port
>= FXP_PORT_NR
)
449 reply_mess
.m_type
= DL_CONF_REPLY
;
450 reply_mess
.m3_i1
= ENXIO
;
451 mess_reply(mp
, &reply_mess
);
454 fp
= &fxp_table
[port
];
455 if (fp
->fxp_mode
== FM_DISABLED
)
457 /* This is the default, try to (re)locate the device. */
459 if (fp
->fxp_mode
== FM_DISABLED
)
461 /* Probe failed, or the device is configured off. */
462 reply_mess
.m_type
= DL_CONF_REPLY
;
463 reply_mess
.m3_i1
= ENXIO
;
464 mess_reply(mp
, &reply_mess
);
467 if (fp
->fxp_mode
== FM_ENABLED
)
472 assert(fp
->fxp_mode
== FM_ENABLED
);
473 assert(fp
->fxp_flags
& FF_ENABLED
);
475 fp
->fxp_flags
&= ~(FF_PROMISC
| FF_MULTI
| FF_BROAD
);
477 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
478 fp
->fxp_flags
|= FF_PROMISC
;
479 if (mp
->DL_MODE
& DL_MULTI_REQ
)
480 fp
->fxp_flags
|= FF_MULTI
;
481 if (mp
->DL_MODE
& DL_BROAD_REQ
)
482 fp
->fxp_flags
|= FF_BROAD
;
484 fp
->fxp_client
= mp
->m_source
;
487 reply_mess
.m_type
= DL_CONF_REPLY
;
488 reply_mess
.m3_i1
= mp
->DL_PORT
;
489 reply_mess
.m3_i2
= FXP_PORT_NR
;
490 *(ether_addr_t
*) reply_mess
.m3_ca1
= fp
->fxp_address
;
492 mess_reply(mp
, &reply_mess
);
495 /*===========================================================================*
497 *===========================================================================*/
498 static void fxp_pci_conf()
500 static char envvar
[] = FXP_ENVVAR
"#";
501 static char envfmt
[] = "*:d.d.d";
507 for (i
= 0, fp
= fxp_table
; i
<FXP_PORT_NR
; i
++, fp
++)
509 strcpy(fp
->fxp_name
, "fxp#0");
510 fp
->fxp_name
[4] += i
;
512 fp
->fxp_features
= FFE_NONE
;
513 envvar
[sizeof(FXP_ENVVAR
)-1]= '0'+i
;
515 if (getenv(envvar
) != NULL
)
517 if (strcmp(getenv(envvar
), "off") == 0)
522 if (!env_prefix(envvar
, "pci"))
529 (void) env_parse(envvar
, envfmt
, 1, &v
, 0, 255);
534 (void) env_parse(envvar
, envfmt
, 2, &v
, 0, 255);
539 (void) env_parse(envvar
, envfmt
, 3, &v
, 0, 255);
546 for (h
= 1; h
>= 0; h
--) {
547 for (i
= 0, fp
= fxp_table
; i
<FXP_PORT_NR
; i
++, fp
++)
549 if (fp
->fxp_pcibus
== 255)
551 if (((fp
->fxp_pcibus
| fp
->fxp_pcidev
|
552 fp
->fxp_pcifunc
) != 0) != h
)
562 /*===========================================================================*
564 *===========================================================================*/
565 static int fxp_probe(fp
)
568 int i
, r
, devind
, just_one
;
574 if ((fp
->fxp_pcibus
| fp
->fxp_pcidev
| fp
->fxp_pcifunc
) != 0)
576 /* Look for specific PCI device */
577 r
= pci_find_dev(fp
->fxp_pcibus
, fp
->fxp_pcidev
,
578 fp
->fxp_pcifunc
, &devind
);
581 printf("%s: no PCI device found at %d.%d.%d\n",
582 fp
->fxp_name
, fp
->fxp_pcibus
,
583 fp
->fxp_pcidev
, fp
->fxp_pcifunc
);
586 pci_ids(devind
, &vid
, &did
);
591 r
= pci_first_dev(&devind
, &vid
, &did
);
599 for (i
= 0; pcitab_fxp
[i
].vid
!= 0; i
++)
601 if (pcitab_fxp
[i
].vid
!= vid
)
603 if (pcitab_fxp
[i
].did
!= did
)
605 if (pcitab_fxp
[i
].checkclass
)
607 panic("FXP","fxp_probe: class check not implemented",
612 if (pcitab_fxp
[i
].vid
!= 0)
618 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
619 fp
->fxp_name
, vid
, did
,
621 fp
->fxp_pcidev
, fp
->fxp_pcifunc
);
625 r
= pci_next_dev(&devind
, &vid
, &did
);
630 dname
= pci_dev_name(vid
, did
);
633 dname
= "unknown device";
634 printf("%s: %s (%04x/%04x) at %s\n",
635 fp
->fxp_name
, dname
, vid
, did
, pci_slot_name(devind
));
639 bar
= pci_attr_r32(devind
, PCI_BAR_2
) & 0xffffffe0;
642 panic("FXP","fxp_probe: base address is not properly configured",
645 fp
->fxp_base_port
= bar
;
647 ilr
= pci_attr_r8(devind
, PCI_ILR
);
651 printf("%s: using I/O address 0x%lx, IRQ %d\n",
652 fp
->fxp_name
, (unsigned long)bar
, ilr
);
655 rev
= pci_attr_r8(devind
, PCI_REV
);
657 fp
->fxp_type
= FT_UNKNOWN
;
660 case FXP_REV_82557A
: str
= "82557A"; /* 0x01 */
661 fp
->fxp_type
= FT_82557
;
663 case FXP_REV_82557B
: str
= "82557B"; break; /* 0x02 */
664 case FXP_REV_82557C
: str
= "82557C"; break; /* 0x03 */
665 case FXP_REV_82558A
: str
= "82558A"; /* 0x04 */
666 fp
->fxp_type
= FT_82558A
;
668 case FXP_REV_82558B
: str
= "82558B"; break; /* 0x05 */
669 case FXP_REV_82559A
: str
= "82559A"; break; /* 0x06 */
670 case FXP_REV_82559B
: str
= "82559B"; break; /* 0x07 */
671 case FXP_REV_82559C
: str
= "82559C"; /* 0x08 */
672 fp
->fxp_type
= FT_82559
;
674 case FXP_REV_82559ERA
: str
= "82559ER-A"; /* 0x09 */
675 fp
->fxp_type
= FT_82559
;
677 case FXP_REV_82550_1
: str
= "82550(1)"; /* 0x0C */
678 fp
->fxp_type
= FT_82559
;
680 case FXP_REV_82550_2
: str
= "82550(2)"; /* 0x0D */
681 fp
->fxp_type
= FT_82559
;
683 case FXP_REV_82550_3
: str
= "82550(3)"; /* 0x0E */
684 fp
->fxp_type
= FT_82559
;
686 case FXP_REV_82551_1
: str
= "82551(1)"; /* 0x0F */
687 fp
->fxp_type
= FT_82559
;
689 case FXP_REV_82551_2
: str
= "82551(2)"; /* 0x10 */
690 fp
->fxp_type
= FT_82559
;
692 case FXP_REV_82801DB
: str
= "82801DB"; /* 0x81 */
693 fp
->fxp_type
= FT_82801
;
699 printf("%s: device revision: %s\n", fp
->fxp_name
, str
);
701 printf("%s: unknown revision: 0x%x\n", fp
->fxp_name
, rev
);
704 if (fp
->fxp_type
== FT_UNKNOWN
)
706 printf("fxp_probe: device is not supported by this driver\n");
713 /*===========================================================================*
715 *===========================================================================*/
716 static void fxp_conf_hw(fp
)
720 int mwi
, ext_stat1
, ext_stat2
, lim_fifo
, i82503
, fc
;
722 fp
->fxp_mode
= FM_DISABLED
; /* Superfluous */
727 /* PCI device is present */
728 fp
->fxp_mode
= FM_ENABLED
;
730 fp
->fxp_flags
= FF_EMPTY
;
733 fp
->fxp_ee_addrlen
= 0; /* Unknown */
734 fp
->fxp_need_reset
= 0;
735 fp
->fxp_report_link
= 0;
736 fp
->fxp_link_up
= -1; /* Unknown */
739 fp
->fxp_rx_need_restart
= 0;
740 fp
->fxp_need_conf
= 0;
744 fp
->fxp_tx_threshold
= TXTT_MIN
;
746 /* Try to come up with a sensible configuration for the current
747 * device. Unfortunately every device is different, defaults are
748 * not always zero, and some fields are re-used with a completely
749 * different interpretation. We start out with a sensible default
750 * for all devices and then add device specific changes.
752 fp
->fxp_conf_bytes
[0]= CC_BYTES_NR
;
753 fp
->fxp_conf_bytes
[1]= CTL_DEFAULT
| CRL_DEFAULT
;
754 fp
->fxp_conf_bytes
[2]= CAI_DEFAULT
;
755 fp
->fxp_conf_bytes
[3]= 0;
756 fp
->fxp_conf_bytes
[4]= 0;
757 fp
->fxp_conf_bytes
[5]= 0;
758 fp
->fxp_conf_bytes
[6]= CCB6_ESC
| CCB6_ETCB
| CCB6_RES
;
759 fp
->fxp_conf_bytes
[7]= CUR_1
;
760 fp
->fxp_conf_bytes
[8]= CCB8_503_MII
;
761 fp
->fxp_conf_bytes
[9]= 0;
762 fp
->fxp_conf_bytes
[10]= CLB_NORMAL
| CPAL_DEFAULT
| CCB10_NSAI
|
764 fp
->fxp_conf_bytes
[11]= 0;
765 fp
->fxp_conf_bytes
[12]= CIS_DEFAULT
;
766 fp
->fxp_conf_bytes
[13]= CCB13_DEFAULT
;
767 fp
->fxp_conf_bytes
[14]= CCB14_DEFAULT
;
768 fp
->fxp_conf_bytes
[15]= CCB15_RES1
| CCB15_RES2
;
769 fp
->fxp_conf_bytes
[16]= CCB16_DEFAULT
;
770 fp
->fxp_conf_bytes
[17]= CCB17_DEFAULT
;
771 fp
->fxp_conf_bytes
[18]= CCB18_RES1
| CCB18_PFCT
| CCB18_PE
;
772 fp
->fxp_conf_bytes
[19]= CCB19_FDPE
;
773 fp
->fxp_conf_bytes
[20]= CCB20_PFCL
| CCB20_RES1
;
774 fp
->fxp_conf_bytes
[21]= CCB21_RES21
;
777 for (i
= 0; i
<CC_BYTES_NR
; i
++)
778 printf("%d: %0x, ", i
, fp
->fxp_conf_bytes
[i
]);
782 mwi
= 0; /* Do we want "Memory Write and Invalidate"? */
783 ext_stat1
= 0; /* Do we want extended statistical counters? */
784 ext_stat2
= 0; /* Do we want even more statistical counters? */
785 lim_fifo
= 0; /* Limit number of frame in TX FIFO */
786 i82503
= 0; /* Older 10 Mbps interface on the 82557 */
787 fc
= 0; /* Flow control */
794 fp
->fxp_conf_bytes
[8] &= ~CCB8_503_MII
;
795 fp
->fxp_conf_bytes
[15] |= CCB15_CRSCDT
;
802 fp
->fxp_conf_bytes
[3] |= CCB3_MWIE
;
804 fp
->fxp_conf_bytes
[6] &= ~CCB6_ESC
;
806 fp
->fxp_conf_bytes
[6] &= ~CCB6_TCOSC
;
808 fp
->fxp_conf_bytes
[7] |= CCB7_2FFIFO
;
811 /* From FreeBSD driver */
812 fp
->fxp_conf_bytes
[16]= 0x1f;
813 fp
->fxp_conf_bytes
[17]= 0x01;
815 fp
->fxp_conf_bytes
[19] |= CCB19_FDRSTAFC
|
819 fp
->fxp_conf_bytes
[18] |= CCB18_LROK
;
821 if (fp
->fxp_type
== FT_82801
)
823 fp
->fxp_conf_bytes
[6] = 0xba; /* ctrl 1 */
824 fp
->fxp_conf_bytes
[15] = 0x48; /* promiscuous */
825 fp
->fxp_conf_bytes
[21] = 0x05; /* mc_all */
829 panic("FXP","fxp_conf_hw: bad device type", fp
->fxp_type
);
833 for (i
= 0; i
<CC_BYTES_NR
; i
++)
834 printf("%d: %0x, ", i
, fp
->fxp_conf_bytes
[i
]);
839 /*===========================================================================*
841 *===========================================================================*/
842 static void fxp_init_hw(fp
)
849 port
= fp
->fxp_base_port
;
853 fp
->fxp_flags
= FF_EMPTY
;
854 fp
->fxp_flags
|= FF_ENABLED
;
856 /* Set the interrupt handler and policy. Do not automatically
857 * reenable interrupts. Return the IRQ line number on interrupts.
859 fp
->fxp_hook
= fp
->fxp_irq
;
860 r
= sys_irqsetpolicy(fp
->fxp_irq
, 0, &fp
->fxp_hook
);
862 panic("FXP","sys_irqsetpolicy failed", r
);
866 r
= sys_irqenable(&fp
->fxp_hook
);
868 panic("FXP","sys_irqenable failed", r
);
874 /* Set pointer to statistical counters */
875 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&fp
->fxp_stat
, sizeof(fp
->fxp_stat
),
878 panic("FXP","sys_umap failed", r
);
879 fxp_cu_ptr_cmd(fp
, SC_CU_LOAD_DCA
, bus_addr
, TRUE
/* check idle */);
881 /* Ack previous interrupts */
882 isr
= fxp_inb(port
, SCB_INT_STAT
);
883 fxp_outb(port
, SCB_INT_STAT
, isr
);
885 /* Enable interrupts */
886 fxp_outb(port
, SCB_INT_MASK
, 0);
888 fxp_ru_ptr_cmd(fp
, SC_RU_START
, fp
->fxp_rx_busaddr
,
889 TRUE
/* check idle */);
894 printf("%s: Ethernet address ", fp
->fxp_name
);
895 for (i
= 0; i
< 6; i
++)
897 printf("%x%c", fp
->fxp_address
.ea_addr
[i
],
903 /*===========================================================================*
905 *===========================================================================*/
906 static void fxp_init_buf(fp
)
909 size_t rx_totbufsize
, tx_totbufsize
, tot_bufsize
, alloc_bufsize
;
917 fp
->fxp_rx_nbuf
= N_RX_BUF
;
918 rx_totbufsize
= fp
->fxp_rx_nbuf
* sizeof(struct rfd
);
919 fp
->fxp_rx_bufsize
= rx_totbufsize
;
921 fp
->fxp_tx_nbuf
= N_TX_BUF
;
922 tx_totbufsize
= fp
->fxp_tx_nbuf
* sizeof(struct tx
);
923 fp
->fxp_tx_bufsize
= tx_totbufsize
;
925 tot_bufsize
= sizeof(*tmpbufp
) + tx_totbufsize
+ rx_totbufsize
;
926 if (tot_bufsize
% 4096)
927 tot_bufsize
+= 4096 - (tot_bufsize
% 4096);
928 alloc_bufsize
= tot_bufsize
;
929 alloc_buf
= alloc_contig(alloc_bufsize
, AC_ALIGN4K
, &ph
);
930 if (alloc_buf
== NULL
)
932 panic(__FILE__
, "fxp_init_buf: unable to alloc_contig size",
936 buf
= (phys_bytes
)alloc_buf
;
938 tell_dev((vir_bytes
)buf
, tot_bufsize
, 0, 0, 0);
940 tmpbufp
= (union tmpbuf
*)buf
;
942 fp
->fxp_rx_buf
= (struct rfd
*)&tmpbufp
[1];
943 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)fp
->fxp_rx_buf
, rx_totbufsize
,
944 &fp
->fxp_rx_busaddr
);
946 panic("FXP","sys_umap failed", r
);
949 printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n",
950 fp
->fxp_rx_busaddr
, fp
->fxp_rx_buf
);
953 for (i
= 0, rfdp
= fp
->fxp_rx_buf
; i
<fp
->fxp_rx_nbuf
; i
++, rfdp
++)
956 rfdp
->rfd_command
= 0;
957 if (i
!= fp
->fxp_rx_nbuf
-1)
959 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&rfdp
[1],
960 sizeof(rfdp
[1]), &rfdp
->rfd_linkaddr
);
962 panic("FXP","sys_umap failed", r
);
966 rfdp
->rfd_linkaddr
= fp
->fxp_rx_busaddr
;
967 rfdp
->rfd_command
|= RFDC_EL
;
969 rfdp
->rfd_reserved
= 0;
971 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
976 fp
->fxp_tx_buf
= (struct tx
*)((char *)fp
->fxp_rx_buf
+rx_totbufsize
);
977 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)fp
->fxp_tx_buf
,
978 (phys_bytes
)tx_totbufsize
, &fp
->fxp_tx_busaddr
);
980 panic("FXP","sys_umap failed", r
);
982 for (i
= 0, txp
= fp
->fxp_tx_buf
; i
<fp
->fxp_tx_nbuf
; i
++, txp
++)
985 txp
->tx_command
= TXC_EL
| CBL_NOP
; /* Just in case */
986 if (i
!= fp
->fxp_tx_nbuf
-1)
988 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&txp
[1],
989 (phys_bytes
)sizeof(txp
[1]),
992 panic("FXP","sys_umap failed", r
);
996 txp
->tx_linkaddr
= fp
->fxp_tx_busaddr
;
998 txp
->tx_tbda
= TX_TBDA_NIL
;
1000 txp
->tx_tthresh
= fp
->fxp_tx_threshold
;
1006 /*===========================================================================*
1008 *===========================================================================*/
1009 static void fxp_reset_hw(fp
)
1012 /* Inline the function in init? */
1015 port
= fp
->fxp_base_port
;
1018 fxp_outl(port
, CSR_PORT
, CP_CMD_SOFT_RESET
);
1019 tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY
));
1021 /* Disable interrupts */
1022 fxp_outb(port
, SCB_INT_MASK
, SIM_M
);
1024 /* Set CU base to zero */
1025 fxp_cu_ptr_cmd(fp
, SC_CU_LOAD_BASE
, 0, TRUE
/* check idle */);
1027 /* Set RU base to zero */
1028 fxp_ru_ptr_cmd(fp
, SC_RU_LOAD_BASE
, 0, TRUE
/* check idle */);
1031 /*===========================================================================*
1033 *===========================================================================*/
1034 static void fxp_confaddr(fp
)
1037 static char eakey
[]= FXP_ENVVAR
"#_EA";
1038 static char eafmt
[]= "x:x:x:x:x:x";
1045 port
= fp
->fxp_base_port
;
1047 /* User defined ethernet address? */
1048 eakey
[sizeof(FXP_ENVVAR
)-1]= '0' + (fp
-fxp_table
);
1050 for (i
= 0; i
< 6; i
++)
1052 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
1054 fp
->fxp_address
.ea_addr
[i
]= v
;
1057 if (i
!= 0 && i
!= 6) env_panic(eakey
); /* It's all or nothing */
1061 /* Get ethernet address from EEPROM */
1062 for (i
= 0; i
<3; i
++)
1064 v
= eeprom_read(fp
, i
);
1065 fp
->fxp_address
.ea_addr
[i
*2]= (v
& 0xff);
1066 fp
->fxp_address
.ea_addr
[i
*2+1]= ((v
>> 8) & 0xff);
1070 /* Tell NIC about ethernet address */
1071 tmpbufp
->ias
.ias_status
= 0;
1072 tmpbufp
->ias
.ias_command
= CBL_C_EL
| CBL_AIS
;
1073 tmpbufp
->ias
.ias_linkaddr
= 0;
1074 memcpy(tmpbufp
->ias
.ias_ethaddr
, fp
->fxp_address
.ea_addr
,
1075 sizeof(tmpbufp
->ias
.ias_ethaddr
));
1076 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&tmpbufp
->ias
,
1077 (phys_bytes
)sizeof(tmpbufp
->ias
), &bus_addr
);
1079 panic("FXP","sys_umap failed", r
);
1081 fxp_cu_ptr_cmd(fp
, SC_CU_START
, bus_addr
, TRUE
/* check idle */);
1085 /* Wait for CU command to complete */
1086 if (tmpbufp
->ias
.ias_status
& CBL_F_C
)
1088 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(1000));
1090 if (!(tmpbufp
->ias
.ias_status
& CBL_F_C
))
1091 panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM
);
1092 if (!(tmpbufp
->ias
.ias_status
& CBL_F_OK
))
1093 panic("FXP","fxp_confaddr: CU command failed", NO_NUM
);
1096 printf("%s: hardware ethernet address: ", fp
->fxp_name
);
1097 for (i
= 0; i
<6; i
++)
1099 printf("%02x%s", fp
->fxp_address
.ea_addr
[i
],
1106 /*===========================================================================*
1108 *===========================================================================*/
1109 static void fxp_rec_mode(fp
)
1112 fp
->fxp_conf_bytes
[0]= CC_BYTES_NR
; /* Just to be sure */
1113 fp
->fxp_conf_bytes
[15] &= ~(CCB15_BD
|CCB15_PM
);
1114 fp
->fxp_conf_bytes
[21] &= ~CCB21_MA
;
1116 if (fp
->fxp_flags
& FF_PROMISC
)
1117 fp
->fxp_conf_bytes
[15] |= CCB15_PM
;
1118 if (fp
->fxp_flags
& FF_MULTI
)
1119 fp
->fxp_conf_bytes
[21] |= CCB21_MA
;
1121 if (!(fp
->fxp_flags
& (FF_BROAD
|FF_MULTI
|FF_PROMISC
)))
1122 fp
->fxp_conf_bytes
[15] |= CCB15_BD
;
1124 /* Queue request if not idle */
1125 if (fp
->fxp_tx_idle
)
1131 printf("fxp_rec_mode: setting fxp_need_conf\n");
1132 fp
->fxp_need_conf
= TRUE
;
1136 /*===========================================================================*
1138 *===========================================================================*/
1139 static void fxp_writev(mp
, from_int
, vectored
)
1145 int i
, j
, n
, o
, r
, s
, dl_port
, count
, size
, prev_head
;
1146 int fxp_client
, fxp_tx_nbuf
, fxp_tx_head
;
1150 struct tx
*txp
, *prev_txp
;
1152 dl_port
= mp
->DL_PORT
;
1153 count
= mp
->DL_COUNT
;
1154 if (dl_port
< 0 || dl_port
>= FXP_PORT_NR
)
1155 panic("FXP","fxp_writev: illegal port", dl_port
);
1156 fp
= &fxp_table
[dl_port
];
1157 fxp_client
= mp
->DL_PROC
;
1158 fp
->fxp_client
= fxp_client
;
1160 assert(fp
->fxp_mode
== FM_ENABLED
);
1161 assert(fp
->fxp_flags
& FF_ENABLED
);
1165 assert(fp
->fxp_flags
& FF_SEND_AVAIL
);
1166 fp
->fxp_flags
&= ~FF_SEND_AVAIL
;
1167 fp
->fxp_tx_alive
= TRUE
;
1170 if (fp
->fxp_tx_idle
)
1172 txp
= fp
->fxp_tx_buf
;
1173 fxp_tx_head
= 0; /* lint */
1174 prev_txp
= NULL
; /* lint */
1178 fxp_tx_nbuf
= fp
->fxp_tx_nbuf
;
1179 prev_head
= fp
->fxp_tx_head
;
1180 fxp_tx_head
= prev_head
+1;
1181 if (fxp_tx_head
== fxp_tx_nbuf
)
1183 assert(fxp_tx_head
< fxp_tx_nbuf
);
1185 if (fxp_tx_head
== fp
->fxp_tx_tail
)
1187 /* Send queue is full */
1188 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
1189 fp
->fxp_flags
|= FF_SEND_AVAIL
;
1193 prev_txp
= &fp
->fxp_tx_buf
[prev_head
];
1194 txp
= &fp
->fxp_tx_buf
[fxp_tx_head
];
1197 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
1198 assert(!(fp
->fxp_flags
& FF_PACK_SENT
));
1203 iov_src
= (vir_bytes
)mp
->DL_ADDR
;
1207 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1208 iov_src
+= IOVEC_NR
* sizeof(fp
->fxp_iovec
[0]))
1213 r
= sys_vircopy(fxp_client
, D
, iov_src
,
1214 SELF
, D
, (vir_bytes
)fp
->fxp_iovec
,
1215 n
* sizeof(fp
->fxp_iovec
[0]));
1217 panic("FXP","fxp_writev: sys_vircopy failed", r
);
1219 for (j
= 0, iovp
= fp
->fxp_iovec
; j
<n
; j
++, iovp
++)
1222 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
)
1224 panic("FXP","fxp_writev: invalid packet size",
1228 r
= sys_vircopy(fxp_client
, D
, iovp
->iov_addr
,
1229 SELF
, D
, (vir_bytes
)(txp
->tx_buf
+o
),
1233 panic("FXP","fxp_writev: sys_vircopy failed",
1240 if (size
< ETH_MIN_PACK_SIZE
)
1241 panic("FXP","fxp_writev: invalid packet size", size
);
1246 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE_TAGGED
)
1247 panic("FXP","fxp_writev: invalid packet size", size
);
1249 r
= sys_vircopy(fxp_client
, D
, (vir_bytes
)mp
->DL_ADDR
,
1250 SELF
, D
, (vir_bytes
)txp
->tx_buf
, size
);
1252 panic("FXP","fxp_writev: sys_vircopy failed", r
);
1256 txp
->tx_command
= TXC_EL
| CBL_XMIT
;
1257 txp
->tx_tbda
= TX_TBDA_NIL
;
1258 txp
->tx_size
= TXSZ_EOF
| size
;
1259 txp
->tx_tthresh
= fp
->fxp_tx_threshold
;
1261 if (fp
->fxp_tx_idle
)
1264 fp
->fxp_tx_head
= fp
->fxp_tx_tail
= 0;
1266 fxp_cu_ptr_cmd(fp
, SC_CU_START
, fp
->fxp_tx_busaddr
,
1267 TRUE
/* check idle */);
1271 /* Link new request in transmit list */
1272 tx_command
= prev_txp
->tx_command
;
1273 assert(tx_command
== (TXC_EL
| CBL_XMIT
));
1274 prev_txp
->tx_command
= CBL_XMIT
;
1275 fp
->fxp_tx_head
= fxp_tx_head
;
1278 fp
->fxp_flags
|= FF_PACK_SENT
;
1280 /* If the interrupt handler called, don't send a reply. The reply
1281 * will be sent after all interrupts are handled.
1285 reply(fp
, OK
, FALSE
);
1290 panic("FXP","fxp: should not be sending\n", NO_NUM
);
1292 fp
->fxp_tx_mess
= *mp
;
1293 reply(fp
, OK
, FALSE
);
1296 /*===========================================================================*
1298 *===========================================================================*/
1299 static void fxp_writev_s(mp
, from_int
)
1303 cp_grant_id_t iov_grant
;
1304 vir_bytes iov_offset
;
1305 int i
, j
, n
, o
, r
, s
, dl_port
, count
, size
, prev_head
;
1306 int fxp_client
, fxp_tx_nbuf
, fxp_tx_head
;
1310 struct tx
*txp
, *prev_txp
;
1312 dl_port
= mp
->DL_PORT
;
1313 count
= mp
->DL_COUNT
;
1314 if (dl_port
< 0 || dl_port
>= FXP_PORT_NR
)
1315 panic("FXP","fxp_writev: illegal port", dl_port
);
1316 fp
= &fxp_table
[dl_port
];
1317 fxp_client
= mp
->DL_PROC
;
1318 fp
->fxp_client
= fxp_client
;
1320 assert(fp
->fxp_mode
== FM_ENABLED
);
1321 assert(fp
->fxp_flags
& FF_ENABLED
);
1325 assert(fp
->fxp_flags
& FF_SEND_AVAIL
);
1326 fp
->fxp_flags
&= ~FF_SEND_AVAIL
;
1327 fp
->fxp_tx_alive
= TRUE
;
1330 if (fp
->fxp_tx_idle
)
1332 txp
= fp
->fxp_tx_buf
;
1333 fxp_tx_head
= 0; /* lint */
1334 prev_txp
= NULL
; /* lint */
1338 fxp_tx_nbuf
= fp
->fxp_tx_nbuf
;
1339 prev_head
= fp
->fxp_tx_head
;
1340 fxp_tx_head
= prev_head
+1;
1341 if (fxp_tx_head
== fxp_tx_nbuf
)
1343 assert(fxp_tx_head
< fxp_tx_nbuf
);
1345 if (fxp_tx_head
== fp
->fxp_tx_tail
)
1347 /* Send queue is full */
1348 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
1349 fp
->fxp_flags
|= FF_SEND_AVAIL
;
1353 prev_txp
= &fp
->fxp_tx_buf
[prev_head
];
1354 txp
= &fp
->fxp_tx_buf
[fxp_tx_head
];
1357 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
1358 assert(!(fp
->fxp_flags
& FF_PACK_SENT
));
1360 iov_grant
= mp
->DL_GRANT
;
1365 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1366 iov_offset
+= IOVEC_NR
* sizeof(fp
->fxp_iovec_s
[0]))
1371 r
= sys_safecopyfrom(fxp_client
, iov_grant
, iov_offset
,
1372 (vir_bytes
)fp
->fxp_iovec_s
,
1373 n
* sizeof(fp
->fxp_iovec_s
[0]), D
);
1375 panic("FXP","fxp_writev: sys_safecopyfrom failed", r
);
1377 for (j
= 0, iovp
= fp
->fxp_iovec_s
; j
<n
; j
++, iovp
++)
1380 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
)
1382 panic("FXP","fxp_writev: invalid packet size",
1386 r
= sys_safecopyfrom(fxp_client
, iovp
->iov_grant
,
1387 0, (vir_bytes
)(txp
->tx_buf
+o
), s
, D
);
1391 "fxp_writev_s: sys_safecopyfrom failed",
1398 if (size
< ETH_MIN_PACK_SIZE
)
1399 panic("FXP","fxp_writev: invalid packet size", size
);
1402 txp
->tx_command
= TXC_EL
| CBL_XMIT
;
1403 txp
->tx_tbda
= TX_TBDA_NIL
;
1404 txp
->tx_size
= TXSZ_EOF
| size
;
1405 txp
->tx_tthresh
= fp
->fxp_tx_threshold
;
1407 if (fp
->fxp_tx_idle
)
1410 fp
->fxp_tx_head
= fp
->fxp_tx_tail
= 0;
1412 fxp_cu_ptr_cmd(fp
, SC_CU_START
, fp
->fxp_tx_busaddr
,
1413 TRUE
/* check idle */);
1417 /* Link new request in transmit list */
1418 tx_command
= prev_txp
->tx_command
;
1419 assert(tx_command
== (TXC_EL
| CBL_XMIT
));
1420 prev_txp
->tx_command
= CBL_XMIT
;
1421 fp
->fxp_tx_head
= fxp_tx_head
;
1424 fp
->fxp_flags
|= FF_PACK_SENT
;
1426 /* If the interrupt handler called, don't send a reply. The reply
1427 * will be sent after all interrupts are handled.
1431 reply(fp
, OK
, FALSE
);
1436 panic("FXP","fxp: should not be sending\n", NO_NUM
);
1438 fp
->fxp_tx_mess
= *mp
;
1439 reply(fp
, OK
, FALSE
);
1442 /*===========================================================================*
1444 *===========================================================================*/
1445 static void fxp_readv(mp
, from_int
, vectored
)
1450 int i
, j
, n
, o
, r
, s
, dl_port
, fxp_client
, count
, size
,
1451 fxp_rx_head
, fxp_rx_nbuf
;
1460 struct rfd
*rfdp
, *prev_rfdp
;
1462 dl_port
= mp
->DL_PORT
;
1463 count
= mp
->DL_COUNT
;
1464 if (dl_port
< 0 || dl_port
>= FXP_PORT_NR
)
1465 panic("FXP","fxp_readv: illegal port", dl_port
);
1466 fp
= &fxp_table
[dl_port
];
1467 fxp_client
= mp
->DL_PROC
;
1468 fp
->fxp_client
= fxp_client
;
1470 assert(fp
->fxp_mode
== FM_ENABLED
);
1471 assert(fp
->fxp_flags
& FF_ENABLED
);
1473 port
= fp
->fxp_base_port
;
1475 fxp_rx_head
= fp
->fxp_rx_head
;
1476 rfdp
= &fp
->fxp_rx_buf
[fxp_rx_head
];
1478 rfd_status
= rfdp
->rfd_status
;
1479 if (!(rfd_status
& RFDS_C
))
1481 /* Receive buffer is empty, suspend */
1485 if (!rfd_status
& RFDS_OK
)
1487 /* Not OK? What happened? */
1492 assert(!(rfd_status
& (RFDS_CRCERR
| RFDS_ALIGNERR
|
1493 RFDS_OUTOFBUF
| RFDS_DMAOVR
| RFDS_TOOSHORT
|
1496 rfd_res
= rfdp
->rfd_res
;
1497 assert(rfd_res
& RFDR_EOF
);
1498 assert(rfd_res
& RFDR_F
);
1500 packlen
= rfd_res
& RFDSZ_SIZE
;
1504 iov_src
= (vir_bytes
)mp
->DL_ADDR
;
1508 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1509 iov_src
+= IOVEC_NR
* sizeof(fp
->fxp_iovec
[0]))
1514 r
= sys_vircopy(fxp_client
, D
, iov_src
,
1515 SELF
, D
, (vir_bytes
)fp
->fxp_iovec
,
1516 n
* sizeof(fp
->fxp_iovec
[0]));
1518 panic("FXP","fxp_readv: sys_vircopy failed", r
);
1520 for (j
= 0, iovp
= fp
->fxp_iovec
; j
<n
; j
++, iovp
++)
1523 if (size
+ s
> packlen
)
1525 assert(packlen
> size
);
1529 r
= sys_vircopy(SELF
, D
,
1530 (vir_bytes
)(rfdp
->rfd_buf
+o
),
1531 fxp_client
, D
, iovp
->iov_addr
, s
);
1534 panic("FXP","fxp_readv: sys_vircopy failed",
1539 if (size
== packlen
)
1543 if (size
== packlen
)
1556 fp
->fxp_read_s
= packlen
;
1557 fp
->fxp_flags
= (fp
->fxp_flags
& ~FF_READING
) | FF_PACK_RECV
;
1559 /* Re-init the current buffer */
1560 rfdp
->rfd_status
= 0;
1561 rfdp
->rfd_command
= RFDC_EL
;
1562 rfdp
->rfd_reserved
= 0;
1564 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
1566 fxp_rx_nbuf
= fp
->fxp_rx_nbuf
;
1567 if (fxp_rx_head
== 0)
1569 prev_rfdp
= &fp
->fxp_rx_buf
[fxp_rx_nbuf
-1];
1572 prev_rfdp
= &rfdp
[-1];
1574 assert(prev_rfdp
->rfd_command
& RFDC_EL
);
1575 prev_rfdp
->rfd_command
&= ~RFDC_EL
;
1578 if (fxp_rx_head
== fxp_rx_nbuf
)
1580 assert(fxp_rx_head
< fxp_rx_nbuf
);
1581 fp
->fxp_rx_head
= fxp_rx_head
;
1584 reply(fp
, OK
, FALSE
);
1589 if (fp
->fxp_rx_need_restart
)
1591 fp
->fxp_rx_need_restart
= 0;
1593 /* Check the status of the RU */
1594 scb_status
= fxp_inb(port
, SCB_STATUS
);
1595 if ((scb_status
& SS_RUS_MASK
) != SS_RU_NORES
)
1597 /* Race condition? */
1598 printf("fxp_readv: restart race: 0x%x\n",
1600 assert((scb_status
& SS_RUS_MASK
) == SS_RU_READY
);
1609 assert(fp
->fxp_flags
& FF_READING
);
1611 /* No need to store any state */
1615 fp
->fxp_rx_mess
= *mp
;
1616 assert(!(fp
->fxp_flags
& FF_READING
));
1617 fp
->fxp_flags
|= FF_READING
;
1619 reply(fp
, OK
, FALSE
);
1622 /*===========================================================================*
1624 *===========================================================================*/
1625 static void fxp_readv_s(mp
, from_int
)
1629 int i
, j
, n
, o
, r
, s
, dl_port
, fxp_client
, count
, size
,
1630 fxp_rx_head
, fxp_rx_nbuf
;
1631 cp_grant_id_t iov_grant
;
1634 vir_bytes iov_offset
;
1640 struct rfd
*rfdp
, *prev_rfdp
;
1642 dl_port
= mp
->DL_PORT
;
1643 count
= mp
->DL_COUNT
;
1644 if (dl_port
< 0 || dl_port
>= FXP_PORT_NR
)
1645 panic("FXP","fxp_readv: illegal port", dl_port
);
1646 fp
= &fxp_table
[dl_port
];
1647 fxp_client
= mp
->DL_PROC
;
1648 fp
->fxp_client
= fxp_client
;
1650 assert(fp
->fxp_mode
== FM_ENABLED
);
1651 assert(fp
->fxp_flags
& FF_ENABLED
);
1653 port
= fp
->fxp_base_port
;
1655 fxp_rx_head
= fp
->fxp_rx_head
;
1656 rfdp
= &fp
->fxp_rx_buf
[fxp_rx_head
];
1658 rfd_status
= rfdp
->rfd_status
;
1659 if (!(rfd_status
& RFDS_C
))
1661 /* Receive buffer is empty, suspend */
1665 if (!rfd_status
& RFDS_OK
)
1667 /* Not OK? What happened? */
1672 assert(!(rfd_status
& (RFDS_CRCERR
| RFDS_ALIGNERR
|
1673 RFDS_OUTOFBUF
| RFDS_DMAOVR
| RFDS_TOOSHORT
|
1676 rfd_res
= rfdp
->rfd_res
;
1677 assert(rfd_res
& RFDR_EOF
);
1678 assert(rfd_res
& RFDR_F
);
1680 packlen
= rfd_res
& RFDSZ_SIZE
;
1682 iov_grant
= mp
->DL_GRANT
;
1687 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1688 iov_offset
+= IOVEC_NR
* sizeof(fp
->fxp_iovec_s
[0]))
1693 r
= sys_safecopyfrom(fxp_client
, iov_grant
, iov_offset
,
1694 (vir_bytes
)fp
->fxp_iovec_s
,
1695 n
* sizeof(fp
->fxp_iovec_s
[0]), D
);
1697 panic("FXP","fxp_readv_s: sys_safecopyfrom failed", r
);
1699 for (j
= 0, iovp
= fp
->fxp_iovec_s
; j
<n
; j
++, iovp
++)
1702 if (size
+ s
> packlen
)
1704 assert(packlen
> size
);
1708 r
= sys_safecopyto(fxp_client
, iovp
->iov_grant
,
1709 0, (vir_bytes
)(rfdp
->rfd_buf
+o
), s
, D
);
1712 panic("FXP","fxp_readv: sys_safecopyto failed",
1717 if (size
== packlen
)
1721 if (size
== packlen
)
1729 fp
->fxp_read_s
= packlen
;
1730 fp
->fxp_flags
= (fp
->fxp_flags
& ~FF_READING
) | FF_PACK_RECV
;
1732 /* Re-init the current buffer */
1733 rfdp
->rfd_status
= 0;
1734 rfdp
->rfd_command
= RFDC_EL
;
1735 rfdp
->rfd_reserved
= 0;
1737 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
1739 fxp_rx_nbuf
= fp
->fxp_rx_nbuf
;
1740 if (fxp_rx_head
== 0)
1742 prev_rfdp
= &fp
->fxp_rx_buf
[fxp_rx_nbuf
-1];
1745 prev_rfdp
= &rfdp
[-1];
1747 assert(prev_rfdp
->rfd_command
& RFDC_EL
);
1748 prev_rfdp
->rfd_command
&= ~RFDC_EL
;
1751 if (fxp_rx_head
== fxp_rx_nbuf
)
1753 assert(fxp_rx_head
< fxp_rx_nbuf
);
1754 fp
->fxp_rx_head
= fxp_rx_head
;
1757 reply(fp
, OK
, FALSE
);
1762 if (fp
->fxp_rx_need_restart
)
1764 fp
->fxp_rx_need_restart
= 0;
1766 /* Check the status of the RU */
1767 scb_status
= fxp_inb(port
, SCB_STATUS
);
1768 if ((scb_status
& SS_RUS_MASK
) != SS_RU_NORES
)
1770 /* Race condition? */
1771 printf("fxp_readv: restart race: 0x%x\n",
1773 assert((scb_status
& SS_RUS_MASK
) == SS_RU_READY
);
1782 assert(fp
->fxp_flags
& FF_READING
);
1784 /* No need to store any state */
1788 fp
->fxp_rx_mess
= *mp
;
1789 assert(!(fp
->fxp_flags
& FF_READING
));
1790 fp
->fxp_flags
|= FF_READING
;
1792 reply(fp
, OK
, FALSE
);
1795 /*===========================================================================*
1797 *===========================================================================*/
1798 static void fxp_do_conf(fp
)
1805 /* Configure device */
1806 tmpbufp
->cc
.cc_status
= 0;
1807 tmpbufp
->cc
.cc_command
= CBL_C_EL
| CBL_CONF
;
1808 tmpbufp
->cc
.cc_linkaddr
= 0;
1809 memcpy(tmpbufp
->cc
.cc_bytes
, fp
->fxp_conf_bytes
,
1810 sizeof(tmpbufp
->cc
.cc_bytes
));
1812 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&tmpbufp
->cc
,
1813 (phys_bytes
)sizeof(tmpbufp
->cc
), &bus_addr
);
1815 panic("FXP","sys_umap failed", r
);
1817 fxp_cu_ptr_cmd(fp
, SC_CU_START
, bus_addr
, TRUE
/* check idle */);
1821 /* Wait for CU command to complete */
1822 if (tmpbufp
->cc
.cc_status
& CBL_F_C
)
1824 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(100000));
1826 if (!(tmpbufp
->cc
.cc_status
& CBL_F_C
))
1827 panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM
);
1828 if (!(tmpbufp
->cc
.cc_status
& CBL_F_OK
))
1829 panic("FXP","fxp_do_conf: CU command failed", NO_NUM
);
1833 /*===========================================================================*
1835 *===========================================================================*/
1836 static void fxp_cu_ptr_cmd(fp
, cmd
, bus_addr
, check_idle
)
1839 phys_bytes bus_addr
;
1846 port
= fp
->fxp_base_port
;
1850 /* Consistency check. Make sure that CU is idle */
1851 if ((fxp_inb(port
, SCB_STATUS
) & SS_CUS_MASK
) != SS_CU_IDLE
)
1852 panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM
);
1855 fxp_outl(port
, SCB_POINTER
, bus_addr
);
1856 fxp_outb(port
, SCB_CMD
, cmd
);
1858 /* What is a reasonable time-out? There is nothing in the
1859 * documentation. 1 ms should be enough.
1863 /* Wait for CU command to be accepted */
1864 scb_cmd
= fxp_inb(port
, SCB_CMD
);
1865 if ((scb_cmd
& SC_CUC_MASK
) == SC_CU_NOP
)
1867 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(100000));
1869 if ((scb_cmd
& SC_CUC_MASK
) != SC_CU_NOP
)
1870 panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM
);
1873 /*===========================================================================*
1875 *===========================================================================*/
1876 static void fxp_ru_ptr_cmd(fp
, cmd
, bus_addr
, check_idle
)
1879 phys_bytes bus_addr
;
1886 port
= fp
->fxp_base_port
;
1890 /* Consistency check, make sure that RU is idle */
1891 if ((fxp_inb(port
, SCB_STATUS
) & SS_RUS_MASK
) != SS_RU_IDLE
)
1892 panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM
);
1895 fxp_outl(port
, SCB_POINTER
, bus_addr
);
1896 fxp_outb(port
, SCB_CMD
, cmd
);
1900 /* Wait for RU command to be accepted */
1901 scb_cmd
= fxp_inb(port
, SCB_CMD
);
1902 if ((scb_cmd
& SC_RUC_MASK
) == SC_RU_NOP
)
1904 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(1000));
1906 if ((scb_cmd
& SC_RUC_MASK
) != SC_RU_NOP
)
1907 panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM
);
1910 /*===========================================================================*
1912 *===========================================================================*/
1913 static void fxp_restart_ru(fp
)
1920 port
= fp
->fxp_base_port
;
1922 fxp_rx_nbuf
= fp
->fxp_rx_nbuf
;
1923 for (i
= 0, rfdp
= fp
->fxp_rx_buf
; i
<fxp_rx_nbuf
; i
++, rfdp
++)
1925 rfdp
->rfd_status
= 0;
1926 rfdp
->rfd_command
= 0;
1927 if (i
== fp
->fxp_rx_nbuf
-1)
1928 rfdp
->rfd_command
= RFDC_EL
;
1929 rfdp
->rfd_reserved
= 0;
1931 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
1935 /* Make sure that RU is in the 'No resources' state */
1936 if ((fxp_inb(port
, SCB_STATUS
) & SS_RUS_MASK
) != SS_RU_NORES
)
1937 panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM
);
1939 fxp_ru_ptr_cmd(fp
, SC_RU_START
, fp
->fxp_rx_busaddr
,
1940 FALSE
/* do not check idle */);
1943 /*===========================================================================*
1945 *===========================================================================*/
1946 static void fxp_getstat(mp
)
1956 dl_port
= mp
->DL_PORT
;
1957 if (dl_port
< 0 || dl_port
>= FXP_PORT_NR
)
1958 panic("FXP","fxp_getstat: illegal port", dl_port
);
1959 fp
= &fxp_table
[dl_port
];
1960 fp
->fxp_client
= mp
->DL_PROC
;
1962 assert(fp
->fxp_mode
== FM_ENABLED
);
1963 assert(fp
->fxp_flags
& FF_ENABLED
);
1965 port
= fp
->fxp_base_port
;
1967 p
= &fp
->fxp_stat
.sc_tx_fcp
;
1970 /* The dump commmand doesn't take a pointer. Setting a pointer
1971 * doesn't hard though.
1973 fxp_cu_ptr_cmd(fp
, SC_CU_DUMP_SC
, 0, FALSE
/* do not check idle */);
1977 /* Wait for CU command to complete */
1980 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(1000));
1983 panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM
);
1985 panic("FXP","fxp_getstat: bad magic", NO_NUM
);
1988 fp
->fxp_stat
.sc_rx_crc
+
1989 fp
->fxp_stat
.sc_rx_align
+
1990 fp
->fxp_stat
.sc_rx_resource
+
1991 fp
->fxp_stat
.sc_rx_overrun
+
1992 fp
->fxp_stat
.sc_rx_cd
+
1993 fp
->fxp_stat
.sc_rx_short
;
1995 fp
->fxp_stat
.sc_tx_maxcol
+
1996 fp
->fxp_stat
.sc_tx_latecol
+
1997 fp
->fxp_stat
.sc_tx_crs
;
1998 stats
.ets_OVW
= fp
->fxp_stat
.sc_rx_overrun
;
1999 stats
.ets_CRCerr
= fp
->fxp_stat
.sc_rx_crc
;
2000 stats
.ets_frameAll
= fp
->fxp_stat
.sc_rx_align
;
2001 stats
.ets_missedP
= fp
->fxp_stat
.sc_rx_resource
;
2002 stats
.ets_packetR
= fp
->fxp_stat
.sc_rx_good
;
2003 stats
.ets_packetT
= fp
->fxp_stat
.sc_tx_good
;
2004 stats
.ets_transDef
= fp
->fxp_stat
.sc_tx_defered
;
2005 stats
.ets_collision
= fp
->fxp_stat
.sc_tx_totcol
;
2006 stats
.ets_transAb
= fp
->fxp_stat
.sc_tx_maxcol
;
2007 stats
.ets_carrSense
= fp
->fxp_stat
.sc_tx_crs
;
2008 stats
.ets_fifoUnder
= fp
->fxp_stat
.sc_tx_underrun
;
2009 stats
.ets_fifoOver
= fp
->fxp_stat
.sc_rx_overrun
;
2010 stats
.ets_CDheartbeat
= 0;
2011 stats
.ets_OWC
= fp
->fxp_stat
.sc_tx_latecol
;
2013 r
= sys_vircopy(SELF
, D
, (vir_bytes
)&stats
,
2014 mp
->DL_PROC
, D
, (vir_bytes
) mp
->DL_ADDR
, sizeof(stats
));
2016 panic(__FILE__
,"fxp_getstat: sys_vircopy failed", r
);
2018 mp
->m_type
= DL_STAT_REPLY
;
2019 mp
->DL_PORT
= dl_port
;
2021 r
= send(mp
->m_source
, mp
);
2023 panic(__FILE__
, "fxp_getstat: send failed: %d\n", r
);
2027 /*===========================================================================*
2029 *===========================================================================*/
2030 static void fxp_getstat_s(mp
)
2040 dl_port
= mp
->DL_PORT
;
2041 if (dl_port
< 0 || dl_port
>= FXP_PORT_NR
)
2042 panic("FXP","fxp_getstat: illegal port", dl_port
);
2043 fp
= &fxp_table
[dl_port
];
2044 fp
->fxp_client
= mp
->DL_PROC
;
2046 assert(fp
->fxp_mode
== FM_ENABLED
);
2047 assert(fp
->fxp_flags
& FF_ENABLED
);
2049 port
= fp
->fxp_base_port
;
2051 p
= &fp
->fxp_stat
.sc_tx_fcp
;
2054 /* The dump commmand doesn't take a pointer. Setting a pointer
2055 * doesn't hurt though.
2057 fxp_cu_ptr_cmd(fp
, SC_CU_DUMP_SC
, 0, FALSE
/* do not check idle */);
2061 /* Wait for CU command to complete */
2064 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(1000));
2067 panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM
);
2069 panic("FXP","fxp_getstat: bad magic", NO_NUM
);
2072 fp
->fxp_stat
.sc_rx_crc
+
2073 fp
->fxp_stat
.sc_rx_align
+
2074 fp
->fxp_stat
.sc_rx_resource
+
2075 fp
->fxp_stat
.sc_rx_overrun
+
2076 fp
->fxp_stat
.sc_rx_cd
+
2077 fp
->fxp_stat
.sc_rx_short
;
2079 fp
->fxp_stat
.sc_tx_maxcol
+
2080 fp
->fxp_stat
.sc_tx_latecol
+
2081 fp
->fxp_stat
.sc_tx_crs
;
2082 stats
.ets_OVW
= fp
->fxp_stat
.sc_rx_overrun
;
2083 stats
.ets_CRCerr
= fp
->fxp_stat
.sc_rx_crc
;
2084 stats
.ets_frameAll
= fp
->fxp_stat
.sc_rx_align
;
2085 stats
.ets_missedP
= fp
->fxp_stat
.sc_rx_resource
;
2086 stats
.ets_packetR
= fp
->fxp_stat
.sc_rx_good
;
2087 stats
.ets_packetT
= fp
->fxp_stat
.sc_tx_good
;
2088 stats
.ets_transDef
= fp
->fxp_stat
.sc_tx_defered
;
2089 stats
.ets_collision
= fp
->fxp_stat
.sc_tx_totcol
;
2090 stats
.ets_transAb
= fp
->fxp_stat
.sc_tx_maxcol
;
2091 stats
.ets_carrSense
= fp
->fxp_stat
.sc_tx_crs
;
2092 stats
.ets_fifoUnder
= fp
->fxp_stat
.sc_tx_underrun
;
2093 stats
.ets_fifoOver
= fp
->fxp_stat
.sc_rx_overrun
;
2094 stats
.ets_CDheartbeat
= 0;
2095 stats
.ets_OWC
= fp
->fxp_stat
.sc_tx_latecol
;
2097 r
= sys_safecopyto(mp
->DL_PROC
, mp
->DL_GRANT
, 0, (vir_bytes
)&stats
,
2100 panic(__FILE__
,"fxp_getstat_s: sys_safecopyto failed", r
);
2102 mp
->m_type
= DL_STAT_REPLY
;
2103 mp
->DL_PORT
= dl_port
;
2105 r
= send(mp
->m_source
, mp
);
2107 panic(__FILE__
, "fxp_getstat_s: send failed: %d\n", r
);
2111 /*===========================================================================*
2113 *===========================================================================*/
2114 static void fxp_getname(mp
)
2119 strncpy(mp
->DL_NAME
, progname
, sizeof(mp
->DL_NAME
));
2120 mp
->DL_NAME
[sizeof(mp
->DL_NAME
)-1]= '\0';
2121 mp
->m_type
= DL_NAME_REPLY
;
2122 r
= send(mp
->m_source
, mp
);
2124 panic("FXP", "fxp_getname: send failed", r
);
2127 /*===========================================================================*
2129 *===========================================================================*/
2130 static int fxp_handler(fp
)
2138 port
= fp
->fxp_base_port
;
2141 isr
= fxp_inb(port
, SCB_INT_STAT
);
2142 fxp_outb(port
, SCB_INT_STAT
, isr
);
2148 if (!fp
->fxp_got_int
&& (fp
->fxp_flags
& FF_READING
))
2150 fp
->fxp_got_int
= TRUE
;
2151 interrupt(fxp_tasknr
);
2157 if (!fp
->fxp_tx_idle
)
2159 fp
->fxp_send_int
= TRUE
;
2160 if (!fp
->fxp_got_int
)
2162 fp
->fxp_got_int
= TRUE
;
2163 interrupt(fxp_tasknr
);
2171 /* Assume that receive buffer is full of packets. fxp_readv
2172 * will restart the RU.
2174 fp
->fxp_rx_need_restart
= 1;
2178 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
2185 /*===========================================================================*
2187 *===========================================================================*/
2188 static void fxp_check_ints(fp
)
2191 int n
, fxp_flags
, prev_tail
;
2192 int fxp_tx_tail
, fxp_tx_nbuf
, fxp_tx_threshold
;
2199 fxp_flags
= fp
->fxp_flags
;
2201 if (fxp_flags
& FF_READING
)
2203 if (!(fp
->fxp_rx_buf
[fp
->fxp_rx_head
].rfd_status
& RFDS_C
))
2205 else if (fp
->fxp_rx_mess
.m_type
== DL_READV
)
2207 fxp_readv(&fp
->fxp_rx_mess
, TRUE
/* from int */,
2208 TRUE
/* vectored */);
2210 else if (fp
->fxp_rx_mess
.m_type
== DL_READV_S
)
2212 fxp_readv_s(&fp
->fxp_rx_mess
, TRUE
/* from int */);
2217 assert(fp
->fxp_rx_mess
.m_type
== DL_READ
);
2218 fxp_readv(&fp
->fxp_rx_mess
, TRUE
/* from int */,
2219 FALSE
/* !vectored */);
2222 if (fp
->fxp_tx_idle
)
2223 ; /* Nothing to do */
2224 else if (fp
->fxp_send_int
)
2226 fp
->fxp_send_int
= FALSE
;
2227 fxp_tx_tail
= fp
->fxp_tx_tail
;
2228 fxp_tx_nbuf
= fp
->fxp_tx_nbuf
;
2232 txp
= &fp
->fxp_tx_buf
[fxp_tx_tail
];
2233 tx_status
= txp
->tx_status
;
2234 if (!(tx_status
& TXS_C
))
2239 assert(tx_status
& TXS_OK
);
2240 if (tx_status
& TXS_U
)
2242 fxp_tx_threshold
= fp
->fxp_tx_threshold
;
2243 if (fxp_tx_threshold
< TXTT_MAX
)
2246 fp
->fxp_tx_threshold
= fxp_tx_threshold
;
2249 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
2253 if (txp
->tx_command
& TXC_EL
)
2260 if (fxp_tx_tail
== fxp_tx_nbuf
)
2262 assert(fxp_tx_tail
< fxp_tx_nbuf
);
2265 if (fp
->fxp_need_conf
)
2267 /* Check the status of the CU */
2268 port
= fp
->fxp_base_port
;
2269 scb_status
= fxp_inb(port
, SCB_STATUS
);
2270 if ((scb_status
& SS_CUS_MASK
) != SS_CU_IDLE
)
2273 printf("scb_status = 0x%x\n", scb_status
);
2277 printf("fxp_check_ints: fxp_need_conf\n");
2278 fp
->fxp_need_conf
= FALSE
;
2285 if (!fp
->fxp_tx_idle
)
2287 fp
->fxp_tx_tail
= fxp_tx_tail
;
2289 /* Check the status of the CU */
2290 port
= fp
->fxp_base_port
;
2291 scb_status
= fxp_inb(port
, SCB_STATUS
);
2292 if ((scb_status
& SS_CUS_MASK
) != SS_CU_IDLE
)
2295 printf("scb_status = 0x%x\n",
2301 if (fxp_tx_tail
== 0)
2302 prev_tail
= fxp_tx_nbuf
-1;
2304 prev_tail
= fxp_tx_tail
-1;
2305 busaddr
= fp
->fxp_tx_buf
[prev_tail
].
2308 fxp_cu_ptr_cmd(fp
, SC_CU_START
,
2309 busaddr
, 1 /* check idle */);
2313 if (fp
->fxp_flags
& FF_SEND_AVAIL
)
2315 if (fp
->fxp_tx_mess
.m_type
== DL_WRITEV
)
2317 fxp_writev(&fp
->fxp_tx_mess
,
2318 TRUE
/* from int */,
2319 TRUE
/* vectored */);
2321 else if (fp
->fxp_tx_mess
.m_type
== DL_WRITEV_S
)
2323 fxp_writev_s(&fp
->fxp_tx_mess
,
2324 TRUE
/* from int */);
2328 assert(fp
->fxp_tx_mess
.m_type
==
2330 fxp_writev(&fp
->fxp_tx_mess
,
2331 TRUE
/* from int */,
2332 FALSE
/* !vectored */);
2338 if (fp
->fxp_report_link
)
2339 fxp_report_link(fp
);
2341 if (fp
->fxp_flags
& (FF_PACK_SENT
| FF_PACK_RECV
))
2342 reply(fp
, OK
, TRUE
);
2345 /*===========================================================================*
2347 *===========================================================================*/
2348 static void fxp_watchdog_f(tp
)
2354 tmr_arg(&fxp_watchdog
)->ta_int
= 0;
2355 fxp_set_timer(&fxp_watchdog
, system_hz
, fxp_watchdog_f
);
2357 for (i
= 0, fp
= &fxp_table
[0]; i
<FXP_PORT_NR
; i
++, fp
++)
2359 if (fp
->fxp_mode
!= FM_ENABLED
)
2362 /* Handle race condition, MII interface mgith be busy */
2363 if(!fp
->fxp_mii_busy
)
2365 /* Check the link status. */
2366 if (fxp_link_changed(fp
))
2369 printf("fxp_watchdog_f: link changed\n");
2371 fp
->fxp_report_link
= TRUE
;
2372 fp
->fxp_got_int
= TRUE
;
2373 interrupt(fxp_tasknr
);
2377 if (!(fp
->fxp_flags
& FF_SEND_AVAIL
))
2379 /* Assume that an idle system is alive */
2380 fp
->fxp_tx_alive
= TRUE
;
2383 if (fp
->fxp_tx_alive
)
2385 fp
->fxp_tx_alive
= FALSE
;
2389 fp
->fxp_need_reset
= TRUE
;
2390 fp
->fxp_got_int
= TRUE
;
2391 interrupt(fxp_tasknr
);
2395 /*===========================================================================*
2396 * fxp_link_changed *
2397 *===========================================================================*/
2398 static int fxp_link_changed(fp
)
2403 scr
= mii_read(fp
, MII_SCR
);
2404 scr
&= ~(MII_SCR_RES
|MII_SCR_RES_1
);
2406 return (fp
->fxp_mii_scr
!= scr
);
2409 /*===========================================================================*
2411 *===========================================================================*/
2412 static void fxp_report_link(fp
)
2416 u16_t mii_ctrl
, mii_status
, mii_id1
, mii_id2
,
2417 mii_ana
, mii_anlpa
, mii_ane
, mii_extstat
,
2418 mii_ms_ctrl
, mii_ms_status
, scr
;
2421 int f
, link_up
, ms_regs
;
2423 /* Assume an 82555 (compatible) PHY. The should be changed for
2424 * 82557 NICs with different PHYs
2426 ms_regs
= 0; /* No master/slave registers. */
2428 fp
->fxp_report_link
= FALSE
;
2429 port
= fp
->fxp_base_port
;
2431 scr
= mii_read(fp
, MII_SCR
);
2432 scr
&= ~(MII_SCR_RES
|MII_SCR_RES_1
);
2433 fp
->fxp_mii_scr
= scr
;
2435 mii_ctrl
= mii_read(fp
, MII_CTRL
);
2436 mii_read(fp
, MII_STATUS
); /* Read the status register twice, why? */
2437 mii_status
= mii_read(fp
, MII_STATUS
);
2438 mii_id1
= mii_read(fp
, MII_PHYID_H
);
2439 mii_id2
= mii_read(fp
, MII_PHYID_L
);
2440 mii_ana
= mii_read(fp
, MII_ANA
);
2441 mii_anlpa
= mii_read(fp
, MII_ANLPA
);
2442 mii_ane
= mii_read(fp
, MII_ANE
);
2443 if (mii_status
& MII_STATUS_EXT_STAT
)
2444 mii_extstat
= mii_read(fp
, MII_EXT_STATUS
);
2449 mii_ms_ctrl
= mii_read(fp
, MII_MS_CTRL
);
2450 mii_ms_status
= mii_read(fp
, MII_MS_STATUS
);
2458 /* How do we know about the link status? */
2459 link_up
= !!(mii_status
& MII_STATUS_LS
);
2461 fp
->fxp_link_up
= link_up
;
2465 printf("%s: link down\n", fp
->fxp_name
);
2470 oui
= (mii_id1
<< MII_PH_OUI_H_C_SHIFT
) |
2471 ((mii_id2
& MII_PL_OUI_L_MASK
) >> MII_PL_OUI_L_SHIFT
);
2472 model
= ((mii_id2
& MII_PL_MODEL_MASK
) >> MII_PL_MODEL_SHIFT
);
2473 rev
= (mii_id2
& MII_PL_REV_MASK
);
2476 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui
, model
, rev
);
2479 if (mii_ctrl
& (MII_CTRL_LB
|MII_CTRL_PD
|MII_CTRL_ISO
))
2481 printf("%s: PHY: ", fp
->fxp_name
);
2483 if (mii_ctrl
& MII_CTRL_LB
)
2485 printf("loopback mode");
2488 if (mii_ctrl
& MII_CTRL_PD
)
2490 if (!f
) printf(", ");
2492 printf("powered down");
2494 if (mii_ctrl
& MII_CTRL_ISO
)
2496 if (!f
) printf(", ");
2503 if (!(mii_ctrl
& MII_CTRL_ANE
))
2505 printf("%s: manual config: ", fp
->fxp_name
);
2506 switch(mii_ctrl
& (MII_CTRL_SP_LSB
|MII_CTRL_SP_MSB
))
2508 case MII_CTRL_SP_10
: printf("10 Mbps"); break;
2509 case MII_CTRL_SP_100
: printf("100 Mbps"); break;
2510 case MII_CTRL_SP_1000
: printf("1000 Mbps"); break;
2511 case MII_CTRL_SP_RES
: printf("reserved speed"); break;
2513 if (mii_ctrl
& MII_CTRL_DM
)
2514 printf(", full duplex");
2516 printf(", half duplex");
2521 if (!debug
) goto resspeed
;
2523 printf("%s: ", fp
->fxp_name
);
2524 mii_print_stat_speed(mii_status
, mii_extstat
);
2527 if (!(mii_status
& MII_STATUS_ANC
))
2528 printf("%s: auto-negotiation not complete\n", fp
->fxp_name
);
2529 if (mii_status
& MII_STATUS_RF
)
2530 printf("%s: remote fault detected\n", fp
->fxp_name
);
2531 if (!(mii_status
& MII_STATUS_ANA
))
2533 printf("%s: local PHY has no auto-negotiation ability\n",
2536 if (!(mii_status
& MII_STATUS_LS
))
2537 printf("%s: link down\n", fp
->fxp_name
);
2538 if (mii_status
& MII_STATUS_JD
)
2539 printf("%s: jabber condition detected\n", fp
->fxp_name
);
2540 if (!(mii_status
& MII_STATUS_EC
))
2542 printf("%s: no extended register set\n", fp
->fxp_name
);
2545 if (!(mii_status
& MII_STATUS_ANC
))
2548 printf("%s: local cap.: ", fp
->fxp_name
);
2549 if (mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
2551 printf("1000 Mbps: T-");
2552 switch(mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
2554 case MII_MSC_1000T_FD
: printf("FD"); break;
2555 case MII_MSC_1000T_HD
: printf("HD"); break;
2556 default: printf("FD/HD"); break;
2561 mii_print_techab(mii_ana
);
2564 if (mii_ane
& MII_ANE_PDF
)
2565 printf("%s: parallel detection fault\n", fp
->fxp_name
);
2566 if (!(mii_ane
& MII_ANE_LPANA
))
2568 printf("%s: link-partner does not support auto-negotiation\n",
2573 printf("%s: remote cap.: ", fp
->fxp_name
);
2574 if (mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
2575 if (mii_ms_status
& (MII_MSS_LP1000T_FD
| MII_MSS_LP1000T_HD
))
2577 printf("1000 Mbps: T-");
2578 switch(mii_ms_status
&
2579 (MII_MSS_LP1000T_FD
| MII_MSS_LP1000T_HD
))
2581 case MII_MSS_LP1000T_FD
: printf("FD"); break;
2582 case MII_MSS_LP1000T_HD
: printf("HD"); break;
2583 default: printf("FD/HD"); break;
2588 mii_print_techab(mii_anlpa
);
2593 printf("%s: ", fp
->fxp_name
);
2594 if (mii_ms_ctrl
& MII_MSC_MS_MANUAL
)
2597 (mii_ms_ctrl
& MII_MSC_MS_VAL
) ?
2598 "MASTER" : "SLAVE");
2603 (mii_ms_ctrl
& MII_MSC_MULTIPORT
) ?
2604 "multiport" : "single-port");
2606 if (mii_ms_ctrl
& MII_MSC_RES
)
2607 printf(" reserved<0x%x>", mii_ms_ctrl
& MII_MSC_RES
);
2609 if (mii_ms_status
& MII_MSS_FAULT
)
2610 printf("M/S config fault");
2611 else if (mii_ms_status
& MII_MSS_MASTER
)
2618 if (mii_ms_status
& (MII_MSS_LP1000T_FD
|MII_MSS_LP1000T_HD
))
2620 if (!(mii_ms_status
& MII_MSS_LOCREC
))
2622 printf("%s: local receiver not OK\n",
2625 if (!(mii_ms_status
& MII_MSS_REMREC
))
2627 printf("%s: remote receiver not OK\n",
2631 if (mii_ms_status
& (MII_MSS_RES
|MII_MSS_IDLE_ERR
))
2633 printf("%s", fp
->fxp_name
);
2634 if (mii_ms_status
& MII_MSS_RES
)
2635 printf(" reserved<0x%x>", mii_ms_status
& MII_MSS_RES
);
2636 if (mii_ms_status
& MII_MSS_IDLE_ERR
)
2638 printf(" idle error %d",
2639 mii_ms_status
& MII_MSS_IDLE_ERR
);
2646 printf("%s: link up, %d Mbps, %s duplex\n",
2647 fp
->fxp_name
, (scr
& MII_SCR_100
) ? 100 : 10,
2648 (scr
& MII_SCR_FD
) ? "full" : "half");
2653 /*===========================================================================*
2655 *===========================================================================*/
2656 static void fxp_stop()
2662 for (i
= 0, fp
= &fxp_table
[0]; i
<FXP_PORT_NR
; i
++, fp
++)
2664 if (fp
->fxp_mode
!= FM_ENABLED
)
2666 if (!(fp
->fxp_flags
& FF_ENABLED
))
2668 port
= fp
->fxp_base_port
;
2672 printf("%s: resetting device\n", fp
->fxp_name
);
2673 fxp_outl(port
, CSR_PORT
, CP_CMD_SOFT_RESET
);
2678 /*===========================================================================*
2680 *===========================================================================*/
2681 static void reply(fp
, err
, may_block
)
2691 if (fp
->fxp_flags
& FF_PACK_SENT
)
2692 status
|= DL_PACK_SEND
;
2693 if (fp
->fxp_flags
& FF_PACK_RECV
)
2694 status
|= DL_PACK_RECV
;
2696 reply
.m_type
= DL_TASK_REPLY
;
2697 reply
.DL_PORT
= fp
- fxp_table
;
2698 reply
.DL_PROC
= fp
->fxp_client
;
2699 reply
.DL_STAT
= status
| ((u32_t
) err
<< 16);
2700 reply
.DL_COUNT
= fp
->fxp_read_s
;
2702 reply
.DL_CLCK
= get_uptime();
2707 r
= send(fp
->fxp_client
, &reply
);
2709 if (r
== ELOCKED
&& may_block
)
2712 printW(); printf("send locked\n");
2718 panic("FXP","fxp: send failed:", r
);
2721 fp
->fxp_flags
&= ~(FF_PACK_SENT
| FF_PACK_RECV
);
2724 /*===========================================================================*
2726 *===========================================================================*/
2727 static void mess_reply(req
, reply_mess
)
2729 message
*reply_mess
;
2731 if (send(req
->m_source
, reply_mess
) != OK
)
2732 panic("FXP","fxp: unable to mess_reply", NO_NUM
);
2735 /*===========================================================================*
2737 *===========================================================================*/
2738 PRIVATE u16_t
eeprom_read(fp
, reg
)
2746 alen
= fp
->fxp_ee_addrlen
;
2749 eeprom_addrsize(fp
);
2750 alen
= fp
->fxp_ee_addrlen
;
2751 assert(alen
== 6 || alen
== 8);
2754 port
= fp
->fxp_base_port
;
2756 fxp_outb(port
, CSR_EEPROM
, CE_EECS
); /* Enable EEPROM */
2757 v
= EEPROM_READ_PREFIX
;
2758 for (i
= EEPROM_PREFIX_LEN
-1; i
>= 0; i
--)
2760 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
2761 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2762 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2763 micro_delay(EESK_PERIOD
/2+1);
2764 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2765 micro_delay(EESK_PERIOD
/2+1);
2769 for (i
= alen
-1; i
>= 0; i
--)
2771 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
2772 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2773 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2774 micro_delay(EESK_PERIOD
/2+1);
2775 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2776 micro_delay(EESK_PERIOD
/2+1);
2780 for (i
= 0; i
<16; i
++)
2782 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| CE_EESK
); /* Clock */
2783 micro_delay(EESK_PERIOD
/2+1);
2784 b
= !!(fxp_inb(port
, CSR_EEPROM
) & CE_EEDO
);
2786 fxp_outb(port
, CSR_EEPROM
, CE_EECS
);
2787 micro_delay(EESK_PERIOD
/2+1);
2789 fxp_outb(port
, CSR_EEPROM
, 0); /* Disable EEPROM */
2790 micro_delay(EECS_DELAY
);
2795 /*===========================================================================*
2797 *===========================================================================*/
2798 PRIVATE
void eeprom_addrsize(fp
)
2805 port
= fp
->fxp_base_port
;
2807 /* Try to find out the size of the EEPROM */
2808 fxp_outb(port
, CSR_EEPROM
, CE_EECS
); /* Enable EEPROM */
2809 v
= EEPROM_READ_PREFIX
;
2810 for (i
= EEPROM_PREFIX_LEN
-1; i
>= 0; i
--)
2812 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
2813 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2814 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2815 micro_delay(EESK_PERIOD
/2+1);
2816 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2817 micro_delay(EESK_PERIOD
/2+1);
2820 for (i
= 0; i
<32; i
++)
2823 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2824 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2825 micro_delay(EESK_PERIOD
/2+1);
2826 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2827 micro_delay(EESK_PERIOD
/2+1);
2828 v
= fxp_inb(port
, CSR_EEPROM
);
2833 panic("FXP","eeprom_addrsize: failed", NO_NUM
);
2834 fp
->fxp_ee_addrlen
= i
+1;
2836 /* Discard 16 data bits */
2837 for (i
= 0; i
<16; i
++)
2839 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| CE_EESK
); /* Clock */
2840 micro_delay(EESK_PERIOD
/2+1);
2841 fxp_outb(port
, CSR_EEPROM
, CE_EECS
);
2842 micro_delay(EESK_PERIOD
/2+1);
2844 fxp_outb(port
, CSR_EEPROM
, 0); /* Disable EEPROM */
2845 micro_delay(EECS_DELAY
);
2848 printf("%s EEPROM address length: %d\n",
2849 fp
->fxp_name
, fp
->fxp_ee_addrlen
);
2853 /*===========================================================================*
2855 *===========================================================================*/
2856 PRIVATE u16_t
mii_read(fp
, reg
)
2864 port
= fp
->fxp_base_port
;
2866 assert(!fp
->fxp_mii_busy
);
2869 if (!(fxp_inl(port
, CSR_MDI_CTL
) & CM_READY
))
2870 panic("FXP","mii_read: MDI not ready", NO_NUM
);
2871 fxp_outl(port
, CSR_MDI_CTL
, CM_READ
| (1 << CM_PHYADDR_SHIFT
) |
2872 (reg
<< CM_REG_SHIFT
));
2876 v
= fxp_inl(port
, CSR_MDI_CTL
);
2879 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(100000));
2881 if (!(v
& CM_READY
))
2882 panic("FXP","mii_read: MDI not ready after command", NO_NUM
);
2885 assert(!fp
->fxp_mii_busy
);
2887 return v
& CM_DATA_MASK
;
2890 /*===========================================================================*
2892 *===========================================================================*/
2893 PRIVATE
void fxp_set_timer(tp
, delta
, watchdog
)
2894 timer_t
*tp
; /* timer to be set */
2895 clock_t delta
; /* in how many ticks */
2896 tmr_func_t watchdog
; /* watchdog function to be called */
2898 clock_t now
; /* current time */
2901 /* Get the current time. */
2904 panic("FXP","unable to get uptime from clock", r
);
2906 /* Add the timer to the local timer queue. */
2907 tmrs_settimer(&fxp_timers
, tp
, now
+ delta
, watchdog
, NULL
);
2909 /* Possibly reschedule an alarm call. This happens when a new timer
2910 * is added in front.
2912 if (fxp_next_timeout
== 0 ||
2913 fxp_timers
->tmr_exp_time
< fxp_next_timeout
)
2915 fxp_next_timeout
= fxp_timers
->tmr_exp_time
;
2917 printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
2918 fxp_next_timeout
, fxp_next_timeout
-now
);
2920 r
= sys_setalarm(fxp_next_timeout
, 1);
2922 panic("FXP","unable to set synchronous alarm", r
);
2926 /*===========================================================================*
2928 *===========================================================================*/
2929 PRIVATE
void fxp_expire_timers()
2931 /* A synchronous alarm message was received. Check if there are any expired
2932 * timers. Possibly reschedule the next alarm.
2934 clock_t now
; /* current time */
2937 /* Get the current time to compare the timers against. */
2940 panic("FXP","Unable to get uptime from clock.", r
);
2942 /* Scan the timers queue for expired timers. Dispatch the watchdog function
2943 * for each expired timers. Possibly a new alarm call must be scheduled.
2945 tmrs_exptimers(&fxp_timers
, now
, NULL
);
2946 if (fxp_timers
== NULL
)
2947 fxp_next_timeout
= TMR_NEVER
;
2949 { /* set new alarm */
2950 fxp_next_timeout
= fxp_timers
->tmr_exp_time
;
2951 r
= sys_setalarm(fxp_next_timeout
, 1);
2953 panic("FXP","Unable to set synchronous alarm.", r
);
2957 static u8_t
do_inb(port_t port
)
2962 r
= sys_inb(port
, &value
);
2964 panic("FXP","sys_inb failed", r
);
2968 static u32_t
do_inl(port_t port
)
2973 r
= sys_inl(port
, &value
);
2975 panic("FXP","sys_inl failed", r
);
2979 static void do_outb(port_t port
, u8_t value
)
2983 r
= sys_outb(port
, value
);
2985 panic("FXP","sys_outb failed", r
);
2988 static void do_outl(port_t port
, u32_t value
)
2992 r
= sys_outl(port
, value
);
2994 panic("FXP","sys_outl failed", r
);
2997 PRIVATE
void tell_dev(buf
, size
, pci_bus
, pci_dev
, pci_func
)
3009 r
= ds_retrieve_label_num("amddev", &u32
);
3014 "fxp`tell_dev: ds_retrieve_label_num failed for 'amddev': %d\n",
3022 m
.m_type
= IOMMU_MAP
;
3029 r
= sendrec(dev_e
, &m
);
3032 printf("fxp`tell_dev: sendrec to %d failed: %d\n",
3038 printf("fxp`tell_dev: dma map request failed: %d\n",
3045 * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $