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>
24 #define RAND_UPDATE /**/
25 #define printW() ((void)0)
31 /* Number of receive buffers */
34 /* Number of transmit buffers */
37 /* I/O vectors are handled IOVEC_NR entries at a time. */
41 #define FXP_ENVVAR "FXPETH"
43 typedef int irq_hook_t
;
45 /* ignore interrupt for the moment */
46 #define interrupt(x) do { } while(0)
63 int fxp_features
; /* Needed? */
65 int fxp_type
; /* What kind of hardware */
66 int fxp_ms_regs
; /* Master/slave registers */
67 int fxp_ee_addrlen
; /* #EEPROM address bits */
75 struct rfd
*fxp_rx_buf
;
76 phys_bytes fxp_rx_busaddr
;
78 int fxp_rx_need_restart
;
79 int fxp_need_conf
; /* Re-configure after draining send
86 struct tx
*fxp_tx_buf
;
87 phys_bytes fxp_tx_busaddr
;
100 int fxp_seen
; /* TRUE iff device available */
104 ether_addr_t fxp_address
;
108 u8_t fxp_conf_bytes
[CC_BYTES_NR
];
109 char fxp_name
[sizeof("fxp#n")];
110 iovec_t fxp_iovec
[IOVEC_NR
];
111 iovec_s_t fxp_iovec_s
[IOVEC_NR
];
116 #define FM_DISABLED 0x0
117 #define FM_ENABLED 0x1
120 #define FF_EMPTY 0x000
121 #define FF_PACK_SENT 0x001
122 #define FF_PACK_RECV 0x002
123 #define FF_SEND_AVAIL 0x004
124 #define FF_READING 0x010
125 #define FF_PROMISC 0x040
126 #define FF_MULTI 0x080
127 #define FF_BROAD 0x100
128 #define FF_ENABLED 0x200
134 #define FT_UNKNOWN 0x0
136 #define FT_82558A 0x2
140 static int fxp_instance
;
142 static fxp_t
*fxp_state
;
144 static timer_t fxp_watchdog
;
146 static u32_t system_hz
;
148 #define fxp_inb(port, offset) (do_inb((port) + (offset)))
149 #define fxp_inl(port, offset) (do_inl((port) + (offset)))
150 #define fxp_outb(port, offset, value) (do_outb((port) + (offset), (value)))
151 #define fxp_outl(port, offset, value) (do_outl((port) + (offset), (value)))
153 static void fxp_init(message
*mp
);
154 static void fxp_pci_conf(void);
155 static int fxp_probe(fxp_t
*fp
, int skip
);
156 static void fxp_conf_hw(fxp_t
*fp
);
157 static void fxp_init_hw(fxp_t
*fp
);
158 static void fxp_init_buf(fxp_t
*fp
);
159 static void fxp_reset_hw(fxp_t
*fp
);
160 static void fxp_confaddr(fxp_t
*fp
);
161 static void fxp_rec_mode(fxp_t
*fp
);
162 static void fxp_writev_s(const message
*mp
, int from_int
);
163 static void fxp_readv_s(message
*mp
, int from_int
);
164 static void fxp_do_conf(fxp_t
*fp
);
165 static void fxp_cu_ptr_cmd(fxp_t
*fp
, int cmd
, phys_bytes bus_addr
, int
167 static void fxp_ru_ptr_cmd(fxp_t
*fp
, int cmd
, phys_bytes bus_addr
, int
169 static void fxp_restart_ru(fxp_t
*fp
);
170 static void fxp_getstat_s(message
*mp
);
171 static void fxp_handler(fxp_t
*fp
);
172 static void fxp_check_ints(fxp_t
*fp
);
173 static void fxp_watchdog_f(timer_t
*tp
);
174 static int fxp_link_changed(fxp_t
*fp
);
175 static void fxp_report_link(fxp_t
*fp
);
176 static void reply(fxp_t
*fp
);
177 static void mess_reply(message
*req
, message
*reply
);
178 static u16_t
eeprom_read(fxp_t
*fp
, int reg
);
179 static void eeprom_addrsize(fxp_t
*fp
);
180 static u16_t
mii_read(fxp_t
*fp
, int reg
);
181 static u8_t
do_inb(port_t port
);
182 static u32_t
do_inl(port_t port
);
183 static void do_outb(port_t port
, u8_t v
);
184 static void do_outl(port_t port
, u32_t v
);
185 static void tell_dev(vir_bytes start
, size_t size
, int pci_bus
, int
186 pci_dev
, int pci_func
);
188 static void handle_hw_intr(void)
195 if (fp
->fxp_mode
!= FM_ENABLED
)
199 r
= sys_irqenable(&fp
->fxp_hook
);
201 panic("unable enable interrupts: %d", r
);
204 if (!fp
->fxp_got_int
)
207 assert(fp
->fxp_flags
& FF_ENABLED
);
211 /* SEF functions and variables. */
212 static void sef_local_startup(void);
213 static int sef_cb_init_fresh(int type
, sef_init_info_t
*info
);
214 static void sef_cb_signal_handler(int signo
);
216 /*===========================================================================*
218 *===========================================================================*/
219 int main(int argc
, char *argv
[])
225 /* SEF local startup. */
226 env_setargs(argc
, argv
);
231 if ((r
= netdriver_receive(ANY
, &m
, &ipc_status
)) != OK
)
232 panic("netdriver_receive failed: %d", r
);
234 if (is_ipc_notify(ipc_status
)) {
235 switch (_ENDPOINT_P(m
.m_source
)) {
240 expire_timers(m
.NOTIFY_TIMESTAMP
);
243 panic(" illegal notify from: %d", m
.m_source
);
246 /* get new message */
252 case DL_WRITEV_S
: fxp_writev_s(&m
, FALSE
); break;
253 case DL_READV_S
: fxp_readv_s(&m
, FALSE
); break;
254 case DL_CONF
: fxp_init(&m
); break;
255 case DL_GETSTAT_S
: fxp_getstat_s(&m
); break;
257 panic(" illegal message: %d", m
.m_type
);
262 /*===========================================================================*
263 * sef_local_startup *
264 *===========================================================================*/
265 static void sef_local_startup()
267 /* Register init callbacks. */
268 sef_setcb_init_fresh(sef_cb_init_fresh
);
269 sef_setcb_init_lu(sef_cb_init_fresh
);
270 sef_setcb_init_restart(sef_cb_init_fresh
);
272 /* Register live update callbacks. */
273 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready
);
274 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree
);
276 /* Register signal callbacks. */
277 sef_setcb_signal_handler(sef_cb_signal_handler
);
279 /* Let SEF perform startup. */
283 /*===========================================================================*
284 * sef_cb_init_fresh *
285 *===========================================================================*/
286 static int sef_cb_init_fresh(int UNUSED(type
), sef_init_info_t
*UNUSED(info
))
288 /* Initialize the fxp driver. */
293 system_hz
= sys_hz();
296 (void) env_parse("instance", "d", 0, &v
, 0, 255);
297 fxp_instance
= (int) v
;
299 ft
= sizeof(*fxp_state
);
301 if(!(fxp_state
= alloc_contig(ft
, 0, NULL
)))
302 panic("couldn't allocate table: %d", ENOMEM
);
304 memset(fxp_state
, 0, ft
);
306 if((r
=tsc_calibrate()) != OK
)
307 panic("tsc_calibrate failed: %d", r
);
309 /* Announce we are up! */
310 netdriver_announce();
315 /*===========================================================================*
316 * sef_cb_signal_handler *
317 *===========================================================================*/
318 static void sef_cb_signal_handler(int signo
)
323 /* Only check for termination signal, ignore anything else. */
324 if (signo
!= SIGTERM
) return;
328 if (fp
->fxp_mode
== FM_ENABLED
&& (fp
->fxp_flags
& FF_ENABLED
)) {
329 port
= fp
->fxp_base_port
;
333 printf("%s: resetting device\n", fp
->fxp_name
);
334 fxp_outl(port
, CSR_PORT
, CP_CMD_SOFT_RESET
);
340 /*===========================================================================*
342 *===========================================================================*/
343 static void fxp_init(mp
)
346 static int first_time
= 1;
354 fxp_pci_conf(); /* Configure PCI devices. */
356 init_timer(&fxp_watchdog
);
357 set_timer(&fxp_watchdog
, system_hz
, fxp_watchdog_f
, 0);
361 if (fp
->fxp_mode
== FM_DISABLED
)
363 /* This is the default, try to (re)locate the device. */
365 if (fp
->fxp_mode
== FM_DISABLED
)
367 /* Probe failed, or the device is configured off. */
368 reply_mess
.m_type
= DL_CONF_REPLY
;
369 reply_mess
.DL_STAT
= ENXIO
;
370 mess_reply(mp
, &reply_mess
);
373 if (fp
->fxp_mode
== FM_ENABLED
)
378 assert(fp
->fxp_mode
== FM_ENABLED
);
379 assert(fp
->fxp_flags
& FF_ENABLED
);
381 fp
->fxp_flags
&= ~(FF_PROMISC
| FF_MULTI
| FF_BROAD
);
383 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
384 fp
->fxp_flags
|= FF_PROMISC
;
385 if (mp
->DL_MODE
& DL_MULTI_REQ
)
386 fp
->fxp_flags
|= FF_MULTI
;
387 if (mp
->DL_MODE
& DL_BROAD_REQ
)
388 fp
->fxp_flags
|= FF_BROAD
;
392 reply_mess
.m_type
= DL_CONF_REPLY
;
393 reply_mess
.DL_STAT
= OK
;
394 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= fp
->fxp_address
;
396 mess_reply(mp
, &reply_mess
);
399 /*===========================================================================*
401 *===========================================================================*/
402 static void fxp_pci_conf()
408 strlcpy(fp
->fxp_name
, "fxp#0", sizeof(fp
->fxp_name
));
409 fp
->fxp_name
[4] += fxp_instance
;
411 fp
->fxp_features
= FFE_NONE
;
415 if (fxp_probe(fp
, fxp_instance
))
419 /*===========================================================================*
421 *===========================================================================*/
422 static int fxp_probe(fxp_t
*fp
, int skip
)
433 r
= pci_first_dev(&devind
, &vid
, &did
);
439 r
= pci_next_dev(&devind
, &vid
, &did
);
445 dname
= pci_dev_name(vid
, did
);
447 dname
= "unknown device";
448 printf("%s: %s (%04x/%04x) at %s\n",
449 fp
->fxp_name
, dname
, vid
, did
, pci_slot_name(devind
));
453 bar
= pci_attr_r32(devind
, PCI_BAR_2
) & 0xffffffe0;
455 panic("fxp_probe: base address is not properly configured");
457 fp
->fxp_base_port
= bar
;
459 ilr
= pci_attr_r8(devind
, PCI_ILR
);
463 printf("%s: using I/O address 0x%lx, IRQ %d\n",
464 fp
->fxp_name
, (unsigned long)bar
, ilr
);
467 rev
= pci_attr_r8(devind
, PCI_REV
);
469 fp
->fxp_type
= FT_UNKNOWN
;
472 case FXP_REV_82557A
: str
= "82557A"; /* 0x01 */
473 fp
->fxp_type
= FT_82557
;
475 case FXP_REV_82557B
: str
= "82557B"; break; /* 0x02 */
476 case FXP_REV_82557C
: str
= "82557C"; break; /* 0x03 */
477 case FXP_REV_82558A
: str
= "82558A"; /* 0x04 */
478 fp
->fxp_type
= FT_82558A
;
480 case FXP_REV_82558B
: str
= "82558B"; /* 0x05 */
481 fp
->fxp_type
= FT_82559
;
483 case FXP_REV_82559A
: str
= "82559A"; break; /* 0x06 */
484 case FXP_REV_82559B
: str
= "82559B"; break; /* 0x07 */
485 case FXP_REV_82559C
: str
= "82559C"; /* 0x08 */
486 fp
->fxp_type
= FT_82559
;
488 case FXP_REV_82559ERA
: str
= "82559ER-A"; /* 0x09 */
489 fp
->fxp_type
= FT_82559
;
491 case FXP_REV_82550_1
: str
= "82550(1)"; /* 0x0C */
492 fp
->fxp_type
= FT_82559
;
494 case FXP_REV_82550_2
: str
= "82550(2)"; /* 0x0D */
495 fp
->fxp_type
= FT_82559
;
497 case FXP_REV_82550_3
: str
= "82550(3)"; /* 0x0E */
498 fp
->fxp_type
= FT_82559
;
500 case FXP_REV_82551_1
: str
= "82551(1)"; /* 0x0F */
501 fp
->fxp_type
= FT_82559
;
503 case FXP_REV_82551_2
: str
= "82551(2)"; /* 0x10 */
504 fp
->fxp_type
= FT_82559
;
506 case FXP_REV_82801CAM
: str
= "82801CAM"; /* 0x42 */
507 fp
->fxp_type
= FT_82801
;
509 case FXP_REV_82801DB
: str
= "82801DB"; /* 0x81 */
510 fp
->fxp_type
= FT_82801
;
516 printf("%s: device revision: %s\n", fp
->fxp_name
, str
);
518 printf("%s: unknown revision: 0x%x\n", fp
->fxp_name
, rev
);
521 if (fp
->fxp_type
== FT_UNKNOWN
)
523 printf("fxp_probe: device is not supported by this driver\n");
530 /*===========================================================================*
532 *===========================================================================*/
533 static void fxp_conf_hw(fxp_t
*fp
)
539 fp
->fxp_mode
= FM_DISABLED
; /* Superfluous */
544 /* PCI device is present */
545 fp
->fxp_mode
= FM_ENABLED
;
547 fp
->fxp_flags
= FF_EMPTY
;
550 fp
->fxp_ee_addrlen
= 0; /* Unknown */
551 fp
->fxp_need_reset
= 0;
552 fp
->fxp_report_link
= 0;
553 fp
->fxp_link_up
= -1; /* Unknown */
556 fp
->fxp_rx_need_restart
= 0;
557 fp
->fxp_need_conf
= 0;
561 fp
->fxp_tx_threshold
= TXTT_MIN
;
563 /* Try to come up with a sensible configuration for the current
564 * device. Unfortunately every device is different, defaults are
565 * not always zero, and some fields are re-used with a completely
566 * different interpretation. We start out with a sensible default
567 * for all devices and then add device specific changes.
569 fp
->fxp_conf_bytes
[0]= CC_BYTES_NR
;
570 fp
->fxp_conf_bytes
[1]= CTL_DEFAULT
| CRL_DEFAULT
;
571 fp
->fxp_conf_bytes
[2]= CAI_DEFAULT
;
572 fp
->fxp_conf_bytes
[3]= 0;
573 fp
->fxp_conf_bytes
[4]= 0;
574 fp
->fxp_conf_bytes
[5]= 0;
575 fp
->fxp_conf_bytes
[6]= CCB6_ESC
| CCB6_ETCB
| CCB6_RES
;
576 fp
->fxp_conf_bytes
[7]= CUR_1
;
577 fp
->fxp_conf_bytes
[8]= CCB8_503_MII
;
578 fp
->fxp_conf_bytes
[9]= 0;
579 fp
->fxp_conf_bytes
[10]= CLB_NORMAL
| CPAL_DEFAULT
| CCB10_NSAI
|
581 fp
->fxp_conf_bytes
[11]= 0;
582 fp
->fxp_conf_bytes
[12]= CIS_DEFAULT
;
583 fp
->fxp_conf_bytes
[13]= CCB13_DEFAULT
;
584 fp
->fxp_conf_bytes
[14]= CCB14_DEFAULT
;
585 fp
->fxp_conf_bytes
[15]= CCB15_RES1
| CCB15_RES2
;
586 fp
->fxp_conf_bytes
[16]= CCB16_DEFAULT
;
587 fp
->fxp_conf_bytes
[17]= CCB17_DEFAULT
;
588 fp
->fxp_conf_bytes
[18]= CCB18_RES1
| CCB18_PFCT
| CCB18_PE
;
589 fp
->fxp_conf_bytes
[19]= CCB19_FDPE
;
590 fp
->fxp_conf_bytes
[20]= CCB20_PFCL
| CCB20_RES1
;
591 fp
->fxp_conf_bytes
[21]= CCB21_RES21
;
594 for (i
= 0; i
<CC_BYTES_NR
; i
++)
595 printf("%d: %0x, ", i
, fp
->fxp_conf_bytes
[i
]);
606 fp
->fxp_conf_bytes
[18] |= CCB18_LROK
;
608 if (fp
->fxp_type
== FT_82801
)
610 fp
->fxp_conf_bytes
[6] = 0xba; /* ctrl 1 */
611 fp
->fxp_conf_bytes
[15] = 0x48; /* promiscuous */
612 fp
->fxp_conf_bytes
[21] = 0x05; /* mc_all */
616 panic("fxp_conf_hw: bad device type: %d", fp
->fxp_type
);
619 /* Assume an 82555 (compatible) PHY. The should be changed for
620 * 82557 NICs with different PHYs
622 fp
->fxp_ms_regs
= 0; /* No master/slave registers. */
625 for (i
= 0; i
<CC_BYTES_NR
; i
++)
626 printf("%d: %0x, ", i
, fp
->fxp_conf_bytes
[i
]);
631 /*===========================================================================*
633 *===========================================================================*/
634 static void fxp_init_hw(fp
)
641 port
= fp
->fxp_base_port
;
645 fp
->fxp_flags
= FF_EMPTY
;
646 fp
->fxp_flags
|= FF_ENABLED
;
648 /* Set the interrupt handler and policy. Do not automatically
649 * reenable interrupts. Return the IRQ line number on interrupts.
651 fp
->fxp_hook
= fp
->fxp_irq
;
652 r
= sys_irqsetpolicy(fp
->fxp_irq
, 0, &fp
->fxp_hook
);
654 panic("sys_irqsetpolicy failed: %d", r
);
658 r
= sys_irqenable(&fp
->fxp_hook
);
660 panic("sys_irqenable failed: %d", r
);
666 /* Set pointer to statistical counters */
667 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&fp
->fxp_stat
, sizeof(fp
->fxp_stat
),
670 panic("sys_umap failed: %d", r
);
671 fxp_cu_ptr_cmd(fp
, SC_CU_LOAD_DCA
, bus_addr
, TRUE
/* check idle */);
673 /* Ack previous interrupts */
674 isr
= fxp_inb(port
, SCB_INT_STAT
);
675 fxp_outb(port
, SCB_INT_STAT
, isr
);
677 /* Enable interrupts */
678 fxp_outb(port
, SCB_INT_MASK
, 0);
680 fxp_ru_ptr_cmd(fp
, SC_RU_START
, fp
->fxp_rx_busaddr
,
681 TRUE
/* check idle */);
686 printf("%s: Ethernet address ", fp
->fxp_name
);
687 for (i
= 0; i
< 6; i
++)
689 printf("%x%c", fp
->fxp_address
.ea_addr
[i
],
695 /*===========================================================================*
697 *===========================================================================*/
698 static void fxp_init_buf(fp
)
701 size_t rx_totbufsize
, tx_totbufsize
, tot_bufsize
, alloc_bufsize
;
703 phys_bytes buf
, bus_addr
;
709 fp
->fxp_rx_nbuf
= N_RX_BUF
;
710 rx_totbufsize
= fp
->fxp_rx_nbuf
* sizeof(struct rfd
);
711 fp
->fxp_rx_bufsize
= rx_totbufsize
;
713 fp
->fxp_tx_nbuf
= N_TX_BUF
;
714 tx_totbufsize
= fp
->fxp_tx_nbuf
* sizeof(struct tx
);
715 fp
->fxp_tx_bufsize
= tx_totbufsize
;
717 tot_bufsize
= sizeof(*tmpbufp
) + tx_totbufsize
+ rx_totbufsize
;
718 if (tot_bufsize
% 4096)
719 tot_bufsize
+= 4096 - (tot_bufsize
% 4096);
720 alloc_bufsize
= tot_bufsize
;
721 alloc_buf
= alloc_contig(alloc_bufsize
, AC_ALIGN4K
, &ph
);
722 if (alloc_buf
== NULL
) {
723 panic("fxp_init_buf: unable to alloc_contig size: %d", alloc_bufsize
);
726 buf
= (phys_bytes
)alloc_buf
;
728 tell_dev((vir_bytes
)buf
, tot_bufsize
, 0, 0, 0);
730 tmpbufp
= (union tmpbuf
*)buf
;
732 fp
->fxp_rx_buf
= (struct rfd
*)&tmpbufp
[1];
733 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)fp
->fxp_rx_buf
, rx_totbufsize
,
736 panic("sys_umap failed: %d", r
);
737 fp
->fxp_rx_busaddr
= bus_addr
;
740 printf("fxp_init_buf: got phys 0x%x for vir 0x%x\n",
741 fp
->fxp_rx_busaddr
, fp
->fxp_rx_buf
);
744 for (i
= 0, rfdp
= fp
->fxp_rx_buf
; i
<fp
->fxp_rx_nbuf
; i
++, rfdp
++)
747 rfdp
->rfd_command
= 0;
748 if (i
!= fp
->fxp_rx_nbuf
-1)
750 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&rfdp
[1],
751 sizeof(rfdp
[1]), &bus_addr
);
753 panic("sys_umap failed: %d", r
);
754 rfdp
->rfd_linkaddr
= bus_addr
;
758 rfdp
->rfd_linkaddr
= fp
->fxp_rx_busaddr
;
759 rfdp
->rfd_command
|= RFDC_EL
;
761 rfdp
->rfd_reserved
= 0;
763 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
768 fp
->fxp_tx_buf
= (struct tx
*)((char *)fp
->fxp_rx_buf
+rx_totbufsize
);
769 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)fp
->fxp_tx_buf
,
770 (phys_bytes
)tx_totbufsize
, &fp
->fxp_tx_busaddr
);
772 panic("sys_umap failed: %d", r
);
774 for (i
= 0, txp
= fp
->fxp_tx_buf
; i
<fp
->fxp_tx_nbuf
; i
++, txp
++)
777 txp
->tx_command
= TXC_EL
| CBL_NOP
; /* Just in case */
778 if (i
!= fp
->fxp_tx_nbuf
-1)
780 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&txp
[1],
781 (phys_bytes
)sizeof(txp
[1]), &bus_addr
);
783 panic("sys_umap failed: %d", r
);
784 txp
->tx_linkaddr
= bus_addr
;
788 txp
->tx_linkaddr
= fp
->fxp_tx_busaddr
;
790 txp
->tx_tbda
= TX_TBDA_NIL
;
792 txp
->tx_tthresh
= fp
->fxp_tx_threshold
;
798 /*===========================================================================*
800 *===========================================================================*/
801 static void fxp_reset_hw(fp
)
804 /* Inline the function in init? */
807 port
= fp
->fxp_base_port
;
810 fxp_outl(port
, CSR_PORT
, CP_CMD_SOFT_RESET
);
811 tickdelay(micros_to_ticks(CSR_PORT_RESET_DELAY
));
813 /* Disable interrupts */
814 fxp_outb(port
, SCB_INT_MASK
, SIM_M
);
816 /* Set CU base to zero */
817 fxp_cu_ptr_cmd(fp
, SC_CU_LOAD_BASE
, 0, TRUE
/* check idle */);
819 /* Set RU base to zero */
820 fxp_ru_ptr_cmd(fp
, SC_RU_LOAD_BASE
, 0, TRUE
/* check idle */);
823 /*===========================================================================*
825 *===========================================================================*/
826 static void fxp_confaddr(fxp_t
*fp
)
828 static char eakey
[]= FXP_ENVVAR
"#_EA";
829 static char eafmt
[]= "x:x:x:x:x:x";
834 /* User defined ethernet address? */
835 eakey
[sizeof(FXP_ENVVAR
)-1]= '0' + fxp_instance
;
837 for (i
= 0; i
< 6; i
++)
839 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
841 fp
->fxp_address
.ea_addr
[i
]= v
;
844 if (i
!= 0 && i
!= 6) env_panic(eakey
); /* It's all or nothing */
848 /* Get ethernet address from EEPROM */
851 v
= eeprom_read(fp
, i
);
852 fp
->fxp_address
.ea_addr
[i
*2]= (v
& 0xff);
853 fp
->fxp_address
.ea_addr
[i
*2+1]= ((v
>> 8) & 0xff);
857 /* Tell NIC about ethernet address */
858 tmpbufp
->ias
.ias_status
= 0;
859 tmpbufp
->ias
.ias_command
= CBL_C_EL
| CBL_AIS
;
860 tmpbufp
->ias
.ias_linkaddr
= 0;
861 memcpy(tmpbufp
->ias
.ias_ethaddr
, fp
->fxp_address
.ea_addr
,
862 sizeof(tmpbufp
->ias
.ias_ethaddr
));
863 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&tmpbufp
->ias
,
864 (phys_bytes
)sizeof(tmpbufp
->ias
), &bus_addr
);
866 panic("sys_umap failed: %d", r
);
868 fxp_cu_ptr_cmd(fp
, SC_CU_START
, bus_addr
, TRUE
/* check idle */);
870 /* Wait for CU command to complete */
871 SPIN_UNTIL(tmpbufp
->ias
.ias_status
& CBL_F_C
, 1000);
873 if (!(tmpbufp
->ias
.ias_status
& CBL_F_C
))
874 panic("fxp_confaddr: CU command failed to complete");
875 if (!(tmpbufp
->ias
.ias_status
& CBL_F_OK
))
876 panic("fxp_confaddr: CU command failed");
879 printf("%s: hardware ethernet address: ", fp
->fxp_name
);
882 printf("%02x%s", fp
->fxp_address
.ea_addr
[i
],
889 /*===========================================================================*
891 *===========================================================================*/
892 static void fxp_rec_mode(fp
)
895 fp
->fxp_conf_bytes
[0]= CC_BYTES_NR
; /* Just to be sure */
896 fp
->fxp_conf_bytes
[15] &= ~(CCB15_BD
|CCB15_PM
);
897 fp
->fxp_conf_bytes
[21] &= ~CCB21_MA
;
899 if (fp
->fxp_flags
& FF_PROMISC
)
900 fp
->fxp_conf_bytes
[15] |= CCB15_PM
;
901 if (fp
->fxp_flags
& FF_MULTI
)
902 fp
->fxp_conf_bytes
[21] |= CCB21_MA
;
904 if (!(fp
->fxp_flags
& (FF_BROAD
|FF_MULTI
|FF_PROMISC
)))
905 fp
->fxp_conf_bytes
[15] |= CCB15_BD
;
907 /* Queue request if not idle */
914 printf("fxp_rec_mode: setting fxp_need_conf\n");
915 fp
->fxp_need_conf
= TRUE
;
919 /*===========================================================================*
921 *===========================================================================*/
922 static void fxp_writev_s(const message
*mp
, int from_int
)
924 endpoint_t iov_endpt
;
925 cp_grant_id_t iov_grant
;
926 vir_bytes iov_offset
;
927 int i
, j
, n
, o
, r
, s
, count
, size
, prev_head
;
928 int fxp_tx_nbuf
, fxp_tx_head
;
932 struct tx
*txp
, *prev_txp
;
936 count
= mp
->DL_COUNT
;
937 fp
->fxp_client
= mp
->m_source
;
939 assert(fp
->fxp_mode
== FM_ENABLED
);
940 assert(fp
->fxp_flags
& FF_ENABLED
);
944 assert(fp
->fxp_flags
& FF_SEND_AVAIL
);
945 fp
->fxp_flags
&= ~FF_SEND_AVAIL
;
946 fp
->fxp_tx_alive
= TRUE
;
952 fxp_tx_head
= 0; /* lint */
953 prev_txp
= NULL
; /* lint */
957 fxp_tx_nbuf
= fp
->fxp_tx_nbuf
;
958 prev_head
= fp
->fxp_tx_head
;
959 fxp_tx_head
= prev_head
+1;
960 if (fxp_tx_head
== fxp_tx_nbuf
)
962 assert(fxp_tx_head
< fxp_tx_nbuf
);
964 if (fxp_tx_head
== fp
->fxp_tx_tail
)
966 /* Send queue is full */
967 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
968 fp
->fxp_flags
|= FF_SEND_AVAIL
;
972 prev_txp
= &fp
->fxp_tx_buf
[prev_head
];
973 txp
= &fp
->fxp_tx_buf
[fxp_tx_head
];
976 assert(!(fp
->fxp_flags
& FF_SEND_AVAIL
));
977 assert(!(fp
->fxp_flags
& FF_PACK_SENT
));
979 iov_endpt
= mp
->m_source
;
980 iov_grant
= mp
->DL_GRANT
;
985 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
986 iov_offset
+= IOVEC_NR
* sizeof(fp
->fxp_iovec_s
[0]))
991 r
= sys_safecopyfrom(iov_endpt
, iov_grant
, iov_offset
,
992 (vir_bytes
)fp
->fxp_iovec_s
,
993 n
* sizeof(fp
->fxp_iovec_s
[0]));
995 panic("fxp_writev: sys_safecopyfrom failed: %d", r
);
997 for (j
= 0, iovp
= fp
->fxp_iovec_s
; j
<n
; j
++, iovp
++)
1000 if (size
+ s
> ETH_MAX_PACK_SIZE_TAGGED
) {
1001 panic("fxp_writev: invalid packet size: %d", size
+ s
);
1004 r
= sys_safecopyfrom(iov_endpt
, iovp
->iov_grant
,
1005 0, (vir_bytes
)(txp
->tx_buf
+o
), s
);
1007 panic("fxp_writev_s: sys_safecopyfrom failed: %d", r
);
1013 if (size
< ETH_MIN_PACK_SIZE
)
1014 panic("fxp_writev: invalid packet size: %d", size
);
1017 txp
->tx_command
= TXC_EL
| CBL_XMIT
;
1018 txp
->tx_tbda
= TX_TBDA_NIL
;
1019 txp
->tx_size
= TXSZ_EOF
| size
;
1020 txp
->tx_tthresh
= fp
->fxp_tx_threshold
;
1022 if (fp
->fxp_tx_idle
)
1025 fp
->fxp_tx_head
= fp
->fxp_tx_tail
= 0;
1027 fxp_cu_ptr_cmd(fp
, SC_CU_START
, fp
->fxp_tx_busaddr
,
1028 TRUE
/* check idle */);
1032 /* Link new request in transmit list */
1033 tx_command
= prev_txp
->tx_command
;
1034 assert(tx_command
== (TXC_EL
| CBL_XMIT
));
1035 prev_txp
->tx_command
= CBL_XMIT
;
1036 fp
->fxp_tx_head
= fxp_tx_head
;
1039 fp
->fxp_flags
|= FF_PACK_SENT
;
1041 /* If the interrupt handler called, don't send a reply. The reply
1042 * will be sent after all interrupts are handled.
1051 panic("fxp: should not be sending");
1053 fp
->fxp_tx_mess
= *mp
;
1057 /*===========================================================================*
1059 *===========================================================================*/
1060 static void fxp_readv_s(mp
, from_int
)
1064 int i
, j
, n
, o
, r
, s
, count
, size
, fxp_rx_head
, fxp_rx_nbuf
;
1065 endpoint_t iov_endpt
;
1066 cp_grant_id_t iov_grant
;
1069 vir_bytes iov_offset
;
1075 struct rfd
*rfdp
, *prev_rfdp
;
1079 count
= mp
->DL_COUNT
;
1080 fp
->fxp_client
= mp
->m_source
;
1082 assert(fp
->fxp_mode
== FM_ENABLED
);
1083 assert(fp
->fxp_flags
& FF_ENABLED
);
1085 port
= fp
->fxp_base_port
;
1087 fxp_rx_head
= fp
->fxp_rx_head
;
1088 rfdp
= &fp
->fxp_rx_buf
[fxp_rx_head
];
1090 rfd_status
= rfdp
->rfd_status
;
1091 if (!(rfd_status
& RFDS_C
))
1093 /* Receive buffer is empty, suspend */
1097 if (!(rfd_status
& RFDS_OK
))
1099 /* Not OK? What happened? */
1104 assert(!(rfd_status
& (RFDS_CRCERR
| RFDS_ALIGNERR
|
1105 RFDS_OUTOFBUF
| RFDS_DMAOVR
| RFDS_TOOSHORT
|
1108 rfd_res
= rfdp
->rfd_res
;
1109 assert(rfd_res
& RFDR_EOF
);
1110 assert(rfd_res
& RFDR_F
);
1112 packlen
= rfd_res
& RFDSZ_SIZE
;
1114 iov_endpt
= mp
->m_source
;
1115 iov_grant
= mp
->DL_GRANT
;
1120 for (i
= 0; i
<count
; i
+= IOVEC_NR
,
1121 iov_offset
+= IOVEC_NR
* sizeof(fp
->fxp_iovec_s
[0]))
1126 r
= sys_safecopyfrom(iov_endpt
, iov_grant
, iov_offset
,
1127 (vir_bytes
)fp
->fxp_iovec_s
,
1128 n
* sizeof(fp
->fxp_iovec_s
[0]));
1130 panic("fxp_readv_s: sys_safecopyfrom failed: %d", r
);
1132 for (j
= 0, iovp
= fp
->fxp_iovec_s
; j
<n
; j
++, iovp
++)
1135 if (size
+ s
> packlen
)
1137 assert(packlen
> size
);
1141 r
= sys_safecopyto(iov_endpt
, iovp
->iov_grant
,
1142 0, (vir_bytes
)(rfdp
->rfd_buf
+o
), s
);
1145 panic("fxp_readv: sys_safecopyto failed: %d", r
);
1149 if (size
== packlen
)
1153 if (size
== packlen
)
1161 fp
->fxp_read_s
= packlen
;
1162 fp
->fxp_flags
= (fp
->fxp_flags
& ~FF_READING
) | FF_PACK_RECV
;
1164 /* Re-init the current buffer */
1165 rfdp
->rfd_status
= 0;
1166 rfdp
->rfd_command
= RFDC_EL
;
1167 rfdp
->rfd_reserved
= 0;
1169 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
1171 fxp_rx_nbuf
= fp
->fxp_rx_nbuf
;
1172 if (fxp_rx_head
== 0)
1174 prev_rfdp
= &fp
->fxp_rx_buf
[fxp_rx_nbuf
-1];
1177 prev_rfdp
= &rfdp
[-1];
1179 assert(prev_rfdp
->rfd_command
& RFDC_EL
);
1180 prev_rfdp
->rfd_command
&= ~RFDC_EL
;
1183 if (fxp_rx_head
== fxp_rx_nbuf
)
1185 assert(fxp_rx_head
< fxp_rx_nbuf
);
1186 fp
->fxp_rx_head
= fxp_rx_head
;
1194 if (fp
->fxp_rx_need_restart
)
1196 fp
->fxp_rx_need_restart
= 0;
1198 /* Check the status of the RU */
1199 scb_status
= fxp_inb(port
, SCB_STATUS
);
1200 if ((scb_status
& SS_RUS_MASK
) != SS_RU_NORES
)
1202 /* Race condition? */
1203 printf("fxp_readv: restart race: 0x%x\n",
1205 assert((scb_status
& SS_RUS_MASK
) == SS_RU_READY
);
1214 assert(fp
->fxp_flags
& FF_READING
);
1216 /* No need to store any state */
1220 fp
->fxp_rx_mess
= *mp
;
1221 assert(!(fp
->fxp_flags
& FF_READING
));
1222 fp
->fxp_flags
|= FF_READING
;
1227 /*===========================================================================*
1229 *===========================================================================*/
1230 static void fxp_do_conf(fp
)
1234 phys_bytes bus_addr
;
1236 /* Configure device */
1237 tmpbufp
->cc
.cc_status
= 0;
1238 tmpbufp
->cc
.cc_command
= CBL_C_EL
| CBL_CONF
;
1239 tmpbufp
->cc
.cc_linkaddr
= 0;
1240 memcpy(tmpbufp
->cc
.cc_bytes
, fp
->fxp_conf_bytes
,
1241 sizeof(tmpbufp
->cc
.cc_bytes
));
1243 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&tmpbufp
->cc
,
1244 (phys_bytes
)sizeof(tmpbufp
->cc
), &bus_addr
);
1246 panic("sys_umap failed: %d", r
);
1248 fxp_cu_ptr_cmd(fp
, SC_CU_START
, bus_addr
, TRUE
/* check idle */);
1250 /* Wait for CU command to complete */
1251 SPIN_UNTIL(tmpbufp
->cc
.cc_status
& CBL_F_C
, 100000);
1253 if (!(tmpbufp
->cc
.cc_status
& CBL_F_C
))
1254 panic("fxp_do_conf: CU command failed to complete");
1255 if (!(tmpbufp
->cc
.cc_status
& CBL_F_OK
))
1256 panic("fxp_do_conf: CU command failed");
1260 /*===========================================================================*
1262 *===========================================================================*/
1263 static void fxp_cu_ptr_cmd(fp
, cmd
, bus_addr
, check_idle
)
1266 phys_bytes bus_addr
;
1273 port
= fp
->fxp_base_port
;
1277 /* Consistency check. Make sure that CU is idle */
1278 if ((fxp_inb(port
, SCB_STATUS
) & SS_CUS_MASK
) != SS_CU_IDLE
)
1279 panic("fxp_cu_ptr_cmd: CU is not idle");
1282 fxp_outl(port
, SCB_POINTER
, bus_addr
);
1283 fxp_outb(port
, SCB_CMD
, cmd
);
1285 /* What is a reasonable time-out? There is nothing in the
1286 * documentation. 1 ms should be enough. We use 100 ms.
1288 spin_init(&spin
, 100000);
1290 /* Wait for CU command to be accepted */
1291 scb_cmd
= fxp_inb(port
, SCB_CMD
);
1292 if ((scb_cmd
& SC_CUC_MASK
) == SC_CU_NOP
)
1294 } while (spin_check(&spin
));
1296 if ((scb_cmd
& SC_CUC_MASK
) != SC_CU_NOP
)
1297 panic("fxp_cu_ptr_cmd: CU does not accept command");
1300 /*===========================================================================*
1302 *===========================================================================*/
1303 static void fxp_ru_ptr_cmd(fp
, cmd
, bus_addr
, check_idle
)
1306 phys_bytes bus_addr
;
1313 port
= fp
->fxp_base_port
;
1317 /* Consistency check, make sure that RU is idle */
1318 if ((fxp_inb(port
, SCB_STATUS
) & SS_RUS_MASK
) != SS_RU_IDLE
)
1319 panic("fxp_ru_ptr_cmd: RU is not idle");
1322 fxp_outl(port
, SCB_POINTER
, bus_addr
);
1323 fxp_outb(port
, SCB_CMD
, cmd
);
1325 spin_init(&spin
, 1000);
1327 /* Wait for RU command to be accepted */
1328 scb_cmd
= fxp_inb(port
, SCB_CMD
);
1329 if ((scb_cmd
& SC_RUC_MASK
) == SC_RU_NOP
)
1331 } while (spin_check(&spin
));
1333 if ((scb_cmd
& SC_RUC_MASK
) != SC_RU_NOP
)
1334 panic("fxp_ru_ptr_cmd: RU does not accept command");
1337 /*===========================================================================*
1339 *===========================================================================*/
1340 static void fxp_restart_ru(fp
)
1347 port
= fp
->fxp_base_port
;
1349 fxp_rx_nbuf
= fp
->fxp_rx_nbuf
;
1350 for (i
= 0, rfdp
= fp
->fxp_rx_buf
; i
<fxp_rx_nbuf
; i
++, rfdp
++)
1352 rfdp
->rfd_status
= 0;
1353 rfdp
->rfd_command
= 0;
1354 if (i
== fp
->fxp_rx_nbuf
-1)
1355 rfdp
->rfd_command
= RFDC_EL
;
1356 rfdp
->rfd_reserved
= 0;
1358 rfdp
->rfd_size
= sizeof(rfdp
->rfd_buf
);
1362 /* Make sure that RU is in the 'No resources' state */
1363 if ((fxp_inb(port
, SCB_STATUS
) & SS_RUS_MASK
) != SS_RU_NORES
)
1364 panic("fxp_restart_ru: RU is in an unexpected state");
1366 fxp_ru_ptr_cmd(fp
, SC_RU_START
, fp
->fxp_rx_busaddr
,
1367 FALSE
/* do not check idle */);
1370 /*===========================================================================*
1372 *===========================================================================*/
1373 static void fxp_getstat_s(message
*mp
)
1382 assert(fp
->fxp_mode
== FM_ENABLED
);
1383 assert(fp
->fxp_flags
& FF_ENABLED
);
1385 p
= &fp
->fxp_stat
.sc_tx_fcp
;
1388 /* The dump commmand doesn't take a pointer. Setting a pointer
1389 * doesn't hurt though.
1391 fxp_cu_ptr_cmd(fp
, SC_CU_DUMP_SC
, 0, FALSE
/* do not check idle */);
1393 /* Wait for CU command to complete */
1394 SPIN_UNTIL(*p
!= 0, 1000);
1397 panic("fxp_getstat: CU command failed to complete");
1399 panic("fxp_getstat: bad magic");
1402 fp
->fxp_stat
.sc_rx_crc
+
1403 fp
->fxp_stat
.sc_rx_align
+
1404 fp
->fxp_stat
.sc_rx_resource
+
1405 fp
->fxp_stat
.sc_rx_overrun
+
1406 fp
->fxp_stat
.sc_rx_cd
+
1407 fp
->fxp_stat
.sc_rx_short
;
1409 fp
->fxp_stat
.sc_tx_maxcol
+
1410 fp
->fxp_stat
.sc_tx_latecol
+
1411 fp
->fxp_stat
.sc_tx_crs
;
1412 stats
.ets_OVW
= fp
->fxp_stat
.sc_rx_overrun
;
1413 stats
.ets_CRCerr
= fp
->fxp_stat
.sc_rx_crc
;
1414 stats
.ets_frameAll
= fp
->fxp_stat
.sc_rx_align
;
1415 stats
.ets_missedP
= fp
->fxp_stat
.sc_rx_resource
;
1416 stats
.ets_packetR
= fp
->fxp_stat
.sc_rx_good
;
1417 stats
.ets_packetT
= fp
->fxp_stat
.sc_tx_good
;
1418 stats
.ets_transDef
= fp
->fxp_stat
.sc_tx_defered
;
1419 stats
.ets_collision
= fp
->fxp_stat
.sc_tx_totcol
;
1420 stats
.ets_transAb
= fp
->fxp_stat
.sc_tx_maxcol
;
1421 stats
.ets_carrSense
= fp
->fxp_stat
.sc_tx_crs
;
1422 stats
.ets_fifoUnder
= fp
->fxp_stat
.sc_tx_underrun
;
1423 stats
.ets_fifoOver
= fp
->fxp_stat
.sc_rx_overrun
;
1424 stats
.ets_CDheartbeat
= 0;
1425 stats
.ets_OWC
= fp
->fxp_stat
.sc_tx_latecol
;
1427 r
= sys_safecopyto(mp
->m_source
, mp
->DL_GRANT
, 0, (vir_bytes
)&stats
,
1430 panic("fxp_getstat_s: sys_safecopyto failed: %d", r
);
1432 mp
->m_type
= DL_STAT_REPLY
;
1433 r
= send(mp
->m_source
, mp
);
1435 panic("fxp_getstat_s: send failed: %d", r
);
1438 /*===========================================================================*
1440 *===========================================================================*/
1441 static void fxp_handler(fxp_t
*fp
)
1448 port
= fp
->fxp_base_port
;
1451 isr
= fxp_inb(port
, SCB_INT_STAT
);
1452 fxp_outb(port
, SCB_INT_STAT
, isr
);
1458 if (!fp
->fxp_got_int
&& (fp
->fxp_flags
& FF_READING
))
1460 fp
->fxp_got_int
= TRUE
;
1461 interrupt(fxp_tasknr
);
1467 if (!fp
->fxp_tx_idle
)
1469 fp
->fxp_send_int
= TRUE
;
1470 if (!fp
->fxp_got_int
)
1472 fp
->fxp_got_int
= TRUE
;
1473 interrupt(fxp_tasknr
);
1481 /* Assume that receive buffer is full of packets. fxp_readv
1482 * will restart the RU.
1484 fp
->fxp_rx_need_restart
= 1;
1488 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
1493 /*===========================================================================*
1495 *===========================================================================*/
1496 static void fxp_check_ints(fxp_t
*fp
)
1498 int n
, fxp_flags
, prev_tail
;
1499 int fxp_tx_tail
, fxp_tx_nbuf
, fxp_tx_threshold
;
1506 fxp_flags
= fp
->fxp_flags
;
1508 if (fxp_flags
& FF_READING
)
1510 if (!(fp
->fxp_rx_buf
[fp
->fxp_rx_head
].rfd_status
& RFDS_C
))
1514 fxp_readv_s(&fp
->fxp_rx_mess
, TRUE
/* from int */);
1517 if (fp
->fxp_tx_idle
)
1518 ; /* Nothing to do */
1519 else if (fp
->fxp_send_int
)
1521 fp
->fxp_send_int
= FALSE
;
1522 fxp_tx_tail
= fp
->fxp_tx_tail
;
1523 fxp_tx_nbuf
= fp
->fxp_tx_nbuf
;
1527 txp
= &fp
->fxp_tx_buf
[fxp_tx_tail
];
1528 tx_status
= txp
->tx_status
;
1529 if (!(tx_status
& TXS_C
))
1534 assert(tx_status
& TXS_OK
);
1535 if (tx_status
& TXS_U
)
1537 fxp_tx_threshold
= fp
->fxp_tx_threshold
;
1538 if (fxp_tx_threshold
< TXTT_MAX
)
1541 fp
->fxp_tx_threshold
= fxp_tx_threshold
;
1544 "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
1548 if (txp
->tx_command
& TXC_EL
)
1555 if (fxp_tx_tail
== fxp_tx_nbuf
)
1557 assert(fxp_tx_tail
< fxp_tx_nbuf
);
1560 if (fp
->fxp_need_conf
)
1562 /* Check the status of the CU */
1563 port
= fp
->fxp_base_port
;
1564 scb_status
= fxp_inb(port
, SCB_STATUS
);
1565 if ((scb_status
& SS_CUS_MASK
) != SS_CU_IDLE
)
1568 printf("scb_status = 0x%x\n", scb_status
);
1572 printf("fxp_check_ints: fxp_need_conf\n");
1573 fp
->fxp_need_conf
= FALSE
;
1580 if (!fp
->fxp_tx_idle
)
1582 fp
->fxp_tx_tail
= fxp_tx_tail
;
1584 /* Check the status of the CU */
1585 port
= fp
->fxp_base_port
;
1586 scb_status
= fxp_inb(port
, SCB_STATUS
);
1587 if ((scb_status
& SS_CUS_MASK
) != SS_CU_IDLE
)
1590 printf("scb_status = 0x%x\n",
1596 if (fxp_tx_tail
== 0)
1597 prev_tail
= fxp_tx_nbuf
-1;
1599 prev_tail
= fxp_tx_tail
-1;
1600 busaddr
= fp
->fxp_tx_buf
[prev_tail
].
1603 fxp_cu_ptr_cmd(fp
, SC_CU_START
,
1604 busaddr
, 1 /* check idle */);
1608 if (fp
->fxp_flags
& FF_SEND_AVAIL
)
1610 fxp_writev_s(&fp
->fxp_tx_mess
,
1611 TRUE
/* from int */);
1616 if (fp
->fxp_report_link
)
1617 fxp_report_link(fp
);
1619 if (fp
->fxp_flags
& (FF_PACK_SENT
| FF_PACK_RECV
))
1623 /*===========================================================================*
1625 *===========================================================================*/
1626 static void fxp_watchdog_f(tp
)
1631 set_timer(&fxp_watchdog
, system_hz
, fxp_watchdog_f
, 0);
1634 if (fp
->fxp_mode
!= FM_ENABLED
)
1637 /* Handle race condition, MII interface might be busy */
1638 if(!fp
->fxp_mii_busy
)
1640 /* Check the link status. */
1641 if (fxp_link_changed(fp
))
1644 printf("fxp_watchdog_f: link changed\n");
1646 fp
->fxp_report_link
= TRUE
;
1647 fp
->fxp_got_int
= TRUE
;
1648 interrupt(fxp_tasknr
);
1652 if (!(fp
->fxp_flags
& FF_SEND_AVAIL
))
1654 /* Assume that an idle system is alive */
1655 fp
->fxp_tx_alive
= TRUE
;
1658 if (fp
->fxp_tx_alive
)
1660 fp
->fxp_tx_alive
= FALSE
;
1664 fp
->fxp_need_reset
= TRUE
;
1665 fp
->fxp_got_int
= TRUE
;
1666 interrupt(fxp_tasknr
);
1669 /*===========================================================================*
1670 * fxp_link_changed *
1671 *===========================================================================*/
1672 static int fxp_link_changed(fp
)
1677 scr
= mii_read(fp
, MII_SCR
);
1678 scr
&= ~(MII_SCR_RES
|MII_SCR_RES_1
);
1680 return (fp
->fxp_mii_scr
!= scr
);
1683 /*===========================================================================*
1685 *===========================================================================*/
1686 static void fxp_report_link(fxp_t
*fp
)
1688 u16_t mii_ctrl
, mii_status
, mii_id1
, mii_id2
,
1689 mii_ana
, mii_anlpa
, mii_ane
, mii_extstat
,
1690 mii_ms_ctrl
, mii_ms_status
, scr
;
1695 fp
->fxp_report_link
= FALSE
;
1697 scr
= mii_read(fp
, MII_SCR
);
1698 scr
&= ~(MII_SCR_RES
|MII_SCR_RES_1
);
1699 fp
->fxp_mii_scr
= scr
;
1701 mii_ctrl
= mii_read(fp
, MII_CTRL
);
1702 mii_read(fp
, MII_STATUS
); /* The status reg is latched, read twice */
1703 mii_status
= mii_read(fp
, MII_STATUS
);
1704 mii_id1
= mii_read(fp
, MII_PHYID_H
);
1705 mii_id2
= mii_read(fp
, MII_PHYID_L
);
1706 mii_ana
= mii_read(fp
, MII_ANA
);
1707 mii_anlpa
= mii_read(fp
, MII_ANLPA
);
1708 mii_ane
= mii_read(fp
, MII_ANE
);
1709 if (mii_status
& MII_STATUS_EXT_STAT
)
1710 mii_extstat
= mii_read(fp
, MII_EXT_STATUS
);
1713 if (fp
->fxp_ms_regs
)
1715 mii_ms_ctrl
= mii_read(fp
, MII_MS_CTRL
);
1716 mii_ms_status
= mii_read(fp
, MII_MS_STATUS
);
1724 /* How do we know about the link status? */
1725 link_up
= !!(mii_status
& MII_STATUS_LS
);
1727 fp
->fxp_link_up
= link_up
;
1731 printf("%s: link down\n", fp
->fxp_name
);
1736 oui
= (mii_id1
<< MII_PH_OUI_H_C_SHIFT
) |
1737 ((mii_id2
& MII_PL_OUI_L_MASK
) >> MII_PL_OUI_L_SHIFT
);
1738 model
= ((mii_id2
& MII_PL_MODEL_MASK
) >> MII_PL_MODEL_SHIFT
);
1739 rev
= (mii_id2
& MII_PL_REV_MASK
);
1742 printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui
, model
, rev
);
1745 if (mii_ctrl
& (MII_CTRL_LB
|MII_CTRL_PD
|MII_CTRL_ISO
))
1747 printf("%s: PHY: ", fp
->fxp_name
);
1749 if (mii_ctrl
& MII_CTRL_LB
)
1751 printf("loopback mode");
1754 if (mii_ctrl
& MII_CTRL_PD
)
1756 if (!f
) printf(", ");
1758 printf("powered down");
1760 if (mii_ctrl
& MII_CTRL_ISO
)
1762 if (!f
) printf(", ");
1769 if (!(mii_ctrl
& MII_CTRL_ANE
))
1771 printf("%s: manual config: ", fp
->fxp_name
);
1772 switch(mii_ctrl
& (MII_CTRL_SP_LSB
|MII_CTRL_SP_MSB
))
1774 case MII_CTRL_SP_10
: printf("10 Mbps"); break;
1775 case MII_CTRL_SP_100
: printf("100 Mbps"); break;
1776 case MII_CTRL_SP_1000
: printf("1000 Mbps"); break;
1777 case MII_CTRL_SP_RES
: printf("reserved speed"); break;
1779 if (mii_ctrl
& MII_CTRL_DM
)
1780 printf(", full duplex");
1782 printf(", half duplex");
1787 if (!debug
) goto resspeed
;
1789 printf("%s: ", fp
->fxp_name
);
1790 mii_print_stat_speed(mii_status
, mii_extstat
);
1793 if (!(mii_status
& MII_STATUS_ANC
))
1794 printf("%s: auto-negotiation not complete\n", fp
->fxp_name
);
1795 if (mii_status
& MII_STATUS_RF
)
1796 printf("%s: remote fault detected\n", fp
->fxp_name
);
1797 if (!(mii_status
& MII_STATUS_ANA
))
1799 printf("%s: local PHY has no auto-negotiation ability\n",
1802 if (!(mii_status
& MII_STATUS_LS
))
1803 printf("%s: link down\n", fp
->fxp_name
);
1804 if (mii_status
& MII_STATUS_JD
)
1805 printf("%s: jabber condition detected\n", fp
->fxp_name
);
1806 if (!(mii_status
& MII_STATUS_EC
))
1808 printf("%s: no extended register set\n", fp
->fxp_name
);
1811 if (!(mii_status
& MII_STATUS_ANC
))
1814 printf("%s: local cap.: ", fp
->fxp_name
);
1815 if (mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
1817 printf("1000 Mbps: T-");
1818 switch(mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
1820 case MII_MSC_1000T_FD
: printf("FD"); break;
1821 case MII_MSC_1000T_HD
: printf("HD"); break;
1822 default: printf("FD/HD"); break;
1827 mii_print_techab(mii_ana
);
1830 if (mii_ane
& MII_ANE_PDF
)
1831 printf("%s: parallel detection fault\n", fp
->fxp_name
);
1832 if (!(mii_ane
& MII_ANE_LPANA
))
1834 printf("%s: link-partner does not support auto-negotiation\n",
1839 printf("%s: remote cap.: ", fp
->fxp_name
);
1840 if (mii_ms_ctrl
& (MII_MSC_1000T_FD
| MII_MSC_1000T_HD
))
1841 if (mii_ms_status
& (MII_MSS_LP1000T_FD
| MII_MSS_LP1000T_HD
))
1843 printf("1000 Mbps: T-");
1844 switch(mii_ms_status
&
1845 (MII_MSS_LP1000T_FD
| MII_MSS_LP1000T_HD
))
1847 case MII_MSS_LP1000T_FD
: printf("FD"); break;
1848 case MII_MSS_LP1000T_HD
: printf("HD"); break;
1849 default: printf("FD/HD"); break;
1854 mii_print_techab(mii_anlpa
);
1857 if (fp
->fxp_ms_regs
)
1859 printf("%s: ", fp
->fxp_name
);
1860 if (mii_ms_ctrl
& MII_MSC_MS_MANUAL
)
1863 (mii_ms_ctrl
& MII_MSC_MS_VAL
) ?
1864 "MASTER" : "SLAVE");
1869 (mii_ms_ctrl
& MII_MSC_MULTIPORT
) ?
1870 "multiport" : "single-port");
1872 if (mii_ms_ctrl
& MII_MSC_RES
)
1873 printf(" reserved<0x%x>", mii_ms_ctrl
& MII_MSC_RES
);
1875 if (mii_ms_status
& MII_MSS_FAULT
)
1876 printf("M/S config fault");
1877 else if (mii_ms_status
& MII_MSS_MASTER
)
1884 if (mii_ms_status
& (MII_MSS_LP1000T_FD
|MII_MSS_LP1000T_HD
))
1886 if (!(mii_ms_status
& MII_MSS_LOCREC
))
1888 printf("%s: local receiver not OK\n",
1891 if (!(mii_ms_status
& MII_MSS_REMREC
))
1893 printf("%s: remote receiver not OK\n",
1897 if (mii_ms_status
& (MII_MSS_RES
|MII_MSS_IDLE_ERR
))
1899 printf("%s", fp
->fxp_name
);
1900 if (mii_ms_status
& MII_MSS_RES
)
1901 printf(" reserved<0x%x>", mii_ms_status
& MII_MSS_RES
);
1902 if (mii_ms_status
& MII_MSS_IDLE_ERR
)
1904 printf(" idle error %d",
1905 mii_ms_status
& MII_MSS_IDLE_ERR
);
1912 printf("%s: link up, %d Mbps, %s duplex\n",
1913 fp
->fxp_name
, (scr
& MII_SCR_100
) ? 100 : 10,
1914 (scr
& MII_SCR_FD
) ? "full" : "half");
1919 /*===========================================================================*
1921 *===========================================================================*/
1922 static void reply(fp
)
1930 if (fp
->fxp_flags
& FF_PACK_SENT
)
1931 flags
|= DL_PACK_SEND
;
1932 if (fp
->fxp_flags
& FF_PACK_RECV
)
1933 flags
|= DL_PACK_RECV
;
1935 reply
.m_type
= DL_TASK_REPLY
;
1936 reply
.DL_FLAGS
= flags
;
1937 reply
.DL_COUNT
= fp
->fxp_read_s
;
1939 r
= send(fp
->fxp_client
, &reply
);
1942 panic("fxp: send failed: %d", r
);
1945 fp
->fxp_flags
&= ~(FF_PACK_SENT
| FF_PACK_RECV
);
1948 /*===========================================================================*
1950 *===========================================================================*/
1951 static void mess_reply(req
, reply_mess
)
1953 message
*reply_mess
;
1955 if (send(req
->m_source
, reply_mess
) != OK
)
1956 panic("fxp: unable to mess_reply");
1959 /*===========================================================================*
1961 *===========================================================================*/
1962 static u16_t
eeprom_read(fp
, reg
)
1970 alen
= fp
->fxp_ee_addrlen
;
1973 eeprom_addrsize(fp
);
1974 alen
= fp
->fxp_ee_addrlen
;
1975 assert(alen
== 6 || alen
== 8);
1978 port
= fp
->fxp_base_port
;
1980 fxp_outb(port
, CSR_EEPROM
, CE_EECS
); /* Enable EEPROM */
1981 v
= EEPROM_READ_PREFIX
;
1982 for (i
= EEPROM_PREFIX_LEN
-1; i
>= 0; i
--)
1984 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
1985 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
1986 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
1987 micro_delay(EESK_PERIOD
/2+1);
1988 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
1989 micro_delay(EESK_PERIOD
/2+1);
1993 for (i
= alen
-1; i
>= 0; i
--)
1995 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
1996 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
1997 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
1998 micro_delay(EESK_PERIOD
/2+1);
1999 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2000 micro_delay(EESK_PERIOD
/2+1);
2004 for (i
= 0; i
<16; i
++)
2006 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| CE_EESK
); /* Clock */
2007 micro_delay(EESK_PERIOD
/2+1);
2008 b
= !!(fxp_inb(port
, CSR_EEPROM
) & CE_EEDO
);
2010 fxp_outb(port
, CSR_EEPROM
, CE_EECS
);
2011 micro_delay(EESK_PERIOD
/2+1);
2013 fxp_outb(port
, CSR_EEPROM
, 0); /* Disable EEPROM */
2014 micro_delay(EECS_DELAY
);
2019 /*===========================================================================*
2021 *===========================================================================*/
2022 static void eeprom_addrsize(fp
)
2029 port
= fp
->fxp_base_port
;
2031 /* Try to find out the size of the EEPROM */
2032 fxp_outb(port
, CSR_EEPROM
, CE_EECS
); /* Enable EEPROM */
2033 v
= EEPROM_READ_PREFIX
;
2034 for (i
= EEPROM_PREFIX_LEN
-1; i
>= 0; i
--)
2036 b
= ((v
& (1 << i
)) ? CE_EEDI
: 0);
2037 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2038 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2039 micro_delay(EESK_PERIOD
/2+1);
2040 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2041 micro_delay(EESK_PERIOD
/2+1);
2044 for (i
= 0; i
<32; i
++)
2047 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
); /* bit */
2048 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
| CE_EESK
); /* Clock */
2049 micro_delay(EESK_PERIOD
/2+1);
2050 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| b
);
2051 micro_delay(EESK_PERIOD
/2+1);
2052 v
= fxp_inb(port
, CSR_EEPROM
);
2057 panic("eeprom_addrsize: failed");
2058 fp
->fxp_ee_addrlen
= i
+1;
2060 /* Discard 16 data bits */
2061 for (i
= 0; i
<16; i
++)
2063 fxp_outb(port
, CSR_EEPROM
, CE_EECS
| CE_EESK
); /* Clock */
2064 micro_delay(EESK_PERIOD
/2+1);
2065 fxp_outb(port
, CSR_EEPROM
, CE_EECS
);
2066 micro_delay(EESK_PERIOD
/2+1);
2068 fxp_outb(port
, CSR_EEPROM
, 0); /* Disable EEPROM */
2069 micro_delay(EECS_DELAY
);
2072 printf("%s EEPROM address length: %d\n",
2073 fp
->fxp_name
, fp
->fxp_ee_addrlen
);
2077 /*===========================================================================*
2079 *===========================================================================*/
2080 static u16_t
mii_read(fp
, reg
)
2088 port
= fp
->fxp_base_port
;
2090 assert(!fp
->fxp_mii_busy
);
2093 if (!(fxp_inl(port
, CSR_MDI_CTL
) & CM_READY
))
2094 panic("mii_read: MDI not ready");
2095 fxp_outl(port
, CSR_MDI_CTL
, CM_READ
| (1 << CM_PHYADDR_SHIFT
) |
2096 (reg
<< CM_REG_SHIFT
));
2098 spin_init(&spin
, 100000);
2100 v
= fxp_inl(port
, CSR_MDI_CTL
);
2103 } while (spin_check(&spin
));
2105 if (!(v
& CM_READY
))
2106 panic("mii_read: MDI not ready after command");
2109 assert(!fp
->fxp_mii_busy
);
2111 return v
& CM_DATA_MASK
;
2114 static u8_t
do_inb(port_t port
)
2119 r
= sys_inb(port
, &value
);
2121 panic("sys_inb failed: %d", r
);
2125 static u32_t
do_inl(port_t port
)
2130 r
= sys_inl(port
, &value
);
2132 panic("sys_inl failed: %d", r
);
2136 static void do_outb(port_t port
, u8_t value
)
2140 r
= sys_outb(port
, value
);
2142 panic("sys_outb failed: %d", r
);
2145 static void do_outl(port_t port
, u32_t value
)
2149 r
= sys_outl(port
, value
);
2151 panic("sys_outl failed: %d", r
);
2154 static void tell_dev(buf
, size
, pci_bus
, pci_dev
, pci_func
)
2165 r
= ds_retrieve_label_endpt("amddev", &dev_e
);
2170 "fxp`tell_dev: ds_retrieve_label_endpt failed for 'amddev': %d\n",
2176 m
.m_type
= IOMMU_MAP
;
2183 r
= sendrec(dev_e
, &m
);
2186 printf("fxp`tell_dev: sendrec to %d failed: %d\n",
2192 printf("fxp`tell_dev: dma map request failed: %d\n",
2199 * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $