4 * This file contains an ethernet device driver for Intel 82557, 82558,
5 * 82559, 82550, and 82562 fast ethernet controllers.
7 * Created: Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
10 #include <minix/drivers.h>
11 #include <minix/netdriver.h>
15 #include <net/gen/ether.h>
16 #include <net/gen/eth_io.h>
17 #include <machine/pci.h>
19 #include <minix/endpoint.h>
23 #define tmra_ut timer_t
24 #define tmra_inittimer(tp) tmr_inittimer(tp)
26 #define RAND_UPDATE /**/
27 #define printW() ((void)0)
33 /* Number of receive buffers */
36 /* Number of transmit buffers */
39 /* I/O vectors are handled IOVEC_NR entries at a time. */
43 #define FXP_ENVVAR "FXPETH"
52 PRIVATE
struct pcitab pcitab_fxp
[]=
54 { 0x8086, 0x1229, 0 }, /* Intel 82557, etc. */
55 { 0x8086, 0x2449, 0 }, /* Intel 82801BA/BAM/CA/CAM */
56 { 0x8086, 0x103d, 0 }, /* Intel 82801DB */
57 { 0x8086, 0x1064, 0 }, /* Intel 82562 */
62 typedef int irq_hook_t
;
64 static timer_t
*fxp_timers
= NULL
;
65 static clock_t fxp_next_timeout
= 0;
67 /* ignore interrupt for the moment */
68 #define interrupt(x) 0
85 int fxp_features
; /* Needed? */
87 int fxp_type
; /* What kind of hardware */
88 int fxp_ee_addrlen
; /* #EEPROM address bits */
96 struct rfd
*fxp_rx_buf
;
97 phys_bytes fxp_rx_busaddr
;
99 int fxp_rx_need_restart
;
100 int fxp_need_conf
; /* Re-configure after draining send
107 struct tx
*fxp_tx_buf
;
108 phys_bytes fxp_tx_busaddr
;
112 int fxp_tx_threshold
;
121 int fxp_seen
; /* TRUE iff device available */
128 ether_addr_t fxp_address
;
132 u8_t fxp_conf_bytes
[CC_BYTES_NR
];
133 char fxp_name
[sizeof("fxp#n")];
134 iovec_t fxp_iovec
[IOVEC_NR
];
135 iovec_s_t fxp_iovec_s
[IOVEC_NR
];
140 #define FM_DISABLED 0x0
141 #define FM_ENABLED 0x1
144 #define FF_EMPTY 0x000
145 #define FF_PACK_SENT 0x001
146 #define FF_PACK_RECV 0x002
147 #define FF_SEND_AVAIL 0x004
148 #define FF_READING 0x010
149 #define FF_PROMISC 0x040
150 #define FF_MULTI 0x080
151 #define FF_BROAD 0x100
152 #define FF_ENABLED 0x200
158 #define FT_UNKNOWN 0x0
160 #define FT_82558A 0x2
164 PRIVATE
int fxp_instance
;
166 PRIVATE fxp_t
*fxp_state
;
168 PRIVATE tmra_ut fxp_watchdog
;
170 PRIVATE u32_t system_hz
;
172 #define fxp_inb(port, offset) (do_inb((port) + (offset)))
173 #define fxp_inl(port, offset) (do_inl((port) + (offset)))
174 #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
175 #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
177 _PROTOTYPE( static void fxp_init
, (message
*mp
) );
178 _PROTOTYPE( static void fxp_pci_conf
, (void) );
179 _PROTOTYPE( static int fxp_probe
, (fxp_t
*fp
, int skip
) );
180 _PROTOTYPE( static void fxp_conf_hw
, (fxp_t
*fp
) );
181 _PROTOTYPE( static void fxp_init_hw
, (fxp_t
*fp
) );
182 _PROTOTYPE( static void fxp_init_buf
, (fxp_t
*fp
) );
183 _PROTOTYPE( static void fxp_reset_hw
, (fxp_t
*fp
) );
184 _PROTOTYPE( static void fxp_confaddr
, (fxp_t
*fp
) );
185 _PROTOTYPE( static void fxp_rec_mode
, (fxp_t
*fp
) );
186 _PROTOTYPE( static void fxp_writev_s
, (const message
*mp
, int from_int
) );
187 _PROTOTYPE( static void fxp_readv_s
, (message
*mp
, int from_int
) );
188 _PROTOTYPE( static void fxp_do_conf
, (fxp_t
*fp
) );
189 _PROTOTYPE( static void fxp_cu_ptr_cmd
, (fxp_t
*fp
, int cmd
,
190 phys_bytes bus_addr
, int check_idle
) );
191 _PROTOTYPE( static void fxp_ru_ptr_cmd
, (fxp_t
*fp
, int cmd
,
192 phys_bytes bus_addr
, int check_idle
) );
193 _PROTOTYPE( static void fxp_restart_ru
, (fxp_t
*fp
) );
194 _PROTOTYPE( static void fxp_getstat_s
, (message
*mp
) );
195 _PROTOTYPE( static void fxp_handler
, (fxp_t
*fp
) );
196 _PROTOTYPE( static void fxp_check_ints
, (fxp_t
*fp
) );
197 _PROTOTYPE( static void fxp_watchdog_f
, (timer_t
*tp
) );
198 _PROTOTYPE( static int fxp_link_changed
, (fxp_t
*fp
) );
199 _PROTOTYPE( static void fxp_report_link
, (fxp_t
*fp
) );
200 _PROTOTYPE( static void reply
, (fxp_t
*fp
) );
201 _PROTOTYPE( static void mess_reply
, (message
*req
, message
*reply
) );
202 _PROTOTYPE( static u16_t eeprom_read
, (fxp_t
*fp
, int reg
) );
203 _PROTOTYPE( static void eeprom_addrsize
, (fxp_t
*fp
) );
204 _PROTOTYPE( static u16_t mii_read
, (fxp_t
*fp
, int reg
) );
205 _PROTOTYPE( static void fxp_set_timer
,(timer_t
*tp
, clock_t delta
,
206 tmr_func_t watchdog
) );
207 _PROTOTYPE( static void fxp_expire_timers
,(void) );
208 _PROTOTYPE( static u8_t do_inb
, (port_t port
) );
209 _PROTOTYPE( static u32_t do_inl
, (port_t port
) );
210 _PROTOTYPE( static void do_outb
, (port_t port
, u8_t v
) );
211 _PROTOTYPE( static void do_outl
, (port_t port
, u32_t v
) );
212 _PROTOTYPE( static void tell_dev
, (vir_bytes start
, size_t size
,
213 int pci_bus
, int pci_dev
, int pci_func
) );
215 PRIVATE
void handle_hw_intr(void)
222 if (fp
->fxp_mode
!= FM_ENABLED
)
226 r
= sys_irqenable(&fp
->fxp_hook
);
228 panic("unable enable interrupts: %d", r
);
231 if (!fp
->fxp_got_int
)
234 assert(fp
->fxp_flags
& FF_ENABLED
);
238 /* SEF functions and variables. */
239 FORWARD
_PROTOTYPE( void sef_local_startup
, (void) );
240 FORWARD
_PROTOTYPE( int sef_cb_init_fresh
, (int type
, sef_init_info_t
*info
) );
241 FORWARD
_PROTOTYPE( void sef_cb_signal_handler
, (int signo
) );
243 EXTERN
char **env_argv
;
245 /*===========================================================================*
247 *===========================================================================*/
248 int main(int argc
, char *argv
[])
254 /* SEF local startup. */
255 env_setargs(argc
, argv
);
260 if ((r
= netdriver_receive(ANY
, &m
, &ipc_status
)) != OK
)
261 panic("netdriver_receive failed: %d", r
);
263 if (is_ipc_notify(ipc_status
)) {
264 switch (_ENDPOINT_P(m
.m_source
)) {
272 panic(" illegal notify from: %d", m
.m_source
);
275 /* get new message */
281 case DL_WRITEV_S
: fxp_writev_s(&m
, FALSE
); break;
282 case DL_READV_S
: fxp_readv_s(&m
, FALSE
); break;
283 case DL_CONF
: fxp_init(&m
); break;
284 case DL_GETSTAT_S
: fxp_getstat_s(&m
); break;
286 panic(" illegal message: %d", m
.m_type
);
291 /*===========================================================================*
292 * sef_local_startup *
293 *===========================================================================*/
294 PRIVATE
void sef_local_startup()
296 /* Register init callbacks. */
297 sef_setcb_init_fresh(sef_cb_init_fresh
);
298 sef_setcb_init_lu(sef_cb_init_fresh
);
299 sef_setcb_init_restart(sef_cb_init_fresh
);
301 /* Register live update callbacks. */
302 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready
);
303 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree
);
305 /* Register signal callbacks. */
306 sef_setcb_signal_handler(sef_cb_signal_handler
);
308 /* Let SEF perform startup. */
312 /*===========================================================================*
313 * sef_cb_init_fresh *
314 *===========================================================================*/
315 PRIVATE
int sef_cb_init_fresh(int UNUSED(type
), sef_init_info_t
*UNUSED(info
))
317 /* Initialize the fxp driver. */
322 system_hz
= sys_hz();
325 (void) env_parse("instance", "d", 0, &v
, 0, 255);
326 fxp_instance
= (int) v
;
328 ft
= sizeof(*fxp_state
);
330 if(!(fxp_state
= alloc_contig(ft
, 0, NULL
)))
331 panic("couldn't allocate table: %d", ENOMEM
);
333 memset(fxp_state
, 0, ft
);
335 if((r
=tsc_calibrate()) != OK
)
336 panic("tsc_calibrate failed: %d", r
);
338 /* Announce we are up! */
339 netdriver_announce();
344 /*===========================================================================*
345 * sef_cb_signal_handler *
346 *===========================================================================*/
347 PRIVATE
void sef_cb_signal_handler(int signo
)
352 /* Only check for termination signal, ignore anything else. */
353 if (signo
!= SIGTERM
) return;
357 if (fp
->fxp_mode
== FM_ENABLED
&& (fp
->fxp_flags
& FF_ENABLED
)) {
358 port
= fp
->fxp_base_port
;
362 printf("%s: resetting device\n", fp
->fxp_name
);
363 fxp_outl(port
, CSR_PORT
, CP_CMD_SOFT_RESET
);
369 /*===========================================================================*
371 *===========================================================================*/
372 static void fxp_init(mp
)
375 static int first_time
= 1;
383 fxp_pci_conf(); /* Configure PCI devices. */
385 tmra_inittimer(&fxp_watchdog
);
386 tmr_arg(&fxp_watchdog
)->ta_int
= 0;
387 fxp_set_timer(&fxp_watchdog
, system_hz
, fxp_watchdog_f
);
391 if (fp
->fxp_mode
== FM_DISABLED
)
393 /* This is the default, try to (re)locate the device. */
395 if (fp
->fxp_mode
== FM_DISABLED
)
397 /* Probe failed, or the device is configured off. */
398 reply_mess
.m_type
= DL_CONF_REPLY
;
399 reply_mess
.DL_STAT
= ENXIO
;
400 mess_reply(mp
, &reply_mess
);
403 if (fp
->fxp_mode
== FM_ENABLED
)
408 assert(fp
->fxp_mode
== FM_ENABLED
);
409 assert(fp
->fxp_flags
& FF_ENABLED
);
411 fp
->fxp_flags
&= ~(FF_PROMISC
| FF_MULTI
| FF_BROAD
);
413 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
414 fp
->fxp_flags
|= FF_PROMISC
;
415 if (mp
->DL_MODE
& DL_MULTI_REQ
)
416 fp
->fxp_flags
|= FF_MULTI
;
417 if (mp
->DL_MODE
& DL_BROAD_REQ
)
418 fp
->fxp_flags
|= FF_BROAD
;
422 reply_mess
.m_type
= DL_CONF_REPLY
;
423 reply_mess
.DL_STAT
= OK
;
424 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= fp
->fxp_address
;
426 mess_reply(mp
, &reply_mess
);
429 /*===========================================================================*
431 *===========================================================================*/
432 static void fxp_pci_conf()
434 static char envvar
[] = FXP_ENVVAR
"#";
435 static char envfmt
[] = "*:d.d.d";
442 strcpy(fp
->fxp_name
, "fxp#0");
443 fp
->fxp_name
[4] += fxp_instance
;
445 fp
->fxp_features
= FFE_NONE
;
446 envvar
[sizeof(FXP_ENVVAR
)-1]= '0'+fxp_instance
;
448 if (getenv(envvar
) != NULL
)
450 if (strcmp(getenv(envvar
), "off") == 0)
454 if (!env_prefix(envvar
, "pci"))
461 if (fp
->fxp_pcibus
== 255)
466 (void) env_parse(envvar
, envfmt
, 1, &v
, 0, 255);
471 (void) env_parse(envvar
, envfmt
, 2, &v
, 0, 255);
476 (void) env_parse(envvar
, envfmt
, 3, &v
, 0, 255);
480 if (fxp_probe(fp
, fxp_instance
))
484 /*===========================================================================*
486 *===========================================================================*/
487 static int fxp_probe(fxp_t
*fp
, int skip
)
489 int i
, r
, devind
, just_one
;
495 if ((fp
->fxp_pcibus
| fp
->fxp_pcidev
| fp
->fxp_pcifunc
) != 0)
497 /* Look for specific PCI device */
498 r
= pci_find_dev(fp
->fxp_pcibus
, fp
->fxp_pcidev
,
499 fp
->fxp_pcifunc
, &devind
);
502 printf("%s: no PCI device found at %d.%d.%d\n",
503 fp
->fxp_name
, fp
->fxp_pcibus
,
504 fp
->fxp_pcidev
, fp
->fxp_pcifunc
);
507 pci_ids(devind
, &vid
, &did
);
512 r
= pci_first_dev(&devind
, &vid
, &did
);
520 for (i
= 0; pcitab_fxp
[i
].vid
!= 0; i
++)
522 if (pcitab_fxp
[i
].vid
!= vid
)
524 if (pcitab_fxp
[i
].did
!= did
)
526 if (pcitab_fxp
[i
].checkclass
) {
527 panic("fxp_probe: class check not implemented");
531 if (pcitab_fxp
[i
].vid
!= 0)
533 if (just_one
|| !skip
)
541 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
542 fp
->fxp_name
, vid
, did
,
544 fp
->fxp_pcidev
, fp
->fxp_pcifunc
);
548 r
= pci_next_dev(&devind
, &vid
, &did
);
553 dname
= pci_dev_name(vid
, did
);
556 dname
= "unknown device";
557 printf("%s: %s (%04x/%04x) at %s\n",
558 fp
->fxp_name
, dname
, vid
, did
, pci_slot_name(devind
));
562 bar
= pci_attr_r32(devind
, PCI_BAR_2
) & 0xffffffe0;
564 panic("fxp_probe: base address is not properly configured");
566 fp
->fxp_base_port
= bar
;
568 ilr
= pci_attr_r8(devind
, PCI_ILR
);
572 printf("%s: using I/O address 0x%lx, IRQ %d\n",
573 fp
->fxp_name
, (unsigned long)bar
, ilr
);
576 rev
= pci_attr_r8(devind
, PCI_REV
);
578 fp
->fxp_type
= FT_UNKNOWN
;
581 case FXP_REV_82557A
: str
= "82557A"; /* 0x01 */
582 fp
->fxp_type
= FT_82557
;
584 case FXP_REV_82557B
: str
= "82557B"; break; /* 0x02 */
585 case FXP_REV_82557C
: str
= "82557C"; break; /* 0x03 */
586 case FXP_REV_82558A
: str
= "82558A"; /* 0x04 */
587 fp
->fxp_type
= FT_82558A
;
589 case FXP_REV_82558B
: str
= "82558B"; break; /* 0x05 */
590 case FXP_REV_82559A
: str
= "82559A"; break; /* 0x06 */
591 case FXP_REV_82559B
: str
= "82559B"; break; /* 0x07 */
592 case FXP_REV_82559C
: str
= "82559C"; /* 0x08 */
593 fp
->fxp_type
= FT_82559
;
595 case FXP_REV_82559ERA
: str
= "82559ER-A"; /* 0x09 */
596 fp
->fxp_type
= FT_82559
;
598 case FXP_REV_82550_1
: str
= "82550(1)"; /* 0x0C */
599 fp
->fxp_type
= FT_82559
;
601 case FXP_REV_82550_2
: str
= "82550(2)"; /* 0x0D */
602 fp
->fxp_type
= FT_82559
;
604 case FXP_REV_82550_3
: str
= "82550(3)"; /* 0x0E */
605 fp
->fxp_type
= FT_82559
;
607 case FXP_REV_82551_1
: str
= "82551(1)"; /* 0x0F */
608 fp
->fxp_type
= FT_82559
;
610 case FXP_REV_82551_2
: str
= "82551(2)"; /* 0x10 */
611 fp
->fxp_type
= FT_82559
;
613 case FXP_REV_82801DB
: str
= "82801DB"; /* 0x81 */
614 fp
->fxp_type
= FT_82801
;
620 printf("%s: device revision: %s\n", fp
->fxp_name
, str
);
622 printf("%s: unknown revision: 0x%x\n", fp
->fxp_name
, rev
);
625 if (fp
->fxp_type
== FT_UNKNOWN
)
627 printf("fxp_probe: device is not supported by this driver\n");
634 /*===========================================================================*
636 *===========================================================================*/
637 static void fxp_conf_hw(fxp_t
*fp
)
640 int mwi
, ext_stat1
, ext_stat2
, lim_fifo
, i82503
, fc
;
642 fp
->fxp_mode
= FM_DISABLED
; /* Superfluous */
647 /* PCI device is present */
648 fp
->fxp_mode
= FM_ENABLED
;
650 fp
->fxp_flags
= FF_EMPTY
;
653 fp
->fxp_ee_addrlen
= 0; /* Unknown */
654 fp
->fxp_need_reset
= 0;
655 fp
->fxp_report_link
= 0;
656 fp
->fxp_link_up
= -1; /* Unknown */
659 fp
->fxp_rx_need_restart
= 0;
660 fp
->fxp_need_conf
= 0;
664 fp
->fxp_tx_threshold
= TXTT_MIN
;
666 /* Try to come up with a sensible configuration for the current
667 * device. Unfortunately every device is different, defaults are
668 * not always zero, and some fields are re-used with a completely
669 * different interpretation. We start out with a sensible default
670 * for all devices and then add device specific changes.
672 fp
->fxp_conf_bytes
[0]= CC_BYTES_NR
;
673 fp
->fxp_conf_bytes
[1]= CTL_DEFAULT
| CRL_DEFAULT
;
674 fp
->fxp_conf_bytes
[2]= CAI_DEFAULT
;
675 fp
->fxp_conf_bytes
[3]= 0;
676 fp
->fxp_conf_bytes
[4]= 0;
677 fp
->fxp_conf_bytes
[5]= 0;
678 fp
->fxp_conf_bytes
[6]= CCB6_ESC
| CCB6_ETCB
| CCB6_RES
;
679 fp
->fxp_conf_bytes
[7]= CUR_1
;
680 fp
->fxp_conf_bytes
[8]= CCB8_503_MII
;
681 fp
->fxp_conf_bytes
[9]= 0;
682 fp
->fxp_conf_bytes
[10]= CLB_NORMAL
| CPAL_DEFAULT
| CCB10_NSAI
|
684 fp
->fxp_conf_bytes
[11]= 0;
685 fp
->fxp_conf_bytes
[12]= CIS_DEFAULT
;
686 fp
->fxp_conf_bytes
[13]= CCB13_DEFAULT
;
687 fp
->fxp_conf_bytes
[14]= CCB14_DEFAULT
;
688 fp
->fxp_conf_bytes
[15]= CCB15_RES1
| CCB15_RES2
;
689 fp
->fxp_conf_bytes
[16]= CCB16_DEFAULT
;
690 fp
->fxp_conf_bytes
[17]= CCB17_DEFAULT
;
691 fp
->fxp_conf_bytes
[18]= CCB18_RES1
| CCB18_PFCT
| CCB18_PE
;
692 fp
->fxp_conf_bytes
[19]= CCB19_FDPE
;
693 fp
->fxp_conf_bytes
[20]= CCB20_PFCL
| CCB20_RES1
;
694 fp
->fxp_conf_bytes
[21]= CCB21_RES21
;
697 for (i
= 0; i
<CC_BYTES_NR
; i
++)
698 printf("%d: %0x, ", i
, fp
->fxp_conf_bytes
[i
]);
702 mwi
= 0; /* Do we want "Memory Write and Invalidate"? */
703 ext_stat1
= 0; /* Do we want extended statistical counters? */
704 ext_stat2
= 0; /* Do we want even more statistical counters? */
705 lim_fifo
= 0; /* Limit number of frame in TX FIFO */
706 i82503
= 0; /* Older 10 Mbps interface on the 82557 */
707 fc
= 0; /* Flow control */
714 fp
->fxp_conf_bytes
[8] &= ~CCB8_503_MII
;
715 fp
->fxp_conf_bytes
[15] |= CCB15_CRSCDT
;
722 fp
->fxp_conf_bytes
[3] |= CCB3_MWIE
;
724 fp
->fxp_conf_bytes
[6] &= ~CCB6_ESC
;
726 fp
->fxp_conf_bytes
[6] &= ~CCB6_TCOSC
;
728 fp
->fxp_conf_bytes
[7] |= CCB7_2FFIFO
;
731 /* From FreeBSD driver */
732 fp
->fxp_conf_bytes
[16]= 0x1f;
733 fp
->fxp_conf_bytes
[17]= 0x01;
735 fp
->fxp_conf_bytes
[19] |= CCB19_FDRSTAFC
|
739 fp
->fxp_conf_bytes
[18] |= CCB18_LROK
;
741 if (fp
->fxp_type
== FT_82801
)
743 fp
->fxp_conf_bytes
[6] = 0xba; /* ctrl 1 */
744 fp
->fxp_conf_bytes
[15] = 0x48; /* promiscuous */
745 fp
->fxp_conf_bytes
[21] = 0x05; /* mc_all */
749 panic("fxp_conf_hw: bad device type: %d", fp
->fxp_type
);
753 for (i
= 0; i
<CC_BYTES_NR
; i
++)
754 printf("%d: %0x, ", i
, fp
->fxp_conf_bytes
[i
]);
759 /*===========================================================================*
761 *===========================================================================*/
762 static void fxp_init_hw(fp
)
769 port
= fp
->fxp_base_port
;
773 fp
->fxp_flags
= FF_EMPTY
;
774 fp
->fxp_flags
|= FF_ENABLED
;
776 /* Set the interrupt handler and policy. Do not automatically
777 * reenable interrupts. Return the IRQ line number on interrupts.
779 fp
->fxp_hook
= fp
->fxp_irq
;
780 r
= sys_irqsetpolicy(fp
->fxp_irq
, 0, &fp
->fxp_hook
);
782 panic("sys_irqsetpolicy failed: %d", r
);
786 r
= sys_irqenable(&fp
->fxp_hook
);
788 panic("sys_irqenable failed: %d", r
);
794 /* Set pointer to statistical counters */
795 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&fp
->fxp_stat
, sizeof(fp
->fxp_stat
),
798 panic("sys_umap failed: %d", r
);
799 fxp_cu_ptr_cmd(fp
, SC_CU_LOAD_DCA
, bus_addr
, TRUE
/* check idle */);
801 /* Ack previous interrupts */
802 isr
= fxp_inb(port
, SCB_INT_STAT
);
803 fxp_outb(port
, SCB_INT_STAT
, isr
);
805 /* Enable interrupts */
806 fxp_outb(port
, SCB_INT_MASK
, 0);
808 fxp_ru_ptr_cmd(fp
, SC_RU_START
, fp
->fxp_rx_busaddr
,
809 TRUE
/* check idle */);
814 printf("%s: Ethernet address ", fp
->fxp_name
);
815 for (i
= 0; i
< 6; i
++)
817 printf("%x%c", fp
->fxp_address
.ea_addr
[i
],
823 /*===========================================================================*
825 *===========================================================================*/
826 static void fxp_init_buf(fp
)
829 size_t rx_totbufsize
, tx_totbufsize
, tot_bufsize
, alloc_bufsize
;
837 fp
->fxp_rx_nbuf
= N_RX_BUF
;
838 rx_totbufsize
= fp
->fxp_rx_nbuf
* sizeof(struct rfd
);
839 fp
->fxp_rx_bufsize
= rx_totbufsize
;
841 fp
->fxp_tx_nbuf
= N_TX_BUF
;
842 tx_totbufsize
= fp
->fxp_tx_nbuf
* sizeof(struct tx
);
843 fp
->fxp_tx_bufsize
= tx_totbufsize
;
845 tot_bufsize
= sizeof(*tmpbufp
) + tx_totbufsize
+ rx_totbufsize
;
846 if (tot_bufsize
% 4096)
847 tot_bufsize
+= 4096 - (tot_bufsize
% 4096);
848 alloc_bufsize
= tot_bufsize
;
849 alloc_buf
= alloc_contig(alloc_bufsize
, AC_ALIGN4K
, &ph
);
850 if (alloc_buf
== NULL
) {
851 panic("fxp_init_buf: unable to alloc_contig size: %d", alloc_bufsize
);
854 buf
= (phys_bytes
)alloc_buf
;
856 tell_dev((vir_bytes
)buf
, tot_bufsize
, 0, 0, 0);
858 tmpbufp
= (union tmpbuf
*)buf
;
860 fp
->fxp_rx_buf
= (struct rfd
*)&tmpbufp
[1];
861 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)fp
->fxp_rx_buf
, rx_totbufsize
,
862 &fp
->fxp_rx_busaddr
);
864 panic("sys_umap failed: %d", r
);
867 printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n",
868 fp
->fxp_rx_busaddr
, fp
->fxp_rx_buf
);
871 for (i
= 0, rfdp
= fp
->fxp_rx_buf
; i
<fp
->fxp_rx_nbuf
; i
++, rfdp
++)
874 rfdp
->rfd_command
= 0;
875 if (i
!= fp
->fxp_rx_nbuf
-1)
877 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&rfdp
[1],
878 sizeof(rfdp
[1]), &rfdp
->rfd_linkaddr
);
880 panic("sys_umap failed: %d", r
);
884 rfdp
->rfd_linkaddr
= fp
->fxp_rx_busaddr
;
885 rfdp
->rfd_command
|= RFDC_EL
;
887 rfdp
->rfd_reserved
= 0;
889 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
894 fp
->fxp_tx_buf
= (struct tx
*)((char *)fp
->fxp_rx_buf
+rx_totbufsize
);
895 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)fp
->fxp_tx_buf
,
896 (phys_bytes
)tx_totbufsize
, &fp
->fxp_tx_busaddr
);
898 panic("sys_umap failed: %d", r
);
900 for (i
= 0, txp
= fp
->fxp_tx_buf
; i
<fp
->fxp_tx_nbuf
; i
++, txp
++)
903 txp
->tx_command
= TXC_EL
| CBL_NOP
; /* Just in case */
904 if (i
!= fp
->fxp_tx_nbuf
-1)
906 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&txp
[1],
907 (phys_bytes
)sizeof(txp
[1]),
910 panic("sys_umap failed: %d", r
);
914 txp
->tx_linkaddr
= fp
->fxp_tx_busaddr
;
916 txp
->tx_tbda
= TX_TBDA_NIL
;
918 txp
->tx_tthresh
= fp
->fxp_tx_threshold
;
924 /*===========================================================================*
926 *===========================================================================*/
927 static void fxp_reset_hw(fp
)
930 /* Inline the function in init? */
933 port
= fp
->fxp_base_port
;
936 fxp_outl(port
, CSR_PORT
, CP_CMD_SOFT_RESET
);
937 tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY
));
939 /* Disable interrupts */
940 fxp_outb(port
, SCB_INT_MASK
, SIM_M
);
942 /* Set CU base to zero */
943 fxp_cu_ptr_cmd(fp
, SC_CU_LOAD_BASE
, 0, TRUE
/* check idle */);
945 /* Set RU base to zero */
946 fxp_ru_ptr_cmd(fp
, SC_RU_LOAD_BASE
, 0, TRUE
/* check idle */);
949 /*===========================================================================*
951 *===========================================================================*/
952 static void fxp_confaddr(fxp_t
*fp
)
954 static char eakey
[]= FXP_ENVVAR
"#_EA";
955 static char eafmt
[]= "x:x:x:x:x:x";
961 /* User defined ethernet address? */
962 eakey
[sizeof(FXP_ENVVAR
)-1]= '0' + fxp_instance
;
964 for (i
= 0; i
< 6; i
++)
966 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
968 fp
->fxp_address
.ea_addr
[i
]= v
;
971 if (i
!= 0 && i
!= 6) env_panic(eakey
); /* It's all or nothing */
975 /* Get ethernet address from EEPROM */
978 v
= eeprom_read(fp
, i
);
979 fp
->fxp_address
.ea_addr
[i
*2]= (v
& 0xff);
980 fp
->fxp_address
.ea_addr
[i
*2+1]= ((v
>> 8) & 0xff);
984 /* Tell NIC about ethernet address */
985 tmpbufp
->ias
.ias_status
= 0;
986 tmpbufp
->ias
.ias_command
= CBL_C_EL
| CBL_AIS
;
987 tmpbufp
->ias
.ias_linkaddr
= 0;
988 memcpy(tmpbufp
->ias
.ias_ethaddr
, fp
->fxp_address
.ea_addr
,
989 sizeof(tmpbufp
->ias
.ias_ethaddr
));
990 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&tmpbufp
->ias
,
991 (phys_bytes
)sizeof(tmpbufp
->ias
), &bus_addr
);
993 panic("sys_umap failed: %d", r
);
995 fxp_cu_ptr_cmd(fp
, SC_CU_START
, bus_addr
, TRUE
/* check idle */);
999 /* Wait for CU command to complete */
1000 if (tmpbufp
->ias
.ias_status
& CBL_F_C
)
1002 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(1000));
1004 if (!(tmpbufp
->ias
.ias_status
& CBL_F_C
))
1005 panic("fxp_confaddr: CU command failed to complete");
1006 if (!(tmpbufp
->ias
.ias_status
& CBL_F_OK
))
1007 panic("fxp_confaddr: CU command failed");
1010 printf("%s: hardware ethernet address: ", fp
->fxp_name
);
1011 for (i
= 0; i
<6; i
++)
1013 printf("%02x%s", fp
->fxp_address
.ea_addr
[i
],
1020 /*===========================================================================*
1022 *===========================================================================*/
1023 static void fxp_rec_mode(fp
)
1026 fp
->fxp_conf_bytes
[0]= CC_BYTES_NR
; /* Just to be sure */
1027 fp
->fxp_conf_bytes
[15] &= ~(CCB15_BD
|CCB15_PM
);
1028 fp
->fxp_conf_bytes
[21] &= ~CCB21_MA
;
1030 if (fp
->fxp_flags
& FF_PROMISC
)
1031 fp
->fxp_conf_bytes
[15] |= CCB15_PM
;
1032 if (fp
->fxp_flags
& FF_MULTI
)
1033 fp
->fxp_conf_bytes
[21] |= CCB21_MA
;
1035 if (!(fp
->fxp_flags
& (FF_BROAD
|FF_MULTI
|FF_PROMISC
)))
1036 fp
->fxp_conf_bytes
[15] |= CCB15_BD
;
1038 /* Queue request if not idle */
1039 if (fp
->fxp_tx_idle
)
1045 printf("fxp_rec_mode: setting fxp_need_conf\n");
1046 fp
->fxp_need_conf
= TRUE
;
1050 /*===========================================================================*
1052 *===========================================================================*/
1053 static void fxp_writev_s(const message
*mp
, int from_int
)
1055 endpoint_t iov_endpt
;
1056 cp_grant_id_t iov_grant
;
1057 vir_bytes iov_offset
;
1058 int i
, j
, n
, o
, r
, s
, count
, size
, prev_head
;
1059 int fxp_tx_nbuf
, fxp_tx_head
;
1063 struct tx
*txp
, *prev_txp
;
1067 count
= mp
->DL_COUNT
;
1068 fp
->fxp_client
= mp
->m_source
;
1070 assert(fp
->fxp_mode
== FM_ENABLED
);
1071 assert(fp
->fxp_flags
& FF_ENABLED
);
1075 assert(fp
->fxp_flags
& FF_SEND_AVAIL
);
1076 fp
->fxp_flags
&= ~FF_SEND_AVAIL
;
1077 fp
->fxp_tx_alive
= TRUE
;
1080 if (fp
->fxp_tx_idle
)
1082 txp
= fp
->fxp_tx_buf
;
1083 fxp_tx_head
= 0; /* lint */
1084 prev_txp
= NULL
; /* lint */
1088 fxp_tx_nbuf
= fp
->fxp_tx_nbuf
;
1089 prev_head
= fp
->fxp_tx_head
;
1090 fxp_tx_head
= prev_head
+1;
1091 if (fxp_tx_head
== fxp_tx_nbuf
)
1093 assert(fxp_tx_head
< fxp_tx_nbuf
);
1095 if (fxp_tx_head
== fp
->fxp_tx_tail
)
1097 /* Send queue is full */
1098 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
1099 fp
->fxp_flags
|= FF_SEND_AVAIL
;
1103 prev_txp
= &fp
->fxp_tx_buf
[prev_head
];
1104 txp
= &fp
->fxp_tx_buf
[fxp_tx_head
];
1107 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
1108 assert(!(fp
->fxp_flags
& FF_PACK_SENT
));
1110 iov_endpt
= mp
->DL_ENDPT
;
1111 iov_grant
= mp
->DL_GRANT
;
1116 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1117 iov_offset
+= IOVEC_NR
* sizeof(fp
->fxp_iovec_s
[0]))
1122 r
= sys_safecopyfrom(iov_endpt
, iov_grant
, iov_offset
,
1123 (vir_bytes
)fp
->fxp_iovec_s
,
1124 n
* sizeof(fp
->fxp_iovec_s
[0]), D
);
1126 panic("fxp_writev: sys_safecopyfrom failed: %d", r
);
1128 for (j
= 0, iovp
= fp
->fxp_iovec_s
; j
<n
; j
++, iovp
++)
1131 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
) {
1132 panic("fxp_writev: invalid packet size: %d", size
+ s
);
1135 r
= sys_safecopyfrom(iov_endpt
, iovp
->iov_grant
,
1136 0, (vir_bytes
)(txp
->tx_buf
+o
), s
, D
);
1138 panic("fxp_writev_s: sys_safecopyfrom failed: %d", r
);
1144 if (size
< ETH_MIN_PACK_SIZE
)
1145 panic("fxp_writev: invalid packet size: %d", size
);
1148 txp
->tx_command
= TXC_EL
| CBL_XMIT
;
1149 txp
->tx_tbda
= TX_TBDA_NIL
;
1150 txp
->tx_size
= TXSZ_EOF
| size
;
1151 txp
->tx_tthresh
= fp
->fxp_tx_threshold
;
1153 if (fp
->fxp_tx_idle
)
1156 fp
->fxp_tx_head
= fp
->fxp_tx_tail
= 0;
1158 fxp_cu_ptr_cmd(fp
, SC_CU_START
, fp
->fxp_tx_busaddr
,
1159 TRUE
/* check idle */);
1163 /* Link new request in transmit list */
1164 tx_command
= prev_txp
->tx_command
;
1165 assert(tx_command
== (TXC_EL
| CBL_XMIT
));
1166 prev_txp
->tx_command
= CBL_XMIT
;
1167 fp
->fxp_tx_head
= fxp_tx_head
;
1170 fp
->fxp_flags
|= FF_PACK_SENT
;
1172 /* If the interrupt handler called, don't send a reply. The reply
1173 * will be sent after all interrupts are handled.
1182 panic("fxp: should not be sending");
1184 fp
->fxp_tx_mess
= *mp
;
1188 /*===========================================================================*
1190 *===========================================================================*/
1191 static void fxp_readv_s(mp
, from_int
)
1195 int i
, j
, n
, o
, r
, s
, count
, size
, fxp_rx_head
, fxp_rx_nbuf
;
1196 endpoint_t iov_endpt
;
1197 cp_grant_id_t iov_grant
;
1200 vir_bytes iov_offset
;
1206 struct rfd
*rfdp
, *prev_rfdp
;
1210 count
= mp
->DL_COUNT
;
1211 fp
->fxp_client
= mp
->m_source
;
1213 assert(fp
->fxp_mode
== FM_ENABLED
);
1214 assert(fp
->fxp_flags
& FF_ENABLED
);
1216 port
= fp
->fxp_base_port
;
1218 fxp_rx_head
= fp
->fxp_rx_head
;
1219 rfdp
= &fp
->fxp_rx_buf
[fxp_rx_head
];
1221 rfd_status
= rfdp
->rfd_status
;
1222 if (!(rfd_status
& RFDS_C
))
1224 /* Receive buffer is empty, suspend */
1228 if (!(rfd_status
& RFDS_OK
))
1230 /* Not OK? What happened? */
1235 assert(!(rfd_status
& (RFDS_CRCERR
| RFDS_ALIGNERR
|
1236 RFDS_OUTOFBUF
| RFDS_DMAOVR
| RFDS_TOOSHORT
|
1239 rfd_res
= rfdp
->rfd_res
;
1240 assert(rfd_res
& RFDR_EOF
);
1241 assert(rfd_res
& RFDR_F
);
1243 packlen
= rfd_res
& RFDSZ_SIZE
;
1245 iov_endpt
= mp
->DL_ENDPT
;
1246 iov_grant
= mp
->DL_GRANT
;
1251 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1252 iov_offset
+= IOVEC_NR
* sizeof(fp
->fxp_iovec_s
[0]))
1257 r
= sys_safecopyfrom(iov_endpt
, iov_grant
, iov_offset
,
1258 (vir_bytes
)fp
->fxp_iovec_s
,
1259 n
* sizeof(fp
->fxp_iovec_s
[0]), D
);
1261 panic("fxp_readv_s: sys_safecopyfrom failed: %d", r
);
1263 for (j
= 0, iovp
= fp
->fxp_iovec_s
; j
<n
; j
++, iovp
++)
1266 if (size
+ s
> packlen
)
1268 assert(packlen
> size
);
1272 r
= sys_safecopyto(iov_endpt
, iovp
->iov_grant
,
1273 0, (vir_bytes
)(rfdp
->rfd_buf
+o
), s
, D
);
1276 panic("fxp_readv: sys_safecopyto failed: %d", r
);
1280 if (size
== packlen
)
1284 if (size
== packlen
)
1292 fp
->fxp_read_s
= packlen
;
1293 fp
->fxp_flags
= (fp
->fxp_flags
& ~FF_READING
) | FF_PACK_RECV
;
1295 /* Re-init the current buffer */
1296 rfdp
->rfd_status
= 0;
1297 rfdp
->rfd_command
= RFDC_EL
;
1298 rfdp
->rfd_reserved
= 0;
1300 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
1302 fxp_rx_nbuf
= fp
->fxp_rx_nbuf
;
1303 if (fxp_rx_head
== 0)
1305 prev_rfdp
= &fp
->fxp_rx_buf
[fxp_rx_nbuf
-1];
1308 prev_rfdp
= &rfdp
[-1];
1310 assert(prev_rfdp
->rfd_command
& RFDC_EL
);
1311 prev_rfdp
->rfd_command
&= ~RFDC_EL
;
1314 if (fxp_rx_head
== fxp_rx_nbuf
)
1316 assert(fxp_rx_head
< fxp_rx_nbuf
);
1317 fp
->fxp_rx_head
= fxp_rx_head
;
1325 if (fp
->fxp_rx_need_restart
)
1327 fp
->fxp_rx_need_restart
= 0;
1329 /* Check the status of the RU */
1330 scb_status
= fxp_inb(port
, SCB_STATUS
);
1331 if ((scb_status
& SS_RUS_MASK
) != SS_RU_NORES
)
1333 /* Race condition? */
1334 printf("fxp_readv: restart race: 0x%x\n",
1336 assert((scb_status
& SS_RUS_MASK
) == SS_RU_READY
);
1345 assert(fp
->fxp_flags
& FF_READING
);
1347 /* No need to store any state */
1351 fp
->fxp_rx_mess
= *mp
;
1352 assert(!(fp
->fxp_flags
& FF_READING
));
1353 fp
->fxp_flags
|= FF_READING
;
1358 /*===========================================================================*
1360 *===========================================================================*/
1361 static void fxp_do_conf(fp
)
1368 /* Configure device */
1369 tmpbufp
->cc
.cc_status
= 0;
1370 tmpbufp
->cc
.cc_command
= CBL_C_EL
| CBL_CONF
;
1371 tmpbufp
->cc
.cc_linkaddr
= 0;
1372 memcpy(tmpbufp
->cc
.cc_bytes
, fp
->fxp_conf_bytes
,
1373 sizeof(tmpbufp
->cc
.cc_bytes
));
1375 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&tmpbufp
->cc
,
1376 (phys_bytes
)sizeof(tmpbufp
->cc
), &bus_addr
);
1378 panic("sys_umap failed: %d", r
);
1380 fxp_cu_ptr_cmd(fp
, SC_CU_START
, bus_addr
, TRUE
/* check idle */);
1384 /* Wait for CU command to complete */
1385 if (tmpbufp
->cc
.cc_status
& CBL_F_C
)
1387 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(100000));
1389 if (!(tmpbufp
->cc
.cc_status
& CBL_F_C
))
1390 panic("fxp_do_conf: CU command failed to complete");
1391 if (!(tmpbufp
->cc
.cc_status
& CBL_F_OK
))
1392 panic("fxp_do_conf: CU command failed");
1396 /*===========================================================================*
1398 *===========================================================================*/
1399 static void fxp_cu_ptr_cmd(fp
, cmd
, bus_addr
, check_idle
)
1402 phys_bytes bus_addr
;
1409 port
= fp
->fxp_base_port
;
1413 /* Consistency check. Make sure that CU is idle */
1414 if ((fxp_inb(port
, SCB_STATUS
) & SS_CUS_MASK
) != SS_CU_IDLE
)
1415 panic("fxp_cu_ptr_cmd: CU is not idle");
1418 fxp_outl(port
, SCB_POINTER
, bus_addr
);
1419 fxp_outb(port
, SCB_CMD
, cmd
);
1421 /* What is a reasonable time-out? There is nothing in the
1422 * documentation. 1 ms should be enough.
1426 /* Wait for CU command to be accepted */
1427 scb_cmd
= fxp_inb(port
, SCB_CMD
);
1428 if ((scb_cmd
& SC_CUC_MASK
) == SC_CU_NOP
)
1430 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(100000));
1432 if ((scb_cmd
& SC_CUC_MASK
) != SC_CU_NOP
)
1433 panic("fxp_cu_ptr_cmd: CU does not accept command");
1436 /*===========================================================================*
1438 *===========================================================================*/
1439 static void fxp_ru_ptr_cmd(fp
, cmd
, bus_addr
, check_idle
)
1442 phys_bytes bus_addr
;
1449 port
= fp
->fxp_base_port
;
1453 /* Consistency check, make sure that RU is idle */
1454 if ((fxp_inb(port
, SCB_STATUS
) & SS_RUS_MASK
) != SS_RU_IDLE
)
1455 panic("fxp_ru_ptr_cmd: RU is not idle");
1458 fxp_outl(port
, SCB_POINTER
, bus_addr
);
1459 fxp_outb(port
, SCB_CMD
, cmd
);
1463 /* Wait for RU command to be accepted */
1464 scb_cmd
= fxp_inb(port
, SCB_CMD
);
1465 if ((scb_cmd
& SC_RUC_MASK
) == SC_RU_NOP
)
1467 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(1000));
1469 if ((scb_cmd
& SC_RUC_MASK
) != SC_RU_NOP
)
1470 panic("fxp_ru_ptr_cmd: RU does not accept command");
1473 /*===========================================================================*
1475 *===========================================================================*/
1476 static void fxp_restart_ru(fp
)
1483 port
= fp
->fxp_base_port
;
1485 fxp_rx_nbuf
= fp
->fxp_rx_nbuf
;
1486 for (i
= 0, rfdp
= fp
->fxp_rx_buf
; i
<fxp_rx_nbuf
; i
++, rfdp
++)
1488 rfdp
->rfd_status
= 0;
1489 rfdp
->rfd_command
= 0;
1490 if (i
== fp
->fxp_rx_nbuf
-1)
1491 rfdp
->rfd_command
= RFDC_EL
;
1492 rfdp
->rfd_reserved
= 0;
1494 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
1498 /* Make sure that RU is in the 'No resources' state */
1499 if ((fxp_inb(port
, SCB_STATUS
) & SS_RUS_MASK
) != SS_RU_NORES
)
1500 panic("fxp_restart_ru: RU is in an unexpected state");
1502 fxp_ru_ptr_cmd(fp
, SC_RU_START
, fp
->fxp_rx_busaddr
,
1503 FALSE
/* do not check idle */);
1506 /*===========================================================================*
1508 *===========================================================================*/
1509 static void fxp_getstat_s(message
*mp
)
1519 assert(fp
->fxp_mode
== FM_ENABLED
);
1520 assert(fp
->fxp_flags
& FF_ENABLED
);
1522 p
= &fp
->fxp_stat
.sc_tx_fcp
;
1525 /* The dump commmand doesn't take a pointer. Setting a pointer
1526 * doesn't hurt though.
1528 fxp_cu_ptr_cmd(fp
, SC_CU_DUMP_SC
, 0, FALSE
/* do not check idle */);
1532 /* Wait for CU command to complete */
1535 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(1000));
1538 panic("fxp_getstat: CU command failed to complete");
1540 panic("fxp_getstat: bad magic");
1543 fp
->fxp_stat
.sc_rx_crc
+
1544 fp
->fxp_stat
.sc_rx_align
+
1545 fp
->fxp_stat
.sc_rx_resource
+
1546 fp
->fxp_stat
.sc_rx_overrun
+
1547 fp
->fxp_stat
.sc_rx_cd
+
1548 fp
->fxp_stat
.sc_rx_short
;
1550 fp
->fxp_stat
.sc_tx_maxcol
+
1551 fp
->fxp_stat
.sc_tx_latecol
+
1552 fp
->fxp_stat
.sc_tx_crs
;
1553 stats
.ets_OVW
= fp
->fxp_stat
.sc_rx_overrun
;
1554 stats
.ets_CRCerr
= fp
->fxp_stat
.sc_rx_crc
;
1555 stats
.ets_frameAll
= fp
->fxp_stat
.sc_rx_align
;
1556 stats
.ets_missedP
= fp
->fxp_stat
.sc_rx_resource
;
1557 stats
.ets_packetR
= fp
->fxp_stat
.sc_rx_good
;
1558 stats
.ets_packetT
= fp
->fxp_stat
.sc_tx_good
;
1559 stats
.ets_transDef
= fp
->fxp_stat
.sc_tx_defered
;
1560 stats
.ets_collision
= fp
->fxp_stat
.sc_tx_totcol
;
1561 stats
.ets_transAb
= fp
->fxp_stat
.sc_tx_maxcol
;
1562 stats
.ets_carrSense
= fp
->fxp_stat
.sc_tx_crs
;
1563 stats
.ets_fifoUnder
= fp
->fxp_stat
.sc_tx_underrun
;
1564 stats
.ets_fifoOver
= fp
->fxp_stat
.sc_rx_overrun
;
1565 stats
.ets_CDheartbeat
= 0;
1566 stats
.ets_OWC
= fp
->fxp_stat
.sc_tx_latecol
;
1568 r
= sys_safecopyto(mp
->DL_ENDPT
, mp
->DL_GRANT
, 0, (vir_bytes
)&stats
,
1571 panic("fxp_getstat_s: sys_safecopyto failed: %d", r
);
1573 mp
->m_type
= DL_STAT_REPLY
;
1574 r
= send(mp
->m_source
, mp
);
1576 panic("fxp_getstat_s: send failed: %d", r
);
1579 /*===========================================================================*
1581 *===========================================================================*/
1582 static void fxp_handler(fxp_t
*fp
)
1589 port
= fp
->fxp_base_port
;
1592 isr
= fxp_inb(port
, SCB_INT_STAT
);
1593 fxp_outb(port
, SCB_INT_STAT
, isr
);
1599 if (!fp
->fxp_got_int
&& (fp
->fxp_flags
& FF_READING
))
1601 fp
->fxp_got_int
= TRUE
;
1602 interrupt(fxp_tasknr
);
1608 if (!fp
->fxp_tx_idle
)
1610 fp
->fxp_send_int
= TRUE
;
1611 if (!fp
->fxp_got_int
)
1613 fp
->fxp_got_int
= TRUE
;
1614 interrupt(fxp_tasknr
);
1622 /* Assume that receive buffer is full of packets. fxp_readv
1623 * will restart the RU.
1625 fp
->fxp_rx_need_restart
= 1;
1629 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
1634 /*===========================================================================*
1636 *===========================================================================*/
1637 static void fxp_check_ints(fxp_t
*fp
)
1639 int n
, fxp_flags
, prev_tail
;
1640 int fxp_tx_tail
, fxp_tx_nbuf
, fxp_tx_threshold
;
1647 fxp_flags
= fp
->fxp_flags
;
1649 if (fxp_flags
& FF_READING
)
1651 if (!(fp
->fxp_rx_buf
[fp
->fxp_rx_head
].rfd_status
& RFDS_C
))
1655 fxp_readv_s(&fp
->fxp_rx_mess
, TRUE
/* from int */);
1658 if (fp
->fxp_tx_idle
)
1659 ; /* Nothing to do */
1660 else if (fp
->fxp_send_int
)
1662 fp
->fxp_send_int
= FALSE
;
1663 fxp_tx_tail
= fp
->fxp_tx_tail
;
1664 fxp_tx_nbuf
= fp
->fxp_tx_nbuf
;
1668 txp
= &fp
->fxp_tx_buf
[fxp_tx_tail
];
1669 tx_status
= txp
->tx_status
;
1670 if (!(tx_status
& TXS_C
))
1675 assert(tx_status
& TXS_OK
);
1676 if (tx_status
& TXS_U
)
1678 fxp_tx_threshold
= fp
->fxp_tx_threshold
;
1679 if (fxp_tx_threshold
< TXTT_MAX
)
1682 fp
->fxp_tx_threshold
= fxp_tx_threshold
;
1685 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
1689 if (txp
->tx_command
& TXC_EL
)
1696 if (fxp_tx_tail
== fxp_tx_nbuf
)
1698 assert(fxp_tx_tail
< fxp_tx_nbuf
);
1701 if (fp
->fxp_need_conf
)
1703 /* Check the status of the CU */
1704 port
= fp
->fxp_base_port
;
1705 scb_status
= fxp_inb(port
, SCB_STATUS
);
1706 if ((scb_status
& SS_CUS_MASK
) != SS_CU_IDLE
)
1709 printf("scb_status = 0x%x\n", scb_status
);
1713 printf("fxp_check_ints: fxp_need_conf\n");
1714 fp
->fxp_need_conf
= FALSE
;
1721 if (!fp
->fxp_tx_idle
)
1723 fp
->fxp_tx_tail
= fxp_tx_tail
;
1725 /* Check the status of the CU */
1726 port
= fp
->fxp_base_port
;
1727 scb_status
= fxp_inb(port
, SCB_STATUS
);
1728 if ((scb_status
& SS_CUS_MASK
) != SS_CU_IDLE
)
1731 printf("scb_status = 0x%x\n",
1737 if (fxp_tx_tail
== 0)
1738 prev_tail
= fxp_tx_nbuf
-1;
1740 prev_tail
= fxp_tx_tail
-1;
1741 busaddr
= fp
->fxp_tx_buf
[prev_tail
].
1744 fxp_cu_ptr_cmd(fp
, SC_CU_START
,
1745 busaddr
, 1 /* check idle */);
1749 if (fp
->fxp_flags
& FF_SEND_AVAIL
)
1751 fxp_writev_s(&fp
->fxp_tx_mess
,
1752 TRUE
/* from int */);
1757 if (fp
->fxp_report_link
)
1758 fxp_report_link(fp
);
1760 if (fp
->fxp_flags
& (FF_PACK_SENT
| FF_PACK_RECV
))
1764 /*===========================================================================*
1766 *===========================================================================*/
1767 static void fxp_watchdog_f(tp
)
1772 tmr_arg(&fxp_watchdog
)->ta_int
= 0;
1773 fxp_set_timer(&fxp_watchdog
, system_hz
, fxp_watchdog_f
);
1776 if (fp
->fxp_mode
!= FM_ENABLED
)
1779 /* Handle race condition, MII interface might be busy */
1780 if(!fp
->fxp_mii_busy
)
1782 /* Check the link status. */
1783 if (fxp_link_changed(fp
))
1786 printf("fxp_watchdog_f: link changed\n");
1788 fp
->fxp_report_link
= TRUE
;
1789 fp
->fxp_got_int
= TRUE
;
1790 interrupt(fxp_tasknr
);
1794 if (!(fp
->fxp_flags
& FF_SEND_AVAIL
))
1796 /* Assume that an idle system is alive */
1797 fp
->fxp_tx_alive
= TRUE
;
1800 if (fp
->fxp_tx_alive
)
1802 fp
->fxp_tx_alive
= FALSE
;
1806 fp
->fxp_need_reset
= TRUE
;
1807 fp
->fxp_got_int
= TRUE
;
1808 interrupt(fxp_tasknr
);
1811 /*===========================================================================*
1812 * fxp_link_changed *
1813 *===========================================================================*/
1814 static int fxp_link_changed(fp
)
1819 scr
= mii_read(fp
, MII_SCR
);
1820 scr
&= ~(MII_SCR_RES
|MII_SCR_RES_1
);
1822 return (fp
->fxp_mii_scr
!= scr
);
1825 /*===========================================================================*
1827 *===========================================================================*/
1828 static void fxp_report_link(fxp_t
*fp
)
1830 u16_t mii_ctrl
, mii_status
, mii_id1
, mii_id2
,
1831 mii_ana
, mii_anlpa
, mii_ane
, mii_extstat
,
1832 mii_ms_ctrl
, mii_ms_status
, scr
;
1835 int f
, link_up
, ms_regs
;
1837 /* Assume an 82555 (compatible) PHY. The should be changed for
1838 * 82557 NICs with different PHYs
1840 ms_regs
= 0; /* No master/slave registers. */
1842 fp
->fxp_report_link
= FALSE
;
1844 scr
= mii_read(fp
, MII_SCR
);
1845 scr
&= ~(MII_SCR_RES
|MII_SCR_RES_1
);
1846 fp
->fxp_mii_scr
= scr
;
1848 mii_ctrl
= mii_read(fp
, MII_CTRL
);
1849 mii_read(fp
, MII_STATUS
); /* The status reg is latched, read twice */
1850 mii_status
= mii_read(fp
, MII_STATUS
);
1851 mii_id1
= mii_read(fp
, MII_PHYID_H
);
1852 mii_id2
= mii_read(fp
, MII_PHYID_L
);
1853 mii_ana
= mii_read(fp
, MII_ANA
);
1854 mii_anlpa
= mii_read(fp
, MII_ANLPA
);
1855 mii_ane
= mii_read(fp
, MII_ANE
);
1856 if (mii_status
& MII_STATUS_EXT_STAT
)
1857 mii_extstat
= mii_read(fp
, MII_EXT_STATUS
);
1862 mii_ms_ctrl
= mii_read(fp
, MII_MS_CTRL
);
1863 mii_ms_status
= mii_read(fp
, MII_MS_STATUS
);
1871 /* How do we know about the link status? */
1872 link_up
= !!(mii_status
& MII_STATUS_LS
);
1874 fp
->fxp_link_up
= link_up
;
1878 printf("%s: link down\n", fp
->fxp_name
);
1883 oui
= (mii_id1
<< MII_PH_OUI_H_C_SHIFT
) |
1884 ((mii_id2
& MII_PL_OUI_L_MASK
) >> MII_PL_OUI_L_SHIFT
);
1885 model
= ((mii_id2
& MII_PL_MODEL_MASK
) >> MII_PL_MODEL_SHIFT
);
1886 rev
= (mii_id2
& MII_PL_REV_MASK
);
1889 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui
, model
, rev
);
1892 if (mii_ctrl
& (MII_CTRL_LB
|MII_CTRL_PD
|MII_CTRL_ISO
))
1894 printf("%s: PHY: ", fp
->fxp_name
);
1896 if (mii_ctrl
& MII_CTRL_LB
)
1898 printf("loopback mode");
1901 if (mii_ctrl
& MII_CTRL_PD
)
1903 if (!f
) printf(", ");
1905 printf("powered down");
1907 if (mii_ctrl
& MII_CTRL_ISO
)
1909 if (!f
) printf(", ");
1916 if (!(mii_ctrl
& MII_CTRL_ANE
))
1918 printf("%s: manual config: ", fp
->fxp_name
);
1919 switch(mii_ctrl
& (MII_CTRL_SP_LSB
|MII_CTRL_SP_MSB
))
1921 case MII_CTRL_SP_10
: printf("10 Mbps"); break;
1922 case MII_CTRL_SP_100
: printf("100 Mbps"); break;
1923 case MII_CTRL_SP_1000
: printf("1000 Mbps"); break;
1924 case MII_CTRL_SP_RES
: printf("reserved speed"); break;
1926 if (mii_ctrl
& MII_CTRL_DM
)
1927 printf(", full duplex");
1929 printf(", half duplex");
1934 if (!debug
) goto resspeed
;
1936 printf("%s: ", fp
->fxp_name
);
1937 mii_print_stat_speed(mii_status
, mii_extstat
);
1940 if (!(mii_status
& MII_STATUS_ANC
))
1941 printf("%s: auto-negotiation not complete\n", fp
->fxp_name
);
1942 if (mii_status
& MII_STATUS_RF
)
1943 printf("%s: remote fault detected\n", fp
->fxp_name
);
1944 if (!(mii_status
& MII_STATUS_ANA
))
1946 printf("%s: local PHY has no auto-negotiation ability\n",
1949 if (!(mii_status
& MII_STATUS_LS
))
1950 printf("%s: link down\n", fp
->fxp_name
);
1951 if (mii_status
& MII_STATUS_JD
)
1952 printf("%s: jabber condition detected\n", fp
->fxp_name
);
1953 if (!(mii_status
& MII_STATUS_EC
))
1955 printf("%s: no extended register set\n", fp
->fxp_name
);
1958 if (!(mii_status
& MII_STATUS_ANC
))
1961 printf("%s: local cap.: ", fp
->fxp_name
);
1962 if (mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
1964 printf("1000 Mbps: T-");
1965 switch(mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
1967 case MII_MSC_1000T_FD
: printf("FD"); break;
1968 case MII_MSC_1000T_HD
: printf("HD"); break;
1969 default: printf("FD/HD"); break;
1974 mii_print_techab(mii_ana
);
1977 if (mii_ane
& MII_ANE_PDF
)
1978 printf("%s: parallel detection fault\n", fp
->fxp_name
);
1979 if (!(mii_ane
& MII_ANE_LPANA
))
1981 printf("%s: link-partner does not support auto-negotiation\n",
1986 printf("%s: remote cap.: ", fp
->fxp_name
);
1987 if (mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
1988 if (mii_ms_status
& (MII_MSS_LP1000T_FD
| MII_MSS_LP1000T_HD
))
1990 printf("1000 Mbps: T-");
1991 switch(mii_ms_status
&
1992 (MII_MSS_LP1000T_FD
| MII_MSS_LP1000T_HD
))
1994 case MII_MSS_LP1000T_FD
: printf("FD"); break;
1995 case MII_MSS_LP1000T_HD
: printf("HD"); break;
1996 default: printf("FD/HD"); break;
2001 mii_print_techab(mii_anlpa
);
2006 printf("%s: ", fp
->fxp_name
);
2007 if (mii_ms_ctrl
& MII_MSC_MS_MANUAL
)
2010 (mii_ms_ctrl
& MII_MSC_MS_VAL
) ?
2011 "MASTER" : "SLAVE");
2016 (mii_ms_ctrl
& MII_MSC_MULTIPORT
) ?
2017 "multiport" : "single-port");
2019 if (mii_ms_ctrl
& MII_MSC_RES
)
2020 printf(" reserved<0x%x>", mii_ms_ctrl
& MII_MSC_RES
);
2022 if (mii_ms_status
& MII_MSS_FAULT
)
2023 printf("M/S config fault");
2024 else if (mii_ms_status
& MII_MSS_MASTER
)
2031 if (mii_ms_status
& (MII_MSS_LP1000T_FD
|MII_MSS_LP1000T_HD
))
2033 if (!(mii_ms_status
& MII_MSS_LOCREC
))
2035 printf("%s: local receiver not OK\n",
2038 if (!(mii_ms_status
& MII_MSS_REMREC
))
2040 printf("%s: remote receiver not OK\n",
2044 if (mii_ms_status
& (MII_MSS_RES
|MII_MSS_IDLE_ERR
))
2046 printf("%s", fp
->fxp_name
);
2047 if (mii_ms_status
& MII_MSS_RES
)
2048 printf(" reserved<0x%x>", mii_ms_status
& MII_MSS_RES
);
2049 if (mii_ms_status
& MII_MSS_IDLE_ERR
)
2051 printf(" idle error %d",
2052 mii_ms_status
& MII_MSS_IDLE_ERR
);
2059 printf("%s: link up, %d Mbps, %s duplex\n",
2060 fp
->fxp_name
, (scr
& MII_SCR_100
) ? 100 : 10,
2061 (scr
& MII_SCR_FD
) ? "full" : "half");
2066 /*===========================================================================*
2068 *===========================================================================*/
2069 static void reply(fp
)
2077 if (fp
->fxp_flags
& FF_PACK_SENT
)
2078 flags
|= DL_PACK_SEND
;
2079 if (fp
->fxp_flags
& FF_PACK_RECV
)
2080 flags
|= DL_PACK_RECV
;
2082 reply
.m_type
= DL_TASK_REPLY
;
2083 reply
.DL_FLAGS
= flags
;
2084 reply
.DL_COUNT
= fp
->fxp_read_s
;
2086 r
= send(fp
->fxp_client
, &reply
);
2089 panic("fxp: send failed: %d", r
);
2092 fp
->fxp_flags
&= ~(FF_PACK_SENT
| FF_PACK_RECV
);
2095 /*===========================================================================*
2097 *===========================================================================*/
2098 static void mess_reply(req
, reply_mess
)
2100 message
*reply_mess
;
2102 if (send(req
->m_source
, reply_mess
) != OK
)
2103 panic("fxp: unable to mess_reply");
2106 /*===========================================================================*
2108 *===========================================================================*/
2109 PRIVATE u16_t
eeprom_read(fp
, reg
)
2117 alen
= fp
->fxp_ee_addrlen
;
2120 eeprom_addrsize(fp
);
2121 alen
= fp
->fxp_ee_addrlen
;
2122 assert(alen
== 6 || alen
== 8);
2125 port
= fp
->fxp_base_port
;
2127 fxp_outb(port
, CSR_EEPROM
, CE_EECS
); /* Enable EEPROM */
2128 v
= EEPROM_READ_PREFIX
;
2129 for (i
= EEPROM_PREFIX_LEN
-1; i
>= 0; i
--)
2131 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
2132 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2133 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2134 micro_delay(EESK_PERIOD
/2+1);
2135 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2136 micro_delay(EESK_PERIOD
/2+1);
2140 for (i
= alen
-1; i
>= 0; i
--)
2142 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
2143 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2144 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2145 micro_delay(EESK_PERIOD
/2+1);
2146 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2147 micro_delay(EESK_PERIOD
/2+1);
2151 for (i
= 0; i
<16; i
++)
2153 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| CE_EESK
); /* Clock */
2154 micro_delay(EESK_PERIOD
/2+1);
2155 b
= !!(fxp_inb(port
, CSR_EEPROM
) & CE_EEDO
);
2157 fxp_outb(port
, CSR_EEPROM
, CE_EECS
);
2158 micro_delay(EESK_PERIOD
/2+1);
2160 fxp_outb(port
, CSR_EEPROM
, 0); /* Disable EEPROM */
2161 micro_delay(EECS_DELAY
);
2166 /*===========================================================================*
2168 *===========================================================================*/
2169 PRIVATE
void eeprom_addrsize(fp
)
2176 port
= fp
->fxp_base_port
;
2178 /* Try to find out the size of the EEPROM */
2179 fxp_outb(port
, CSR_EEPROM
, CE_EECS
); /* Enable EEPROM */
2180 v
= EEPROM_READ_PREFIX
;
2181 for (i
= EEPROM_PREFIX_LEN
-1; i
>= 0; i
--)
2183 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
2184 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2185 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2186 micro_delay(EESK_PERIOD
/2+1);
2187 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2188 micro_delay(EESK_PERIOD
/2+1);
2191 for (i
= 0; i
<32; i
++)
2194 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2195 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2196 micro_delay(EESK_PERIOD
/2+1);
2197 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2198 micro_delay(EESK_PERIOD
/2+1);
2199 v
= fxp_inb(port
, CSR_EEPROM
);
2204 panic("eeprom_addrsize: failed");
2205 fp
->fxp_ee_addrlen
= i
+1;
2207 /* Discard 16 data bits */
2208 for (i
= 0; i
<16; i
++)
2210 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| CE_EESK
); /* Clock */
2211 micro_delay(EESK_PERIOD
/2+1);
2212 fxp_outb(port
, CSR_EEPROM
, CE_EECS
);
2213 micro_delay(EESK_PERIOD
/2+1);
2215 fxp_outb(port
, CSR_EEPROM
, 0); /* Disable EEPROM */
2216 micro_delay(EECS_DELAY
);
2219 printf("%s EEPROM address length: %d\n",
2220 fp
->fxp_name
, fp
->fxp_ee_addrlen
);
2224 /*===========================================================================*
2226 *===========================================================================*/
2227 PRIVATE u16_t
mii_read(fp
, reg
)
2235 port
= fp
->fxp_base_port
;
2237 assert(!fp
->fxp_mii_busy
);
2240 if (!(fxp_inl(port
, CSR_MDI_CTL
) & CM_READY
))
2241 panic("mii_read: MDI not ready");
2242 fxp_outl(port
, CSR_MDI_CTL
, CM_READ
| (1 << CM_PHYADDR_SHIFT
) |
2243 (reg
<< CM_REG_SHIFT
));
2247 v
= fxp_inl(port
, CSR_MDI_CTL
);
2250 } while (getuptime(&t1
)==OK
&& (t1
-t0
) < micros_to_ticks(100000));
2252 if (!(v
& CM_READY
))
2253 panic("mii_read: MDI not ready after command");
2256 assert(!fp
->fxp_mii_busy
);
2258 return v
& CM_DATA_MASK
;
2261 /*===========================================================================*
2263 *===========================================================================*/
2264 PRIVATE
void fxp_set_timer(tp
, delta
, watchdog
)
2265 timer_t
*tp
; /* timer to be set */
2266 clock_t delta
; /* in how many ticks */
2267 tmr_func_t watchdog
; /* watchdog function to be called */
2269 clock_t now
; /* current time */
2272 /* Get the current time. */
2275 panic("unable to get uptime from clock: %d", r
);
2277 /* Add the timer to the local timer queue. */
2278 tmrs_settimer(&fxp_timers
, tp
, now
+ delta
, watchdog
, NULL
);
2280 /* Possibly reschedule an alarm call. This happens when a new timer
2281 * is added in front.
2283 if (fxp_next_timeout
== 0 ||
2284 fxp_timers
->tmr_exp_time
< fxp_next_timeout
)
2286 fxp_next_timeout
= fxp_timers
->tmr_exp_time
;
2288 printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
2289 fxp_next_timeout
, fxp_next_timeout
-now
);
2291 r
= sys_setalarm(fxp_next_timeout
, 1);
2293 panic("unable to set synchronous alarm: %d", r
);
2297 /*===========================================================================*
2299 *===========================================================================*/
2300 PRIVATE
void fxp_expire_timers()
2302 /* A synchronous alarm message was received. Check if there are any expired
2303 * timers. Possibly reschedule the next alarm.
2305 clock_t now
; /* current time */
2308 /* Get the current time to compare the timers against. */
2311 panic("Unable to get uptime from clock: %d", r
);
2313 /* Scan the timers queue for expired timers. Dispatch the watchdog function
2314 * for each expired timers. Possibly a new alarm call must be scheduled.
2316 tmrs_exptimers(&fxp_timers
, now
, NULL
);
2317 if (fxp_timers
== NULL
)
2318 fxp_next_timeout
= TMR_NEVER
;
2320 { /* set new alarm */
2321 fxp_next_timeout
= fxp_timers
->tmr_exp_time
;
2322 r
= sys_setalarm(fxp_next_timeout
, 1);
2324 panic("Unable to set synchronous alarm: %d", r
);
2328 static u8_t
do_inb(port_t port
)
2333 r
= sys_inb(port
, &value
);
2335 panic("sys_inb failed: %d", r
);
2339 static u32_t
do_inl(port_t port
)
2344 r
= sys_inl(port
, &value
);
2346 panic("sys_inl failed: %d", r
);
2350 static void do_outb(port_t port
, u8_t value
)
2354 r
= sys_outb(port
, value
);
2356 panic("sys_outb failed: %d", r
);
2359 static void do_outl(port_t port
, u32_t value
)
2363 r
= sys_outl(port
, value
);
2365 panic("sys_outl failed: %d", r
);
2368 PRIVATE
void tell_dev(buf
, size
, pci_bus
, pci_dev
, pci_func
)
2379 r
= ds_retrieve_label_endpt("amddev", &dev_e
);
2384 "fxp`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n",
2390 m
.m_type
= IOMMU_MAP
;
2397 r
= sendrec(dev_e
, &m
);
2400 printf("fxp`tell_dev: sendrec to %d failed: %d\n",
2406 printf("fxp`tell_dev: dma map request failed: %d\n",
2413 * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $