diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2007-07-04 17:12:20 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2007-07-04 17:12:20 +0000 |
commit | a2080f0904e347f69b1b64eeff0940cb58ac6147 (patch) | |
tree | 9799431565f7c413202ce2e5e2311ea55da3ca21 /sys/dev | |
parent | 9372fe533258ab6e647a8913570b6d545e8ca211 (diff) |
bye bye
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/mb86960reg.h | 322 | ||||
-rw-r--r-- | sys/dev/isa/if_fe.c | 2459 | ||||
-rw-r--r-- | sys/dev/isa/if_fereg.h | 114 |
3 files changed, 0 insertions, 2895 deletions
diff --git a/sys/dev/ic/mb86960reg.h b/sys/dev/ic/mb86960reg.h deleted file mode 100644 index 93af344566e..00000000000 --- a/sys/dev/ic/mb86960reg.h +++ /dev/null @@ -1,322 +0,0 @@ -/* $OpenBSD: mb86960reg.h,v 1.3 2003/10/21 18:58:49 jmc Exp $ */ - -/* - * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 - * - * This software may be used, modified, copied, distributed, and sold, in - * both source and binary form provided that the above copyright, these - * terms and the following disclaimer are retained. The name of the author - * and/or the contributor may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#define FE_MB86960_H_VERSION "mb86960.h ver. 0.8" - -/* - * Registers of Fujitsu MB86960A/MB86965A Ethernet controller. - * Written and contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp> - */ - -/* - * Notes on register naming: - * - * Fujitsu documents for MB86960A/MB86965A use no memorable names - * for their registers. They defined only three names for 32 - * registers and appended numbers to distinguish registers of - * same name. Surprisingly, the numbers represent I/O address - * offsets of the registers from the base addresses, and their - * names correspond to the "bank" the registers are allocated. - * All this means that, for example, to say "read DLCR8" has no more - * than to say "read a register at offset 8 on bank DLCR." - * - * The following definitions may look silly, but that's what Fujitsu - * did, and it is necessary to know these names to read Fujitsu - * documents.. - */ - -/* Data Link Control Registers, on invaliant port addresses. */ -#define FE_DLCR0 0 -#define FE_DLCR1 1 -#define FE_DLCR2 2 -#define FE_DLCR3 3 -#define FE_DLCR4 4 -#define FE_DLCR5 5 -#define FE_DLCR6 6 -#define FE_DLCR7 7 - -/* More DLCRs, on register bank #0. */ -#define FE_DLCR8 8 -#define FE_DLCR9 9 -#define FE_DLCR10 10 -#define FE_DLCR11 11 -#define FE_DLCR12 12 -#define FE_DLCR13 13 -#define FE_DLCR14 14 -#define FE_DLCR15 15 - -/* Multicast Address Registers. On register bank #1. */ -#define FE_MAR8 8 -#define FE_MAR9 9 -#define FE_MAR10 10 -#define FE_MAR11 11 -#define FE_MAR12 12 -#define FE_MAR13 13 -#define FE_MAR14 14 -#define FE_MAR15 15 - -/* Buffer Memory Port Registers. On register back #2. */ -#define FE_BMPR8 8 -#define FE_BMPR9 9 -#define FE_BMPR10 10 -#define FE_BMPR11 11 -#define FE_BMPR12 12 -#define FE_BMPR13 13 -#define FE_BMPR14 14 -#define FE_BMPR15 15 - -/* More BMPRs, only on MB86965A, accessible only when JLI mode. */ -#define FE_BMPR16 16 -#define FE_BMPR17 17 -#define FE_BMPR18 18 -#define FE_BMPR19 19 - -#define FE_RESET 31 - -/* - * Definitions of registers. - * I don't have Fujitsu documents of MB86960A/MB86965A, so I don't - * know the official names for the flags and fields. The following - * names are assigned by me (the author of this file), since I cannot - * memorize hexadecimal constants for all of these functions. - * Comments? FIXME. - */ - -/* DLCR0 -- transmitter status */ -#define FE_D0_BUSERR 0x01 /* Bus write error */ -#define FE_D0_COLL16 0x02 /* Collision limit (16) encountered */ -#define FE_D0_COLLID 0x04 /* Collision on last transmission */ -#define FE_D0_JABBER 0x08 /* Jabber */ -#define FE_D0_CRLOST 0x10 /* Carrier lost on last transmission */ -#define FE_D0_PKTRCD 0x20 /* No collision on last transmission */ -#define FE_D0_NETBSY 0x40 /* Network Busy (Carrier Detected) */ -#define FE_D0_TXDONE 0x80 /* Transmission complete */ - -/* DLCR1 -- receiver status */ -#define FE_D1_OVRFLO 0x01 /* Receiver buffer overflow */ -#define FE_D1_CRCERR 0x02 /* CRC error on last packet */ -#define FE_D1_ALGERR 0x04 /* Alignment error on last packet */ -#define FE_D1_SRTPKT 0x08 /* Short (RUNT) packet is received */ -#define FE_D1_RMTRST 0x10 /* Remote reset packet (type = 0x0900) */ -#define FE_D1_DMAEOP 0x20 /* Host asserted End of DMA OPeration */ -#define FE_D1_BUSERR 0x40 /* Bus read error */ -#define FE_D1_PKTRDY 0x80 /* Packet(s) ready on receive buffer */ - -#define FE_D1_ERRBITS "\20\4SRTPKT\3ALGERR\2CRCERR\1OVRFLO" - -/* DLCR2 -- transmitter interrupt control; same layout as DLCR0 */ -#define FE_D2_BUSERR FE_D0_BUSERR -#define FE_D2_COLL16 FE_D0_COLL16 -#define FE_D2_COLLID FE_D0_COLLID -#define FE_D2_JABBER FE_D0_JABBER -#define FE_D2_TXDONE FE_D0_TXDONE - -#define FE_D2_RESERVED 0x70 - -/* DLCR3 -- receiver interrupt control; same layout as DLCR1 */ -#define FE_D3_OVRFLO FE_D1_OVRFLO -#define FE_D3_CRCERR FE_D1_CRCERR -#define FE_D3_ALGERR FE_D1_ALGERR -#define FE_D3_SRTPKT FE_D1_SRTPKT -#define FE_D3_RMTRST FE_D1_RMTRST -#define FE_D3_DMAEOP FE_D1_DMAEOP -#define FE_D3_BUSERR FE_D1_BUSERR -#define FE_D3_PKTRDY FE_D1_PKTRDY - -/* DLCR4 -- transmitter operation mode */ -#define FE_D4_DSC 0x01 /* Disable carrier sense on trans. */ -#define FE_D4_LBC 0x02 /* Loop back test control */ -#define FE_D4_CNTRL 0x04 /* - ??? */ -#define FE_D4_TEST1 0x08 /* Test output #1 */ -#define FE_D4_COL 0xF0 /* Collision counter */ - -#define FE_D4_LBC_ENABLE 0x00 /* Perform loop back test */ -#define FE_D4_LBC_DISABLE 0x02 /* Normal operation */ - -#define FE_D4_COL_SHIFT 4 - -/* DLCR5 -- receiver operation mode */ -#define FE_D5_AFM0 0x01 /* Receive packets for other stations */ -#define FE_D5_AFM1 0x02 /* Receive packets for this station */ -#define FE_D5_RMTRST 0x04 /* Enable remote reset operation */ -#define FE_D5_SRTPKT 0x08 /* Accept short (RUNT) packets */ -#define FE_D5_SRTADR 0x10 /* Short (16 bits?) MAC address */ -#define FE_D5_BADPKT 0x20 /* Accept packets with error */ -#define FE_D5_BUFEMP 0x40 /* Receive buffer is empty */ -#define FE_D5_TEST2 0x80 /* Test output #2 */ - -/* DLCR6 -- hardware configuration #0 */ -#define FE_D6_BUFSIZ 0x03 /* Size of NIC buffer SRAM */ -#define FE_D6_TXBSIZ 0x0C /* Size (and config)of trans. buffer */ -#define FE_D6_BBW 0x10 /* Buffer SRAM bus width */ -#define FE_D6_SBW 0x20 /* System bus width */ -#define FE_D6_SRAM 0x40 /* Buffer SRAM access time */ -#define FE_D6_DLC 0x80 /* Disable DLC (receiver/transmitter) */ - -#define FE_D6_BUFSIZ_8KB 0x00 /* The board has 8KB SRAM */ -#define FE_D6_BUFSIZ_16KB 0x01 /* The board has 16KB SRAM */ -#define FE_D6_BUFSIZ_32KB 0x02 /* The board has 32KB SRAM */ -#define FE_D6_BUFSIZ_64KB 0x03 /* The board has 64KB SRAM */ - -#define FE_D6_TXBSIZ_1x2KB 0x00 /* Single 2KB buffer for trans. */ -#define FE_D6_TXBSIZ_2x2KB 0x04 /* Double 2KB buffers */ -#define FE_D6_TXBSIZ_2x4KB 0x08 /* Double 4KB buffers */ -#define FE_D6_TXBSIZ_2x8KB 0x0C /* Double 8KB buffers */ - -#define FE_D6_BBW_WORD 0x00 /* SRAM has 16 bit data line */ -#define FE_D6_BBW_BYTE 0x10 /* SRAM has 8 bit data line */ - -#define FE_D6_SBW_WORD 0x00 /* Access with 16 bit (AT) bus */ -#define FE_D6_SBW_BYTE 0x20 /* Access with 8 bit (XT) bus */ - -#define FE_D6_SRAM_150ns 0x00 /* The board has slow SRAM */ -#define FE_D6_SRAM_100ns 0x40 /* The board has fast SRAM */ - -#define FE_D6_DLC_ENABLE 0x00 /* Normal operation */ -#define FE_D6_DLC_DISABLE 0x80 /* Stop sending/receiving */ - -/* DLC7 -- hardware configuration #1 */ -#define FE_D7_BYTSWP 0x01 /* Host byte order control */ -#define FE_D7_EOPPOL 0x02 /* Polarity of DMA EOP signal */ -#define FE_D7_RBS 0x0C /* Register bank select */ -#define FE_D7_RDYPNS 0x10 /* Senses RDYPNSEL input signal */ -#define FE_D7_POWER 0x20 /* Stand-by (power down) mode control */ -#define FE_D7_IDENT 0xC0 /* Chip identification */ - -#define FE_D7_BYTSWP_LH 0x00 /* DEC/Intel byte order */ -#define FE_D7_BYTSWP_HL 0x01 /* IBM/Motorolla byte order */ - -#define FE_D7_RBS_DLCR 0x00 /* Select DLCR8-15 */ -#define FE_D7_RBS_MAR 0x04 /* Select MAR8-15 */ -#define FE_D7_RBS_BMPR 0x08 /* Select BMPR8-15 */ - -#define FE_D7_POWER_DOWN 0x00 /* Power down (stand-by) mode */ -#define FE_D7_POWER_UP 0x20 /* Normal operation */ - -#define FE_D7_IDENT_NICE 0x80 -#define FE_D7_IDENT_EC 0xC0 - -/* DLCR8 thru DLCR13 are for Ethernet station address. */ - -/* DLCR14 and DLCR15 are for TDR. (BTW, what is TDR? FIXME.) */ - -/* MAR8 thru MAR15 are for Multicast address filter. */ - -/* BMPR8 and BMPR9 are for packet data. */ - -/* BMPR10 -- transmitter start trigger */ -#define FE_B10_START 0x80 /* Start transmitter */ -#define FE_B10_COUNT 0x7F /* Packet count */ - -/* BMPR11 -- 16 collisions control */ -#define FE_B11_CTRL 0x01 /* Skip or resend errored packets */ -#define FE_B11_MODE1 0x02 /* Restart transmitter after COLL16 */ -#define FE_B11_MODE2 0x04 /* Automatic restart enable */ - -#define FE_B11_CTRL_RESEND 0x00 /* Re-send the collided packet */ -#define FE_B11_CTRL_SKIP 0x01 /* Skip the collided packet */ - -/* BMPR12 -- DMA enable */ -#define FE_B12_TXDMA 0x01 /* Enable transmitter DMA */ -#define FE_B12_RXDMA 0x02 /* Enable receiver DMA */ - -/* BMPR13 -- DMA control */ -#define FE_B13_BSTCTL 0x03 /* DMA burst mode control */ -#define FE_B13_TPTYPE 0x04 /* Twisted pair cable impedance */ -#define FE_B13_PORT 0x18 /* Port (TP/AUI) selection */ -#define FE_B13_LNKTST 0x20 /* Link test enable */ -#define FE_B13_SQTHLD 0x40 /* Lower squelch threshold */ -#define FE_B13_IOUNLK 0x80 /* Change I/O base address */ - -#define FE_B13_BSTCTL_1 0x00 -#define FE_B13_BSTCTL_4 0x01 -#define FE_B13_BSTCTL_8 0x02 -#define FE_B13_BSTCLT_12 0x03 - -#define FE_B13_TPTYPE_UTP 0x00 /* Unshielded (standard) cable */ -#define FE_B13_TPTYPE_STP 0x04 /* Shielded (IBM) cable */ - -#define FE_B13_PORT_AUTO 0x00 /* Auto detected */ -#define FE_B13_PORT_TP 0x08 /* Force TP */ -#define FE_B13_PORT_AUI 0x18 /* Force AUI */ - -/* BMPR14 -- More receiver control and more transmission interrupts */ -#define FE_B14_FILTER 0x01 /* Filter out self-originated packets */ -#define FE_B14_SQE 0x02 /* SQE interrupt enable */ -#define FE_B14_SKIP 0x04 /* Skip a received packet */ -#define FE_B14_RJAB 0x20 /* RJAB interrupt enable */ -#define FE_B14_LLD 0x40 /* Local-link-down interrupt enable */ -#define FE_B14_RLD 0x80 /* Remote-link-down interrupt enable */ - -/* BMPR15 -- More transmitter status; basically same layout as BMPR14 */ -#define FE_B15_SQE FE_B14_SQE -#define FE_B15_RCVPOL 0x08 /* Reversed receive line polarity */ -#define FE_B15_RMTPRT 0x10 /* ??? */ -#define FE_B15_RAJB FE_B14_RJAB -#define FE_B15_LLD FE_B14_LLD -#define FE_B15_RLD FE_B14_RLD - -/* BMPR16 -- EEPROM control */ -#define FE_B16_DOUT 0x04 /* EEPROM Data in (CPU to EEPROM) */ -#define FE_B16_SELECT 0x20 /* EEPROM chip select */ -#define FE_B16_CLOCK 0x40 /* EEPROM shift clock */ -#define FE_B16_DIN 0x80 /* EEPROM data out (EEPROM to CPU) */ - -/* BMPR17 -- EEPROM data */ -#define FE_B17_DATA 0x80 /* EEPROM data bit */ - -/* BMPR18 ??? */ - -/* BMPR19 -- ISA interface configuration */ -#define FE_B19_IRQ 0xC0 -#define FE_B19_IRQ_SHIFT 6 - -#define FE_B19_ROM 0x38 -#define FE_B19_ROM_SHIFT 3 - -#define FE_B19_ADDR 0x07 -#define FE_B19_ADDR_SHIFT 0 - -/* - * EEPROM specification (of JLI mode). - */ - -/* Number of bytes in an EEPROM accessible through 86965. */ -#define FE_EEPROM_SIZE 32 - -/* Offset for JLI config; automatically copied into BMPR19 at startup. */ -#define FE_EEPROM_CONF 0 - -/* - * Some 86960 specific constants. - */ - -/* Length (in bytes) of a Multicast Address Filter. */ -#define FE_FILTER_LEN 8 - -/* How many packets we can put in the transmission buffer on NIC memory. */ -#define FE_QUEUEING_MAX 127 - -/* Length (in bytes) of a "packet length" word in transmission buffer. */ -#define FE_DATA_LEN_LEN 2 diff --git a/sys/dev/isa/if_fe.c b/sys/dev/isa/if_fe.c deleted file mode 100644 index 826f413ce87..00000000000 --- a/sys/dev/isa/if_fe.c +++ /dev/null @@ -1,2459 +0,0 @@ -/* $OpenBSD: if_fe.c,v 1.25 2006/03/25 22:41:44 djm Exp $ */ - -/* - * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 - * - * This software may be used, modified, copied, distributed, and sold, in - * both source and binary form provided that the above copyright, these - * terms and the following disclaimer are retained. The name of the author - * and/or the contributor may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION. - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions copyright (C) 1993, David Greenman. This software may be used, - * modified, copied, distributed, and sold, in both source and binary form - * provided that the above copyright and these terms are retained. Under no - * circumstances is the author responsible for the proper functioning of this - * software, nor does the author assume any responsibility for damages - * incurred with its use. - */ - -#define FE_VERSION "if_fe.c ver. 0.8" - -/* - * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards. - * Contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp> - * - * This version is intended to be a generic template for various - * MB86960A/MB86965A based Ethernet cards. It currently supports - * Fujitsu FMV-180 series (i.e., FMV-181 and FMV-182) and Allied- - * Telesis AT1700 series and RE2000 series. There are some - * unnecessary hooks embedded, which are primarily intended to support - * other types of Ethernet cards, but the author is not sure whether - * they are useful. - */ - -#include "bpfilter.h" - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/errno.h> -#include <sys/ioctl.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/syslog.h> -#include <sys/device.h> - -#include <net/if.h> -#include <net/if_dl.h> -#include <net/if_types.h> -#include <net/netisr.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#endif - -#if NBPFILTER > 0 -#include <net/bpf.h> -#endif - -#include <machine/cpu.h> -#include <machine/intr.h> -#include <machine/pio.h> - -#include <dev/isa/isareg.h> -#include <dev/isa/isavar.h> -#include <dev/ic/mb86960reg.h> -#include <dev/isa/if_fereg.h> - -/* - * Default settings for fe driver specific options. - * They can be set in config file by "options" statements. - */ - -/* - * Debug control. - * 0: No debug at all. All debug specific codes are stripped off. - * 1: Silent. No debug messages are logged except emergent ones. - * 2: Brief. Lair events and/or important information are logged. - * 3: Detailed. Logs all information which *may* be useful for debugging. - * 4: Trace. All actions in the driver is logged. Super verbose. - */ -#ifndef FE_DEBUG -#define FE_DEBUG 1 -#endif - -/* - * Delay padding of short transmission packets to minimum Ethernet size. - * This may or may not gain performance. An EXPERIMENTAL option. - */ -#ifndef FE_DELAYED_PADDING -#define FE_DELAYED_PADDING 0 -#endif - -/* - * Transmit just one packet per a "send" command to 86960. - * This option is intended for performance test. An EXPERIMENTAL option. - */ -#ifndef FE_SINGLE_TRANSMISSION -#define FE_SINGLE_TRANSMISSION 0 -#endif - -/* - * Device configuration flags. - */ - -/* DLCR6 settings. */ -#define FE_FLAGS_DLCR6_VALUE 0x007F - -/* Force DLCR6 override. */ -#define FE_FLAGS_OVERRIDE_DLCR6 0x0080 - -/* A cludge for PCMCIA support. */ -#define FE_FLAGS_PCMCIA 0x8000 - -/* Identification of the driver version. */ -static char const fe_version[] = FE_VERSION " / " FE_REG_VERSION; - -/* - * Supported hardware (Ethernet card) types - * This information is currently used only for debugging - */ -enum fe_type { - /* For cards which are successfully probed but not identified. */ - FE_TYPE_UNKNOWN, - - /* Fujitsu FMV-180 series. */ - FE_TYPE_FMV181, - FE_TYPE_FMV182, - - /* Allied-Telesis AT1700 series and RE2000 series. */ - FE_TYPE_AT1700T, - FE_TYPE_AT1700BT, - FE_TYPE_AT1700FT, - FE_TYPE_AT1700AT, - FE_TYPE_RE2000, - - /* PCMCIA by Fujitsu. */ - FE_TYPE_MBH10302, - FE_TYPE_MBH10304, -}; - -/* - * fe_softc: per line info and status - */ -struct fe_softc { - struct device sc_dev; - void *sc_ih; - - struct arpcom sc_arpcom; /* ethernet common */ - - /* Set by probe() and not modified in later phases. */ - enum fe_type type; /* interface type code */ - char *typestr; /* printable name of the interface. */ - int sc_iobase; /* MB86960A I/O base address */ - - u_char proto_dlcr4; /* DLCR4 prototype. */ - u_char proto_dlcr5; /* DLCR5 prototype. */ - u_char proto_dlcr6; /* DLCR6 prototype. */ - u_char proto_dlcr7; /* DLCR7 prototype. */ - u_char proto_bmpr13; /* BMPR13 prototype. */ - - /* Vendor specific hooks. */ - void (*init)(struct fe_softc *); /* Just before fe_init(). */ - void (*stop)(struct fe_softc *); /* Just after fe_stop(). */ - - /* Transmission buffer management. */ - u_short txb_size; /* total bytes in TX buffer */ - u_short txb_free; /* free bytes in TX buffer */ - u_char txb_count; /* number of packets in TX buffer */ - u_char txb_sched; /* number of scheduled packets */ - u_char txb_padding; /* number of delayed padding bytes */ - - /* Multicast address filter management. */ - u_char filter_change; /* MARs must be changed ASAP. */ - u_char filter[FE_FILTER_LEN]; /* new filter value. */ -}; - -/* Frequently accessed members in arpcom. */ -#define sc_enaddr sc_arpcom.ac_enaddr - -/* Standard driver entry points. These can be static. */ -int feprobe(struct device *, void *, void *); -void feattach(struct device *, struct device *, void *); -int feintr(void *); -void fe_init(struct fe_softc *); -int fe_ioctl(struct ifnet *, u_long, caddr_t); -void fe_start(struct ifnet *); -void fe_reset(struct fe_softc *); -void fe_watchdog(struct ifnet *); - -/* Local functions. Order of declaration is confused. FIXME. */ -int fe_probe_fmv(struct fe_softc *, struct isa_attach_args *); -int fe_probe_ati(struct fe_softc *, struct isa_attach_args *); -int fe_probe_mbh(struct fe_softc *, struct isa_attach_args *); -void fe_init_mbh(struct fe_softc *); -int fe_get_packet(struct fe_softc *, int); -void fe_stop(struct fe_softc *); -void fe_tint(/*struct fe_softc *, u_char*/); -void fe_rint(/*struct fe_softc *, u_char*/); -static inline -void fe_xmit(struct fe_softc *); -void fe_write_mbufs(struct fe_softc *, struct mbuf *); -void fe_getmcaf(struct arpcom *, u_char *); -void fe_setmode(struct fe_softc *); -void fe_loadmar(struct fe_softc *); -#if FE_DEBUG >= 1 -void fe_dump(int, struct fe_softc *); -#endif - -struct cfattach fe_ca = { - sizeof(struct fe_softc), feprobe, feattach -}; - -struct cfdriver fe_cd = { - NULL, "fe", DV_IFNET -}; - -/* Ethernet constants. To be defined in if_ehter.h? FIXME. */ -#define ETHER_MIN_LEN 60 /* with header, without CRC. */ -#define ETHER_MAX_LEN 1514 /* with header, without CRC. */ - -/* - * Fe driver specific constants which relate to 86960/86965. - */ - -/* Interrupt masks. */ -#define FE_TMASK (FE_D2_COLL16 | FE_D2_TXDONE) -#define FE_RMASK (FE_D3_OVRFLO | FE_D3_CRCERR | \ - FE_D3_ALGERR | FE_D3_SRTPKT | FE_D3_PKTRDY) - -/* Maximum number of iterrations for a receive interrupt. */ -#define FE_MAX_RECV_COUNT ((65536 - 2048 * 2) / 64) - /* Maximum size of SRAM is 65536, - * minimum size of transmission buffer in fe is 2x2KB, - * and minimum amount of received packet including headers - * added by the chip is 64 bytes. - * Hence FE_MAX_RECV_COUNT is the upper limit for number - * of packets in the receive buffer. */ - -/* - * Convenient routines to access contiguous I/O ports. - */ - -static inline void -inblk (int addr, u_char * mem, int len) -{ - while (--len >= 0) { - *mem++ = inb(addr++); - } -} - -static inline void -outblk (int addr, u_char const * mem, int len) -{ - while (--len >= 0) { - outb(addr++, *mem++); - } -} - -/* - * Hardware probe routines. - */ - -/* - * Determine if the device is present. - */ -int -feprobe(parent, match, aux) - struct device *parent; - void *match, *aux; -{ - struct fe_softc *sc = match; - struct isa_attach_args *ia = aux; - -#if FE_DEBUG >= 2 - log(LOG_INFO, "%s: %s\n", sc->sc_dev.dv_xname, fe_version); -#endif - - /* Probe an address. */ - sc->sc_iobase = ia->ia_iobase; - - if (fe_probe_fmv(sc, ia)) - return (1); - if (fe_probe_ati(sc, ia)) - return (1); - if (fe_probe_mbh(sc, ia)) - return (1); - return (0); -} - -/* - * Check for specific bits in specific registers have specific values. - */ -struct fe_simple_probe_struct { - u_char port; /* Offset from the base I/O address. */ - u_char mask; /* Bits to be checked. */ - u_char bits; /* Values to be compared against. */ -}; - -static inline int -fe_simple_probe (int addr, struct fe_simple_probe_struct const * sp) -{ - struct fe_simple_probe_struct const * p; - - for (p = sp; p->mask != 0; p++) { - if ((inb(addr + p->port) & p->mask) != p->bits) { - return (0); - } - } - return (1); -} - -/* - * Routines to read all bytes from the config EEPROM through MB86965A. - * I'm not sure what exactly I'm doing here... I was told just to follow - * the steps, and it worked. Could someone tell me why the following - * code works? (Or, why all similar codes I tried previously doesn't - * work.) FIXME. - */ - -static inline void -strobe (int bmpr16) -{ - /* - * Output same value twice. To speed-down execution? - */ - outb(bmpr16, FE_B16_SELECT); - outb(bmpr16, FE_B16_SELECT); - outb(bmpr16, FE_B16_SELECT | FE_B16_CLOCK); - outb(bmpr16, FE_B16_SELECT | FE_B16_CLOCK); - outb(bmpr16, FE_B16_SELECT); - outb(bmpr16, FE_B16_SELECT); -} - -void -fe_read_eeprom(sc, data) - struct fe_softc *sc; - u_char *data; -{ - int iobase = sc->sc_iobase; - int bmpr16 = iobase + FE_BMPR16; - int bmpr17 = iobase + FE_BMPR17; - u_char n, val, bit; - - /* Read bytes from EEPROM; two bytes per an iterration. */ - for (n = 0; n < FE_EEPROM_SIZE / 2; n++) { - /* Reset the EEPROM interface. */ - outb(bmpr16, 0x00); - outb(bmpr17, 0x00); - outb(bmpr16, FE_B16_SELECT); - - /* Start EEPROM access. */ - outb(bmpr17, FE_B17_DATA); - strobe(bmpr16); - - /* Pass the iterration count to the chip. */ - val = 0x80 | n; - for (bit = 0x80; bit != 0x00; bit >>= 1) { - outb(bmpr17, (val & bit) ? FE_B17_DATA : 0); - strobe(bmpr16); - } - outb(bmpr17, 0x00); - - /* Read a byte. */ - val = 0; - for (bit = 0x80; bit != 0x00; bit >>= 1) { - strobe(bmpr16); - if (inb(bmpr17) & FE_B17_DATA) - val |= bit; - } - *data++ = val; - - /* Read one more byte. */ - val = 0; - for (bit = 0x80; bit != 0x00; bit >>= 1) { - strobe(bmpr16); - if (inb(bmpr17) & FE_B17_DATA) - val |= bit; - } - *data++ = val; - } - -#if FE_DEBUG >= 3 - /* Report what we got. */ - data -= FE_EEPROM_SIZE; - log(LOG_INFO, "%s: EEPROM at %04x:" - " %02x%02x%02x%02x %02x%02x%02x%02x -" - " %02x%02x%02x%02x %02x%02x%02x%02x -" - " %02x%02x%02x%02x %02x%02x%02x%02x -" - " %02x%02x%02x%02x %02x%02x%02x%02x\n", - sc->sc_dev.dv_xname, iobase, - data[ 0], data[ 1], data[ 2], data[ 3], - data[ 4], data[ 5], data[ 6], data[ 7], - data[ 8], data[ 9], data[10], data[11], - data[12], data[13], data[14], data[15], - data[16], data[17], data[18], data[19], - data[20], data[21], data[22], data[23], - data[24], data[25], data[26], data[27], - data[28], data[29], data[30], data[31]); -#endif -} - -/* - * Hardware (vendor) specific probe routines. - */ - -/* - * Probe and initialization for Fujitsu FMV-180 series boards - */ -int -fe_probe_fmv(sc, ia) - struct fe_softc *sc; - struct isa_attach_args *ia; -{ - int i, n; - int iobase = sc->sc_iobase; - int irq; - - static int const iomap[8] = - { 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x300, 0x340 }; - static int const irqmap[4] = - { 3, 7, 10, 15 }; - - static struct fe_simple_probe_struct const probe_table[] = { - { FE_DLCR2, 0x70, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - /* { FE_DLCR5, 0x80, 0x00 }, Doesn't work. */ - - { FE_FMV0, FE_FMV0_MAGIC_MASK, FE_FMV0_MAGIC_VALUE }, - { FE_FMV1, FE_FMV1_CARDID_MASK, FE_FMV1_CARDID_ID }, - { FE_FMV3, FE_FMV3_EXTRA_MASK, FE_FMV3_EXTRA_VALUE }, -#if 1 - /* - * Test *vendor* part of the station address for Fujitsu. - * The test will gain reliability of probe process, but - * it rejects FMV-180 clone boards manufactured by other vendors. - * We have to turn the test off when such cards are made available. - */ - { FE_FMV4, 0xFF, 0x00 }, - { FE_FMV5, 0xFF, 0x00 }, - { FE_FMV6, 0xFF, 0x0E }, -#else - /* - * We can always verify the *first* 2 bits (in Ethernet - * bit order) are "no multicast" and "no local" even for - * unknown vendors. - */ - { FE_FMV4, 0x03, 0x00 }, -#endif - { 0 } - }; - -#if 0 - /* - * Dont probe at all if the config says we are PCMCIA... - */ - if ((cf->cf_flags & FE_FLAGS_PCMCIA) != 0) - return (0); -#endif - - /* - * See if the sepcified address is possible for FMV-180 series. - */ - for (i = 0; i < 8; i++) { - if (iomap[i] == iobase) - break; - } - if (i == 8) - return (0); - - /* Simple probe. */ - if (!fe_simple_probe(iobase, probe_table)) - return (0); - - /* Check if our I/O address matches config info on EEPROM. */ - n = (inb(iobase + FE_FMV2) & FE_FMV2_ADDR) >> FE_FMV2_ADDR_SHIFT; - if (iomap[n] != iobase) - return (0); - - /* Determine the card type. */ - switch (inb(iobase + FE_FMV0) & FE_FMV0_MODEL) { - case FE_FMV0_MODEL_FMV181: - sc->type = FE_TYPE_FMV181; - sc->typestr = "FMV-181"; - break; - case FE_FMV0_MODEL_FMV182: - sc->type = FE_TYPE_FMV182; - sc->typestr = "FMV-182"; - break; - default: - /* Unknown card type: maybe a new model, but... */ - return (0); - } - - /* - * An FMV-180 has successfully been proved. - * Determine which IRQ to be used. - * - * In this version, we always get an IRQ assignment from the - * FMV-180's configuration EEPROM, ignoring that specified in - * config file. - */ - n = (inb(iobase + FE_FMV2) & FE_FMV2_IRQ) >> FE_FMV2_IRQ_SHIFT; - irq = irqmap[n]; - - if (ia->ia_irq != IRQUNK) { - if (ia->ia_irq != irq) { - printf("%s: irq mismatch; kernel configured %d != board configured %d\n", - sc->sc_dev.dv_xname, ia->ia_irq, irq); - return (0); - } - } else - ia->ia_irq = irq; - - /* - * Initialize constants in the per-line structure. - */ - - /* Get our station address from EEPROM. */ - inblk(iobase + FE_FMV4, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Make sure we got a valid station address. */ - if ((sc->sc_enaddr[0] & 0x03) != 0x00 - || (sc->sc_enaddr[0] == 0x00 - && sc->sc_enaddr[1] == 0x00 - && sc->sc_enaddr[2] == 0x00)) - return (0); - - /* Register values which depend on board design. */ - sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; - sc->proto_dlcr5 = 0; - sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC; - sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; - - /* - * Program the 86960 as follows: - * SRAM: 32KB, 100ns, byte-wide access. - * Transmission buffer: 4KB x 2. - * System bus interface: 16 bits. - * We cannot change these values but TXBSIZE, because they - * are hard-wired on the board. Modifying TXBSIZE will affect - * the driver performance. - */ - sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB - | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; - - /* - * Minimum initialization of the hardware. - * We write into registers; hope I/O ports have no - * overlap with other boards. - */ - - /* Initialize ASIC. */ - outb(iobase + FE_FMV3, 0); - outb(iobase + FE_FMV10, 0); - - /* Wait for a while. I'm not sure this is necessary. FIXME. */ - delay(200); - - /* Initialize 86960. */ - outb(iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); - delay(200); - - /* Disable all interrupts. */ - outb(iobase + FE_DLCR2, 0); - outb(iobase + FE_DLCR3, 0); - - /* Turn the "master interrupt control" flag of ASIC on. */ - outb(iobase + FE_FMV3, FE_FMV3_ENABLE_FLAG); - - /* - * That's all. FMV-180 occupies 32 I/O addresses, by the way. - */ - ia->ia_iosize = 32; - ia->ia_msize = 0; - return (1); -} - -/* - * Probe and initialization for Allied-Telesis AT1700/RE2000 series. - */ -int -fe_probe_ati(sc, ia) - struct fe_softc *sc; - struct isa_attach_args *ia; -{ - int i, n; - int iobase = sc->sc_iobase; - u_char eeprom[FE_EEPROM_SIZE]; - u_char save16, save17; - int irq; - - static int const iomap[8] = - { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300 }; - static int const irqmap[4][4] = { - { 3, 4, 5, 9 }, - { 10, 11, 12, 15 }, - { 3, 11, 5, 15 }, - { 10, 11, 14, 15 }, - }; - static struct fe_simple_probe_struct const probe_table[] = { - { FE_DLCR2, 0x70, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - { FE_DLCR5, 0x80, 0x00 }, -#if 0 - { FE_BMPR16, 0x1B, 0x00 }, - { FE_BMPR17, 0x7F, 0x00 }, -#endif - { 0 } - }; - -#if 0 - /* - * Don't probe at all if the config says we are PCMCIA... - */ - if ((cf->cf_flags & FE_FLAGS_PCMCIA) != 0) - return (0); -#endif - -#if FE_DEBUG >= 4 - log(LOG_INFO, "%s: probe (0x%x) for ATI\n", sc->sc_dev.dv_xname, iobase); - fe_dump(LOG_INFO, sc); -#endif - - /* - * See if the sepcified address is possible for MB86965A JLI mode. - */ - for (i = 0; i < 8; i++) { - if (iomap[i] == iobase) - break; - } - if (i == 8) - return (0); - - /* - * We should test if MB86965A is on the base address now. - * Unfortunately, it is very hard to probe it reliably, since - * we have no way to reset the chip under software control. - * On cold boot, we could check the "signature" bit patterns - * described in the Fujitsu document. On warm boot, however, - * we can predict almost nothing about register values. - */ - if (!fe_simple_probe(iobase, probe_table)) - return (0); - - /* Save old values of the registers. */ - save16 = inb(iobase + FE_BMPR16); - save17 = inb(iobase + FE_BMPR17); - - /* Check if our I/O address matches config info on 86965. */ - n = (inb(iobase + FE_BMPR19) & FE_B19_ADDR) >> FE_B19_ADDR_SHIFT; - if (iomap[n] != iobase) - goto fail; - - /* - * We are now almost sure we have an AT1700 at the given - * address. So, read EEPROM through 86965. We have to write - * into LSI registers to read from EEPROM. I want to avoid it - * at this stage, but I cannot test the presense of the chip - * any further without reading EEPROM. FIXME. - */ - fe_read_eeprom(sc, eeprom); - - /* Make sure the EEPROM is turned off. */ - outb(iobase + FE_BMPR16, 0); - outb(iobase + FE_BMPR17, 0); - - /* Make sure that config info in EEPROM and 86965 agree. */ - if (eeprom[FE_EEPROM_CONF] != inb(iobase + FE_BMPR19)) - goto fail; - - /* - * Determine the card type. - */ - switch (eeprom[FE_ATI_EEP_MODEL]) { - case FE_ATI_MODEL_AT1700T: - sc->type = FE_TYPE_AT1700T; - sc->typestr = "AT-1700T"; - break; - case FE_ATI_MODEL_AT1700BT: - sc->type = FE_TYPE_AT1700BT; - sc->typestr = "AT-1700BT"; - break; - case FE_ATI_MODEL_AT1700FT: - sc->type = FE_TYPE_AT1700FT; - sc->typestr = "AT-1700FT"; - break; - case FE_ATI_MODEL_AT1700AT: - sc->type = FE_TYPE_AT1700AT; - sc->typestr = "AT-1700AT"; - break; - default: - sc->type = FE_TYPE_RE2000; - sc->typestr = "unknown (RE-2000?)"; - break; - } - - /* - * Try to determine IRQ settings. - * Different models use different ranges of IRQs. - */ - n = (inb(iobase + FE_BMPR19) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT; - switch (eeprom[FE_ATI_EEP_REVISION] & 0xf0) { - case 0x30: - irq = irqmap[3][n]; - break; - case 0x10: - case 0x50: - irq = irqmap[2][n]; - break; - case 0x40: - case 0x60: - if (eeprom[FE_ATI_EEP_MAGIC] & 0x04) { - irq = irqmap[1][n]; - break; - } - default: - irq = irqmap[0][n]; - break; - } - - if (ia->ia_irq != IRQUNK) { - if (ia->ia_irq != irq) { - printf("%s: irq mismatch; kernel configured %d != board configured %d\n", - sc->sc_dev.dv_xname, ia->ia_irq, irq); - return (0); - } - } else - ia->ia_irq = irq; - - /* - * Initialize constants in the per-line structure. - */ - - /* Get our station address from EEPROM. */ - bcopy(eeprom + FE_ATI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Make sure we got a valid station address. */ - if ((sc->sc_enaddr[0] & 0x03) != 0x00 - || (sc->sc_enaddr[0] == 0x00 - && sc->sc_enaddr[1] == 0x00 - && sc->sc_enaddr[2] == 0x00)) - goto fail; - - /* Should find all register prototypes here. FIXME. */ - sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; /* FIXME */ - sc->proto_dlcr5 = 0; - sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC; -#if 0 /* XXXX Should we use this? */ - sc->proto_bmpr13 = eeprom[FE_ATI_EEP_MEDIA]; -#else - sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; -#endif - - /* - * Program the 86965 as follows: - * SRAM: 32KB, 100ns, byte-wide access. - * Transmission buffer: 4KB x 2. - * System bus interface: 16 bits. - * We cannot change these values but TXBSIZE, because they - * are hard-wired on the board. Modifying TXBSIZE will affect - * the driver performance. - */ - sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB - | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: ATI found\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* Initialize 86965. */ - outb(iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); - delay(200); - - /* Disable all interrupts. */ - outb(iobase + FE_DLCR2, 0); - outb(iobase + FE_DLCR3, 0); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: end of fe_probe_ati()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* - * That's all. AT1700 occupies 32 I/O addresses, by the way. - */ - ia->ia_iosize = 32; - ia->ia_msize = 0; - return (1); - -fail: - /* Restore register values, in the case we had no 86965. */ - outb(iobase + FE_BMPR16, save16); - outb(iobase + FE_BMPR17, save17); - return (0); -} - -/* - * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface. - */ -int -fe_probe_mbh(sc, ia) - struct fe_softc *sc; - struct isa_attach_args *ia; -{ - int iobase = sc->sc_iobase; - - static struct fe_simple_probe_struct probe_table[] = { - { FE_DLCR2, 0x70, 0x00 }, - { FE_DLCR4, 0x08, 0x00 }, - /* { FE_DLCR5, 0x80, 0x00 }, Does not work well. */ -#if 0 - /* - * Test *vendor* part of the address for Fujitsu. - * The test will gain reliability of probe process, but - * it rejects clones by other vendors, or OEM product - * supplied by resalers other than Fujitsu. - */ - { FE_MBH10, 0xFF, 0x00 }, - { FE_MBH11, 0xFF, 0x00 }, - { FE_MBH12, 0xFF, 0x0E }, -#else - /* - * We can always verify the *first* 2 bits (in Ethernet - * bit order) are "global" and "unicast" even for - * unknown vendors. - */ - { FE_MBH10, 0x03, 0x00 }, -#endif - /* Just a gap? Seems reliable, anyway. */ - { 0x12, 0xFF, 0x00 }, - { 0x13, 0xFF, 0x00 }, - { 0x14, 0xFF, 0x00 }, - { 0x15, 0xFF, 0x00 }, - { 0x16, 0xFF, 0x00 }, - { 0x17, 0xFF, 0x00 }, - { 0x18, 0xFF, 0xFF }, - { 0x19, 0xFF, 0xFF }, - - { 0 } - }; - -#if 0 - /* - * We need a PCMCIA flag. - */ - if ((cf->cf_flags & FE_FLAGS_PCMCIA) == 0) - return (0); -#endif - - /* - * We need explicit IRQ and supported address. - */ - if (ia->ia_irq == IRQUNK || (iobase & ~0x3E0) != 0) - return (0); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: top of fe_probe_mbh()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* - * See if MBH10302 is on its address. - * I'm not sure the following probe code works. FIXME. - */ - if (!fe_simple_probe(iobase, probe_table)) - return (0); - - /* Determine the card type. */ - sc->type = FE_TYPE_MBH10302; - sc->typestr = "MBH10302 (PCMCIA)"; - - /* - * Initialize constants in the per-line structure. - */ - - /* Get our station address from EEPROM. */ - inblk(iobase + FE_MBH10, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Make sure we got a valid station address. */ - if ((sc->sc_enaddr[0] & 0x03) != 0x00 - || (sc->sc_enaddr[0] == 0x00 - && sc->sc_enaddr[1] == 0x00 - && sc->sc_enaddr[2] == 0x00)) - return (0); - - /* Should find all register prototypes here. FIXME. */ - sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL; - sc->proto_dlcr5 = 0; - sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE; - sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO; - - /* - * Program the 86960 as follows: - * SRAM: 32KB, 100ns, byte-wide access. - * Transmission buffer: 4KB x 2. - * System bus interface: 16 bits. - * We cannot change these values but TXBSIZE, because they - * are hard-wired on the board. Modifying TXBSIZE will affect - * the driver performance. - */ - sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB - | FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns; - - /* Setup hooks. We need a special initialization procedure. */ - sc->init = fe_init_mbh; - - /* - * Minimum initialization. - */ - - /* Wait for a while. I'm not sure this is necessary. FIXME. */ - delay(200); - - /* Minimul initialization of 86960. */ - outb(iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); - delay(200); - - /* Disable all interrupts. */ - outb(iobase + FE_DLCR2, 0); - outb(iobase + FE_DLCR3, 0); - -#if 1 /* FIXME. */ - /* Initialize system bus interface and encoder/decoder operation. */ - outb(iobase + FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_DISABLE); -#endif - - /* - * That's all. MBH10302 occupies 32 I/O addresses, by the way. - */ - ia->ia_iosize = 32; - ia->ia_msize = 0; - return (1); -} - -/* MBH specific initialization routine. */ -void -fe_init_mbh(sc) - struct fe_softc *sc; -{ - - /* Probably required after hot-insertion... */ - - /* Wait for a while. I'm not sure this is necessary. FIXME. */ - delay(200); - - /* Minimul initialization of 86960. */ - outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); - delay(200); - - /* Disable all interrupts. */ - outb(sc->sc_iobase + FE_DLCR2, 0); - outb(sc->sc_iobase + FE_DLCR3, 0); - - /* Enable master interrupt flag. */ - outb(sc->sc_iobase + FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE); -} - -/* - * Install interface into kernel networking data structures - */ -void -feattach(parent, self, aux) - struct device *parent, *self; - void *aux; -{ - struct fe_softc *sc = (void *)self; - struct isa_attach_args *ia = aux; - struct cfdata *cf = sc->sc_dev.dv_cfdata; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - - /* Stop the 86960. */ - fe_stop(sc); - - /* Initialize ifnet structure. */ - bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - ifp->if_softc = sc; - ifp->if_start = fe_start; - ifp->if_ioctl = fe_ioctl; - ifp->if_watchdog = fe_watchdog; - ifp->if_flags = - IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; - IFQ_SET_READY(&ifp->if_snd); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: feattach()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - -#if FE_SINGLE_TRANSMISSION - /* Override txb config to allocate minimum. */ - sc->proto_dlcr6 &= ~FE_D6_TXBSIZ - sc->proto_dlcr6 |= FE_D6_TXBSIZ_2x2KB; -#endif - - /* Modify hardware config if it is requested. */ - if ((cf->cf_flags & FE_FLAGS_OVERRIDE_DLCR6) != 0) - sc->proto_dlcr6 = cf->cf_flags & FE_FLAGS_DLCR6_VALUE; - - /* Find TX buffer size, based on the hardware dependent proto. */ - switch (sc->proto_dlcr6 & FE_D6_TXBSIZ) { - case FE_D6_TXBSIZ_2x2KB: - sc->txb_size = 2048; - break; - case FE_D6_TXBSIZ_2x4KB: - sc->txb_size = 4096; - break; - case FE_D6_TXBSIZ_2x8KB: - sc->txb_size = 8192; - break; - default: - /* Oops, we can't work with single buffer configuration. */ -#if FE_DEBUG >= 2 - log(LOG_WARNING, "%s: strange TXBSIZ config; fixing\n", - sc->sc_dev.dv_xname); -#endif - sc->proto_dlcr6 &= ~FE_D6_TXBSIZ; - sc->proto_dlcr6 |= FE_D6_TXBSIZ_2x2KB; - sc->txb_size = 2048; - break; - } - - /* Attach the interface. */ - if_attach(ifp); - ether_ifattach(ifp); - - /* Print additional info when attached. */ - printf(": address %s, type %s\n", - ether_sprintf(sc->sc_arpcom.ac_enaddr), sc->typestr); -#if FE_DEBUG >= 3 - { - int buf, txb, bbw, sbw, ram; - - buf = txb = bbw = sbw = ram = -1; - switch (sc->proto_dlcr6 & FE_D6_BUFSIZ) { - case FE_D6_BUFSIZ_8KB: - buf = 8; - break; - case FE_D6_BUFSIZ_16KB: - buf = 16; - break; - case FE_D6_BUFSIZ_32KB: - buf = 32; - break; - case FE_D6_BUFSIZ_64KB: - buf = 64; - break; - } - switch (sc->proto_dlcr6 & FE_D6_TXBSIZ) { - case FE_D6_TXBSIZ_2x2KB: - txb = 2; - break; - case FE_D6_TXBSIZ_2x4KB: - txb = 4; - break; - case FE_D6_TXBSIZ_2x8KB: - txb = 8; - break; - } - switch (sc->proto_dlcr6 & FE_D6_BBW) { - case FE_D6_BBW_BYTE: - bbw = 8; - break; - case FE_D6_BBW_WORD: - bbw = 16; - break; - } - switch (sc->proto_dlcr6 & FE_D6_SBW) { - case FE_D6_SBW_BYTE: - sbw = 8; - break; - case FE_D6_SBW_WORD: - sbw = 16; - break; - } - switch (sc->proto_dlcr6 & FE_D6_SRAM) { - case FE_D6_SRAM_100ns: - ram = 100; - break; - case FE_D6_SRAM_150ns: - ram = 150; - break; - } - printf("%s: SRAM %dKB %dbit %dns, TXB %dKBx2, %dbit I/O\n", - sc->sc_dev.dv_xname, buf, bbw, ram, txb, sbw); - } -#endif - - sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, - IPL_NET, feintr, sc, sc->sc_dev.dv_xname); -} - -/* - * Reset interface. - */ -void -fe_reset(sc) - struct fe_softc *sc; -{ - int s; - - s = splnet(); - fe_stop(sc); - fe_init(sc); - splx(s); -} - -/* - * Stop everything on the interface. - * - * All buffered packets, both transmitting and receiving, - * if any, will be lost by stopping the interface. - */ -void -fe_stop(sc) - struct fe_softc *sc; -{ - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: top of fe_stop()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* Disable interrupts. */ - outb(sc->sc_iobase + FE_DLCR2, 0x00); - outb(sc->sc_iobase + FE_DLCR3, 0x00); - - /* Stop interface hardware. */ - delay(200); - outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); - delay(200); - - /* Clear all interrupt status. */ - outb(sc->sc_iobase + FE_DLCR0, 0xFF); - outb(sc->sc_iobase + FE_DLCR1, 0xFF); - - /* Put the chip in stand-by mode. */ - delay(200); - outb(sc->sc_iobase + FE_DLCR7, sc->proto_dlcr7 | FE_D7_POWER_DOWN); - delay(200); - - /* MAR loading can be delayed. */ - sc->filter_change = 0; - - /* Call a hook. */ - if (sc->stop) - sc->stop(sc); - -#if DEBUG >= 3 - log(LOG_INFO, "%s: end of fe_stop()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif -} - -/* - * Device timeout/watchdog routine. Entered if the device neglects to - * generate an interrupt after a transmit has been started on it. - */ -void -fe_watchdog(ifp) - struct ifnet *ifp; -{ - struct fe_softc *sc = ifp->if_softc; - - log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); -#if FE_DEBUG >= 3 - fe_dump(LOG_INFO, sc); -#endif - - /* Record how many packets are lost by this accident. */ - sc->sc_arpcom.ac_if.if_oerrors += sc->txb_sched + sc->txb_count; - - fe_reset(sc); -} - -/* - * Drop (skip) a packet from receive buffer in 86960 memory. - */ -static inline void -fe_droppacket(sc) - struct fe_softc *sc; -{ - - outb(sc->sc_iobase + FE_BMPR14, FE_B14_FILTER | FE_B14_SKIP); -} - -/* - * Initialize device. - */ -void -fe_init(sc) - struct fe_softc *sc; -{ - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - int i; - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: top of fe_init()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* Reset transmitter flags. */ - ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_timer = 0; - - sc->txb_free = sc->txb_size; - sc->txb_count = 0; - sc->txb_sched = 0; - - /* Call a hook. */ - if (sc->init) - sc->init(sc); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: after init hook\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* - * Make sure to disable the chip, also. - * This may also help re-programming the chip after - * hot insertion of PCMCIAs. - */ - outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); - - /* Power up the chip and select register bank for DLCRs. */ - delay(200); - outb(sc->sc_iobase + FE_DLCR7, - sc->proto_dlcr7 | FE_D7_RBS_DLCR | FE_D7_POWER_UP); - delay(200); - - /* Feed the station address. */ - outblk(sc->sc_iobase + FE_DLCR8, sc->sc_enaddr, ETHER_ADDR_LEN); - - /* Select the BMPR bank for runtime register access. */ - outb(sc->sc_iobase + FE_DLCR7, - sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP); - - /* Initialize registers. */ - outb(sc->sc_iobase + FE_DLCR0, 0xFF); /* Clear all bits. */ - outb(sc->sc_iobase + FE_DLCR1, 0xFF); /* ditto. */ - outb(sc->sc_iobase + FE_DLCR2, 0x00); - outb(sc->sc_iobase + FE_DLCR3, 0x00); - outb(sc->sc_iobase + FE_DLCR4, sc->proto_dlcr4); - outb(sc->sc_iobase + FE_DLCR5, sc->proto_dlcr5); - outb(sc->sc_iobase + FE_BMPR10, 0x00); - outb(sc->sc_iobase + FE_BMPR11, FE_B11_CTRL_SKIP); - outb(sc->sc_iobase + FE_BMPR12, 0x00); - outb(sc->sc_iobase + FE_BMPR13, sc->proto_bmpr13); - outb(sc->sc_iobase + FE_BMPR14, FE_B14_FILTER); - outb(sc->sc_iobase + FE_BMPR15, 0x00); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: just before enabling DLC\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* Enable interrupts. */ - outb(sc->sc_iobase + FE_DLCR2, FE_TMASK); - outb(sc->sc_iobase + FE_DLCR3, FE_RMASK); - - /* Enable transmitter and receiver. */ - delay(200); - outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_ENABLE); - delay(200); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: just after enabling DLC\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* - * Make sure to empty the receive buffer. - * - * This may be redundant, but *if* the receive buffer were full - * at this point, the driver would hang. I have experienced - * some strange hangups just after UP. I hope the following - * code solve the problem. - * - * I have changed the order of hardware initialization. - * I think the receive buffer cannot have any packets at this - * point in this version. The following code *must* be - * redundant now. FIXME. - */ - for (i = 0; i < FE_MAX_RECV_COUNT; i++) { - if (inb(sc->sc_iobase + FE_DLCR5) & FE_D5_BUFEMP) - break; - fe_droppacket(sc); - } -#if FE_DEBUG >= 1 - if (i >= FE_MAX_RECV_COUNT) { - log(LOG_ERR, "%s: cannot empty receive buffer\n", - sc->sc_dev.dv_xname); - } -#endif -#if FE_DEBUG >= 3 - if (i < FE_MAX_RECV_COUNT) { - log(LOG_INFO, "%s: receive buffer emptied (%d)\n", - sc->sc_dev.dv_xname, i); - } -#endif - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: after ERB loop\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* Do we need this here? */ - outb(sc->sc_iobase + FE_DLCR0, 0xFF); /* Clear all bits. */ - outb(sc->sc_iobase + FE_DLCR1, 0xFF); /* ditto. */ - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: after FIXME\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* Set 'running' flag. */ - ifp->if_flags |= IFF_RUNNING; - - /* - * At this point, the interface is runnung properly, - * except that it receives *no* packets. we then call - * fe_setmode() to tell the chip what packets to be - * received, based on the if_flags and multicast group - * list. It completes the initialization process. - */ - fe_setmode(sc); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: after setmode\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* ...and attempt to start output. */ - fe_start(ifp); - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: end of fe_init()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif -} - -/* - * This routine actually starts the transmission on the interface - */ -static inline void -fe_xmit(sc) - struct fe_softc *sc; -{ - - /* - * Set a timer just in case we never hear from the board again. - * We use longer timeout for multiple packet transmission. - * I'm not sure this timer value is appropriate. FIXME. - */ - sc->sc_arpcom.ac_if.if_timer = 1 + sc->txb_count; - - /* Update txb variables. */ - sc->txb_sched = sc->txb_count; - sc->txb_count = 0; - sc->txb_free = sc->txb_size; - -#if FE_DELAYED_PADDING - /* Omit the postponed padding process. */ - sc->txb_padding = 0; -#endif - - /* Start transmitter, passing packets in TX buffer. */ - outb(sc->sc_iobase + FE_BMPR10, sc->txb_sched | FE_B10_START); -} - -/* - * Start output on interface. - * We make two assumptions here: - * 1) that the current priority is set to splnet _before_ this code - * is called *and* is returned to the appropriate priority after - * return - * 2) that the IFF_OACTIVE flag is checked before this code is called - * (i.e. that the output part of the interface is idle) - */ -void -fe_start(ifp) - struct ifnet *ifp; -{ - struct fe_softc *sc = ifp->if_softc; - struct mbuf *m; - -#if FE_DEBUG >= 1 - /* Just a sanity check. */ - if ((sc->txb_count == 0) != (sc->txb_free == sc->txb_size)) { - /* - * Txb_count and txb_free co-works to manage the - * transmission buffer. Txb_count keeps track of the - * used potion of the buffer, while txb_free does unused - * potion. So, as long as the driver runs properly, - * txb_count is zero if and only if txb_free is same - * as txb_size (which represents whole buffer.) - */ - log(LOG_ERR, "%s: inconsistent txb variables (%d, %d)\n", - sc->sc_dev.dv_xname, sc->txb_count, sc->txb_free); - /* - * So, what should I do, then? - * - * We now know txb_count and txb_free contradicts. We - * cannot, however, tell which is wrong. More - * over, we cannot peek 86960 transmission buffer or - * reset the transmission buffer. (In fact, we can - * reset the entire interface. I don't want to do it.) - * - * If txb_count is incorrect, leaving it as is will cause - * sending of garbage after next interrupt. We have to - * avoid it. Hence, we reset the txb_count here. If - * txb_free was incorrect, resetting txb_count just loses - * some packets. We can live with it. - */ - sc->txb_count = 0; - } -#endif - -#if FE_DEBUG >= 1 - /* - * First, see if there are buffered packets and an idle - * transmitter - should never happen at this point. - */ - if ((sc->txb_count > 0) && (sc->txb_sched == 0)) { - log(LOG_ERR, "%s: transmitter idle with %d buffered packets\n", - sc->sc_dev.dv_xname, sc->txb_count); - fe_xmit(sc); - } -#endif - - /* - * Stop accepting more transmission packets temporarily, when - * a filter change request is delayed. Updating the MARs on - * 86960 flushes the transmisstion buffer, so it is delayed - * until all buffered transmission packets have been sent - * out. - */ - if (sc->filter_change) { - /* - * Filter change requst is delayed only when the DLC is - * working. DLC soon raise an interrupt after finishing - * the work. - */ - goto indicate_active; - } - - for (;;) { - /* - * See if there is room to put another packet in the buffer. - * We *could* do better job by peeking the send queue to - * know the length of the next packet. Current version just - * tests against the worst case (i.e., longest packet). FIXME. - * - * When adding the packet-peek feature, don't forget adding a - * test on txb_count against QUEUEING_MAX. - * There is a little chance the packet count exceeds - * the limit. Assume transmission buffer is 8KB (2x8KB - * configuration) and an application sends a bunch of small - * (i.e., minimum packet sized) packets rapidly. An 8KB - * buffer can hold 130 blocks of 62 bytes long... - */ - if (sc->txb_free < ETHER_MAX_LEN + FE_DATA_LEN_LEN) { - /* No room. */ - goto indicate_active; - } - -#if FE_SINGLE_TRANSMISSION - if (sc->txb_count > 0) { - /* Just one packet per a transmission buffer. */ - goto indicate_active; - } -#endif - - /* - * Get the next mbuf chain for a packet to send. - */ - IFQ_DEQUEUE(&ifp->if_snd, m); - if (m == 0) { - /* No more packets to send. */ - goto indicate_inactive; - } - -#if NBPFILTER > 0 - /* Tap off here if there is a BPF listener. */ - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); -#endif - - /* - * Copy the mbuf chain into the transmission buffer. - * txb_* variables are updated as necessary. - */ - fe_write_mbufs(sc, m); - - m_freem(m); - - /* Start transmitter if it's idle. */ - if (sc->txb_sched == 0) - fe_xmit(sc); - } - -indicate_inactive: - /* - * We are using the !OACTIVE flag to indicate to - * the outside world that we can accept an - * additional packet rather than that the - * transmitter is _actually_ active. Indeed, the - * transmitter may be active, but if we haven't - * filled all the buffers with data then we still - * want to accept more. - */ - ifp->if_flags &= ~IFF_OACTIVE; - return; - -indicate_active: - /* - * The transmitter is active, and there are no room for - * more outgoing packets in the transmission buffer. - */ - ifp->if_flags |= IFF_OACTIVE; - return; -} - -/* - * Transmission interrupt handler - * The control flow of this function looks silly. FIXME. - */ -void -fe_tint(sc, tstat) - struct fe_softc *sc; - u_char tstat; -{ - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - int left; - int col; - - /* - * Handle "excessive collision" interrupt. - */ - if (tstat & FE_D0_COLL16) { - /* - * Find how many packets (including this collided one) - * are left unsent in transmission buffer. - */ - left = inb(sc->sc_iobase + FE_BMPR10); - -#if FE_DEBUG >= 2 - log(LOG_WARNING, "%s: excessive collision (%d/%d)\n", - sc->sc_dev.dv_xname, left, sc->txb_sched); -#endif -#if FE_DEBUG >= 3 - fe_dump(LOG_INFO, sc); -#endif - - /* - * Update statistics. - */ - ifp->if_collisions += 16; - ifp->if_oerrors++; - ifp->if_opackets += sc->txb_sched - left; - - /* - * Collision statistics has been updated. - * Clear the collision flag on 86960 now to avoid confusion. - */ - outb(sc->sc_iobase + FE_DLCR0, FE_D0_COLLID); - - /* - * Restart transmitter, skipping the - * collided packet. - * - * We *must* skip the packet to keep network running - * properly. Excessive collision error is an - * indication of the network overload. If we - * tried sending the same packet after excessive - * collision, the network would be filled with - * out-of-time packets. Packets belonging - * to reliable transport (such as TCP) are resent - * by some upper layer. - */ - outb(sc->sc_iobase + FE_BMPR11, - FE_B11_CTRL_SKIP | FE_B11_MODE1); - sc->txb_sched = left - 1; - } - - /* - * Handle "transmission complete" interrupt. - */ - if (tstat & FE_D0_TXDONE) { - /* - * Add in total number of collisions on last - * transmission. We also clear "collision occurred" flag - * here. - * - * 86960 has a design flow on collision count on multiple - * packet transmission. When we send two or more packets - * with one start command (that's what we do when the - * transmission queue is clauded), 86960 informs us number - * of collisions occurred on the last packet on the - * transmission only. Number of collisions on previous - * packets are lost. I have told that the fact is clearly - * stated in the Fujitsu document. - * - * I considered not to mind it seriously. Collision - * count is not so important, anyway. Any comments? FIXME. - */ - - if (inb(sc->sc_iobase + FE_DLCR0) & FE_D0_COLLID) { - /* Clear collision flag. */ - outb(sc->sc_iobase + FE_DLCR0, FE_D0_COLLID); - - /* Extract collision count from 86960. */ - col = inb(sc->sc_iobase + FE_DLCR4) & FE_D4_COL; - if (col == 0) { - /* - * Status register indicates collisions, - * while the collision count is zero. - * This can happen after multiple packet - * transmission, indicating that one or more - * previous packet(s) had been collided. - * - * Since the accurate number of collisions - * has been lost, we just guess it as 1; - * Am I too optimistic? FIXME. - */ - col = 1; - } else - col >>= FE_D4_COL_SHIFT; - ifp->if_collisions += col; -#if FE_DEBUG >= 4 - log(LOG_WARNING, "%s: %d collision%s (%d)\n", - sc->sc_dev.dv_xname, col, col == 1 ? "" : "s", - sc->txb_sched); -#endif - } - - /* - * Update total number of successfully - * transmitted packets. - */ - ifp->if_opackets += sc->txb_sched; - sc->txb_sched = 0; - } - - if (sc->txb_sched == 0) { - /* - * The transmitter is no more active. - * Reset output active flag and watchdog timer. - */ - ifp->if_flags &= ~IFF_OACTIVE; - ifp->if_timer = 0; - - /* - * If more data is ready to transmit in the buffer, start - * transmitting them. Otherwise keep transmitter idle, - * even if more data is queued. This gives receive - * process a slight priority. - */ - if (sc->txb_count > 0) - fe_xmit(sc); - } -} - -/* - * Ethernet interface receiver interrupt. - */ -void -fe_rint(sc, rstat) - struct fe_softc *sc; - u_char rstat; -{ - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - int len; - u_char status; - int i; - - /* - * Update statistics if this interrupt is caused by an error. - */ - if (rstat & (FE_D1_OVRFLO | FE_D1_CRCERR | - FE_D1_ALGERR | FE_D1_SRTPKT)) { -#if FE_DEBUG >= 3 - log(LOG_WARNING, "%s: receive error: %b\n", - sc->sc_dev.dv_xname, rstat, FE_D1_ERRBITS); -#endif - ifp->if_ierrors++; - } - - /* - * MB86960 has a flag indicating "receive queue empty." - * We just loop cheking the flag to pull out all received - * packets. - * - * We limit the number of iterrations to avoid infinite loop. - * It can be caused by a very slow CPU (some broken - * peripheral may insert incredible number of wait cycles) - * or, worse, by a broken MB86960 chip. - */ - for (i = 0; i < FE_MAX_RECV_COUNT; i++) { - /* Stop the iterration if 86960 indicates no packets. */ - if (inb(sc->sc_iobase + FE_DLCR5) & FE_D5_BUFEMP) - break; - - /* - * Extract A receive status byte. - * As our 86960 is in 16 bit bus access mode, we have to - * use inw() to get the status byte. The significant - * value is returned in lower 8 bits. - */ - status = (u_char)inw(sc->sc_iobase + FE_BMPR8); -#if FE_DEBUG >= 4 - log(LOG_INFO, "%s: receive status = %02x\n", - sc->sc_dev.dv_xname, status); -#endif - - /* - * If there was an error, update statistics and drop - * the packet, unless the interface is in promiscuous - * mode. - */ - if ((status & 0xF0) != 0x20) { /* XXXX ? */ - if ((ifp->if_flags & IFF_PROMISC) == 0) { - ifp->if_ierrors++; - fe_droppacket(sc); - continue; - } - } - - /* - * Extract the packet length. - * It is a sum of a header (14 bytes) and a payload. - * CRC has been stripped off by the 86960. - */ - len = inw(sc->sc_iobase + FE_BMPR8); - - /* - * MB86965 checks the packet length and drop big packet - * before passing it to us. There are no chance we can - * get [crufty] packets. Hence, if the length exceeds - * the specified limit, it means some serious failure, - * such as out-of-sync on receive buffer management. - * - * Is this statement true? FIXME. - */ - if (len > ETHER_MAX_LEN || len < ETHER_HDR_SIZE) { -#if FE_DEBUG >= 2 - log(LOG_WARNING, - "%s: received a %s packet? (%u bytes)\n", - sc->sc_dev.dv_xname, - len < ETHER_HDR_SIZE ? "partial" : "big", len); -#endif - ifp->if_ierrors++; - fe_droppacket(sc); - continue; - } - - /* - * Check for a short (RUNT) packet. We *do* check - * but do nothing other than print a message. - * Short packets are illegal, but does nothing bad - * if it carries data for upper layer. - */ -#if FE_DEBUG >= 2 - if (len < ETHER_MIN_LEN) { - log(LOG_WARNING, - "%s: received a short packet? (%u bytes)\n", - sc->sc_dev.dv_xname, len); - } -#endif - - /* - * Go get a packet. - */ - if (!fe_get_packet(sc, len)) { - /* Skip a packet, updating statistics. */ -#if FE_DEBUG >= 2 - log(LOG_WARNING, - "%s: out of mbufs; dropping packet (%u bytes)\n", - sc->sc_dev.dv_xname, len); -#endif - ifp->if_ierrors++; - fe_droppacket(sc); - - /* - * We stop receiving packets, even if there are - * more in the buffer. We hope we can get more - * mbufs next time. - */ - return; - } - - /* Successfully received a packet. Update stat. */ - ifp->if_ipackets++; - } -} - -/* - * Ethernet interface interrupt processor - */ -int -feintr(arg) - void *arg; -{ - struct fe_softc *sc = arg; - u_char tstat, rstat; - -#if FE_DEBUG >= 4 - log(LOG_INFO, "%s: feintr()\n", sc->sc_dev.dv_xname); - fe_dump(LOG_INFO, sc); -#endif - - /* - * Get interrupt conditions, masking unneeded flags. - */ - tstat = inb(sc->sc_iobase + FE_DLCR0) & FE_TMASK; - rstat = inb(sc->sc_iobase + FE_DLCR1) & FE_RMASK; - if (tstat == 0 && rstat == 0) - return (0); - - /* - * Loop until there are no more new interrupt conditions. - */ - for (;;) { - /* - * Reset the conditions we are acknowledging. - */ - outb(sc->sc_iobase + FE_DLCR0, tstat); - outb(sc->sc_iobase + FE_DLCR1, rstat); - - /* - * Handle transmitter interrupts. Handle these first because - * the receiver will reset the board under some conditions. - */ - if (tstat != 0) - fe_tint(sc, tstat); - - /* - * Handle receiver interrupts. - */ - if (rstat != 0) - fe_rint(sc, rstat); - - /* - * Update the multicast address filter if it is - * needed and possible. We do it now, because - * we can make sure the transmission buffer is empty, - * and there is a good chance that the receive queue - * is empty. It will minimize the possibility of - * packet lossage. - */ - if (sc->filter_change && - sc->txb_count == 0 && sc->txb_sched == 0) { - fe_loadmar(sc); - sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE; - } - - /* - * If it looks like the transmitter can take more data, - * attempt to start output on the interface. This is done - * after handling the receiver interrupt to give the - * receive operation priority. - */ - if ((sc->sc_arpcom.ac_if.if_flags & IFF_OACTIVE) == 0) - fe_start(&sc->sc_arpcom.ac_if); - - /* - * Get interrupt conditions, masking unneeded flags. - */ - tstat = inb(sc->sc_iobase + FE_DLCR0) & FE_TMASK; - rstat = inb(sc->sc_iobase + FE_DLCR1) & FE_RMASK; - if (tstat == 0 && rstat == 0) - return (1); - } -} - -/* - * Process an ioctl request. This code needs some work - it looks pretty ugly. - */ -int -fe_ioctl(ifp, command, data) - register struct ifnet *ifp; - u_long command; - caddr_t data; -{ - struct fe_softc *sc = ifp->if_softc; - register struct ifaddr *ifa = (struct ifaddr *)data; - struct ifreq *ifr = (struct ifreq *)data; - int s, error = 0; - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: ioctl(%x)\n", sc->sc_dev.dv_xname, command); -#endif - - s = splnet(); - - if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) { - splx(s); - return error; - } - - switch (command) { - - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - fe_init(sc); - arp_ifinit(&sc->sc_arpcom, ifa); - break; -#endif - default: - fe_init(sc); - break; - } - break; - - case SIOCSIFFLAGS: - if ((ifp->if_flags & IFF_UP) == 0 && - (ifp->if_flags & IFF_RUNNING) != 0) { - /* - * If interface is marked down and it is running, then - * stop it. - */ - fe_stop(sc); - ifp->if_flags &= ~IFF_RUNNING; - } else if ((ifp->if_flags & IFF_UP) != 0 && - (ifp->if_flags & IFF_RUNNING) == 0) { - /* - * If interface is marked up and it is stopped, then - * start it. - */ - fe_init(sc); - } else { - /* - * Reset the interface to pick up changes in any other - * flags that affect hardware registers. - */ - fe_setmode(sc); - } -#if DEBUG >= 1 - /* "ifconfig fe0 debug" to print register dump. */ - if (ifp->if_flags & IFF_DEBUG) { - log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n", sc->sc_dev.dv_xname); - fe_dump(LOG_DEBUG, sc); - } -#endif - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - /* Update our multicast list. */ - error = (command == SIOCADDMULTI) ? - ether_addmulti(ifr, &sc->sc_arpcom) : - ether_delmulti(ifr, &sc->sc_arpcom); - - if (error == ENETRESET) { - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - if (ifp->if_flags & IFF_RUNNING) - fe_setmode(sc); - error = 0; - } - break; - - default: - error = EINVAL; - } - - splx(s); - return (error); -} - -/* - * Retreive packet from receive buffer and send to the next level up via - * ether_input_mbuf(). If there is a BPF listener, give a copy to BPF, too. - * Returns 0 if success, -1 if error (i.e., mbuf allocation failure). - */ -int -fe_get_packet(sc, len) - struct fe_softc *sc; - int len; -{ - struct mbuf *m; - struct ifnet *ifp = &sc->sc_arpcom.ac_if; - - /* Allocate a header mbuf. */ - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == 0) - return (0); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = len; - - /* The following silliness is to make NFS happy. */ -#define EROUND ((sizeof(struct ether_header) + 3) & ~3) -#define EOFF (EROUND - sizeof(struct ether_header)) - - /* - * Our strategy has one more problem. There is a policy on - * mbuf cluster allocation. It says that we must have at - * least MINCLSIZE (208 bytes) to allocate a cluster. For a - * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2), - * our code violates the rule... - * On the other hand, the current code is short, simle, - * and fast, however. It does no harmful thing, just waists - * some memory. Any comments? FIXME. - */ - - /* Attach a cluster if this packet doesn't fit in a normal mbuf. */ - if (len > MHLEN - EOFF) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - m_freem(m); - return (0); - } - } - - /* - * The following assumes there is room for the ether header in the - * header mbuf. - */ - m->m_data += EOFF; - - /* Set the length of this packet. */ - m->m_len = len; - - /* Get a packet. */ - insw(sc->sc_iobase + FE_BMPR8, m->m_data, (len + 1) >> 1); - -#if NBPFILTER > 0 - /* - * Check if there's a BPF listener on this interface. If so, hand off - * the raw packet to bpf. - */ - if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); -#endif - - ether_input_mbuf(ifp, m); - return (1); -} - -/* - * Write an mbuf chain to the transmission buffer memory using 16 bit PIO. - * Returns number of bytes actually written, including length word. - * - * If an mbuf chain is too long for an Ethernet frame, it is not sent. - * Packets shorter than Ethernet minimum are legal, and we pad them - * before sending out. An exception is "partial" packets which are - * shorter than mandatory Ethernet header. - * - * I wrote a code for an experimental "delayed padding" technique. - * When employed, it postpones the padding process for short packets. - * If xmit() occurred at the moment, the padding process is omitted, and - * garbages are sent as pad data. If next packet is stored in the - * transmission buffer before xmit(), write_mbuf() pads the previous - * packet before transmitting new packet. This *may* gain the - * system performance (slightly). - */ -void -fe_write_mbufs(sc, m) - struct fe_softc *sc; - struct mbuf *m; -{ - int bmpr8 = sc->sc_iobase + FE_BMPR8; - struct mbuf *mp; - u_char *data; - u_short savebyte; /* WARNING: Architecture dependent! */ - int totlen, len, wantbyte; - -#if FE_DELAYED_PADDING - /* Do the "delayed padding." */ - len = sc->txb_padding >> 1; - if (len > 0) { - while (--len >= 0) - outw(bmpr8, 0); - sc->txb_padding = 0; - } -#endif - - /* We need to use m->m_pkthdr.len, so require the header */ - if ((m->m_flags & M_PKTHDR) == 0) - panic("fe_write_mbufs: no header mbuf"); - -#if FE_DEBUG >= 2 - /* First, count up the total number of bytes to copy. */ - for (totlen = 0, mp = m; mp != 0; mp = mp->m_next) - totlen += mp->m_len; - /* Check if this matches the one in the packet header. */ - if (totlen != m->m_pkthdr.len) - log(LOG_WARNING, "%s: packet length mismatch? (%d/%d)\n", - sc->sc_dev.dv_xname, totlen, m->m_pkthdr.len); -#else - /* Just use the length value in the packet header. */ - totlen = m->m_pkthdr.len; -#endif - -#if FE_DEBUG >= 1 - /* - * Should never send big packets. If such a packet is passed, - * it should be a bug of upper layer. We just ignore it. - * ... Partial (too short) packets, neither. - */ - if (totlen > ETHER_MAX_LEN || totlen < ETHER_HDR_SIZE) { - log(LOG_ERR, "%s: got a %s packet (%u bytes) to send\n", - sc->sc_dev.dv_xname, - totlen < ETHER_HDR_SIZE ? "partial" : "big", totlen); - sc->sc_arpcom.ac_if.if_oerrors++; - return; - } -#endif - - /* - * Put the length word for this frame. - * Does 86960 accept odd length? -- Yes. - * Do we need to pad the length to minimum size by ourselves? - * -- Generally yes. But for (or will be) the last - * packet in the transmission buffer, we can skip the - * padding process. It may gain performance slightly. FIXME. - */ - outw(bmpr8, max(totlen, ETHER_MIN_LEN)); - - /* - * Update buffer status now. - * Truncate the length up to an even number, since we use outw(). - */ - totlen = (totlen + 1) & ~1; - sc->txb_free -= FE_DATA_LEN_LEN + max(totlen, ETHER_MIN_LEN); - sc->txb_count++; - -#if FE_DELAYED_PADDING - /* Postpone the packet padding if necessary. */ - if (totlen < ETHER_MIN_LEN) - sc->txb_padding = ETHER_MIN_LEN - totlen; -#endif - - /* - * Transfer the data from mbuf chain to the transmission buffer. - * MB86960 seems to require that data be transferred as words, and - * only words. So that we require some extra code to patch - * over odd-length mbufs. - */ - wantbyte = 0; - for (; m != 0; m = m->m_next) { - /* Ignore empty mbuf. */ - len = m->m_len; - if (len == 0) - continue; - - /* Find the actual data to send. */ - data = mtod(m, caddr_t); - - /* Finish the last byte. */ - if (wantbyte) { - outw(bmpr8, savebyte | (*data << 8)); - data++; - len--; - wantbyte = 0; - } - - /* Output contiguous words. */ - if (len > 1) - outsw(bmpr8, data, len >> 1); - - /* Save remaining byte, if there is one. */ - if (len & 1) { - data += len & ~1; - savebyte = *data; - wantbyte = 1; - } - } - - /* Spit the last byte, if the length is odd. */ - if (wantbyte) - outw(bmpr8, savebyte); - -#if ! FE_DELAYED_PADDING - /* - * Pad the packet to the minimum length if necessary. - */ - len = (ETHER_MIN_LEN >> 1) - (totlen >> 1); - while (--len >= 0) - outw(bmpr8, 0); -#endif -} - -/* - * Compute the multicast address filter from the - * list of multicast addresses we need to listen to. - */ -void -fe_getmcaf(ac, af) - struct arpcom *ac; - u_char *af; -{ - struct ifnet *ifp = &ac->ac_if; - struct ether_multi *enm; - register u_char *cp, c; - register u_long crc; - register int i, len; - struct ether_multistep step; - - /* - * Set up multicast address filter by passing all multicast addresses - * through a crc generator, and then using the high order 6 bits as an - * index into the 64 bit logical address filter. The high order bit - * selects the word, while the rest of the bits select the bit within - * the word. - */ - - if ((ifp->if_flags & IFF_PROMISC) != 0) - goto allmulti; - - af[0] = af[1] = af[2] = af[3] = af[4] = af[5] = af[6] = af[7] = 0x00; - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, - sizeof(enm->enm_addrlo)) != 0) { - /* - * We must listen to a range of multicast addresses. - * For now, just accept all multicasts, rather than - * trying to set only those filter bits needed to match - * the range. (At this time, the only use of address - * ranges is for IP multicast routing, for which the - * range is big enough to require all bits set.) - */ - goto allmulti; - } - - cp = enm->enm_addrlo; - crc = 0xffffffff; - for (len = sizeof(enm->enm_addrlo); --len >= 0;) { - c = *cp++; - for (i = 8; --i >= 0;) { - if ((crc & 0x01) ^ (c & 0x01)) { - crc >>= 1; - crc ^= 0xedb88320; - } else - crc >>= 1; - c >>= 1; - } - } - /* Just want the 6 most significant bits. */ - crc >>= 26; - - /* Turn on the corresponding bit in the filter. */ - af[crc >> 3] |= 1 << (crc & 7); - - ETHER_NEXT_MULTI(step, enm); - } - ifp->if_flags &= ~IFF_ALLMULTI; - return; - -allmulti: - ifp->if_flags |= IFF_ALLMULTI; - af[0] = af[1] = af[2] = af[3] = af[4] = af[5] = af[6] = af[7] = 0xff; -} - -/* - * Calculate a new "multicast packet filter" and put the 86960 - * receiver in appropriate mode. - */ -void -fe_setmode(sc) - struct fe_softc *sc; -{ - int flags = sc->sc_arpcom.ac_if.if_flags; - - /* - * If the interface is not running, we postpone the update - * process for receive modes and multicast address filter - * until the interface is restarted. It reduces some - * complicated job on maintaining chip states. (Earlier versions - * of this driver had a bug on that point...) - * - * To complete the trick, fe_init() calls fe_setmode() after - * restarting the interface. - */ - if ((flags & IFF_RUNNING) == 0) - return; - - /* - * Promiscuous mode is handled separately. - */ - if ((flags & IFF_PROMISC) != 0) { - /* - * Program 86960 to receive all packets on the segment - * including those directed to other stations. - * Multicast filter stored in MARs are ignored - * under this setting, so we don't need to update it. - * - * Promiscuous mode is used solely by BPF, and BPF only - * listens to valid (no error) packets. So, we ignore - * errornous ones even in this mode. - */ - outb(sc->sc_iobase + FE_DLCR5, - sc->proto_dlcr5 | FE_D5_AFM0 | FE_D5_AFM1); - sc->filter_change = 0; - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: promiscuous mode\n", sc->sc_dev.dv_xname); -#endif - return; - } - - /* - * Turn the chip to the normal (non-promiscuous) mode. - */ - outb(sc->sc_iobase + FE_DLCR5, sc->proto_dlcr5 | FE_D5_AFM1); - - /* - * Find the new multicast filter value. - */ - fe_getmcaf(&sc->sc_arpcom, sc->filter); - sc->filter_change = 1; - -#if FE_DEBUG >= 3 - log(LOG_INFO, - "%s: address filter: [%02x %02x %02x %02x %02x %02x %02x %02x]\n", - sc->sc_dev.dv_xname, - sc->filter[0], sc->filter[1], sc->filter[2], sc->filter[3], - sc->filter[4], sc->filter[5], sc->filter[6], sc->filter[7]); -#endif - - /* - * We have to update the multicast filter in the 86960, A.S.A.P. - * - * Note that the DLC (Data Linc Control unit, i.e. transmitter - * and receiver) must be stopped when feeding the filter, and - * DLC trushes all packets in both transmission and receive - * buffers when stopped. - * - * ... Are the above sentenses correct? I have to check the - * manual of the MB86960A. FIXME. - * - * To reduce the packet lossage, we delay the filter update - * process until buffers are empty. - */ - if (sc->txb_sched == 0 && sc->txb_count == 0 && - (inb(sc->sc_iobase + FE_DLCR1) & FE_D1_PKTRDY) == 0) { - /* - * Buffers are (apparently) empty. Load - * the new filter value into MARs now. - */ - fe_loadmar(sc); - } else { - /* - * Buffers are not empty. Mark that we have to update - * the MARs. The new filter will be loaded by feintr() - * later. - */ -#if FE_DEBUG >= 4 - log(LOG_INFO, "%s: filter change delayed\n", sc->sc_dev.dv_xname); -#endif - } -} - -/* - * Load a new multicast address filter into MARs. - * - * The caller must have splnet'ed befor fe_loadmar. - * This function starts the DLC upon return. So it can be called only - * when the chip is working, i.e., from the driver's point of view, when - * a device is RUNNING. (I mistook the point in previous versions.) - */ -void -fe_loadmar(sc) - struct fe_softc *sc; -{ - - /* Stop the DLC (transmitter and receiver). */ - outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE); - - /* Select register bank 1 for MARs. */ - outb(sc->sc_iobase + FE_DLCR7, - sc->proto_dlcr7 | FE_D7_RBS_MAR | FE_D7_POWER_UP); - - /* Copy filter value into the registers. */ - outblk(sc->sc_iobase + FE_MAR8, sc->filter, FE_FILTER_LEN); - - /* Restore the bank selection for BMPRs (i.e., runtime registers). */ - outb(sc->sc_iobase + FE_DLCR7, - sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP); - - /* Restart the DLC. */ - outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_ENABLE); - - /* We have just updated the filter. */ - sc->filter_change = 0; - -#if FE_DEBUG >= 3 - log(LOG_INFO, "%s: address filter changed\n", sc->sc_dev.dv_xname); -#endif -} - -#if FE_DEBUG >= 1 -void -fe_dump(level, sc) - int level; - struct fe_softc *sc; -{ - int iobase = sc->sc_iobase; - u_char save_dlcr7; - - save_dlcr7 = inb(iobase + FE_DLCR7); - - log(level, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x %02x", - inb(iobase + FE_DLCR0), inb(iobase + FE_DLCR1), - inb(iobase + FE_DLCR2), inb(iobase + FE_DLCR3), - inb(iobase + FE_DLCR4), inb(iobase + FE_DLCR5), - inb(iobase + FE_DLCR6), inb(iobase + FE_DLCR7)); - - outb(iobase + FE_DLCR7, (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_DLCR); - log(level, "\t %02x %02x %02x %02x %02x %02x %02x %02x,", - inb(iobase + FE_DLCR8), inb(iobase + FE_DLCR9), - inb(iobase + FE_DLCR10), inb(iobase + FE_DLCR11), - inb(iobase + FE_DLCR12), inb(iobase + FE_DLCR13), - inb(iobase + FE_DLCR14), inb(iobase + FE_DLCR15)); - - outb(iobase + FE_DLCR7, (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_MAR); - log(level, "\tMAR = %02x %02x %02x %02x %02x %02x %02x %02x,", - inb(iobase + FE_MAR8), inb(iobase + FE_MAR9), - inb(iobase + FE_MAR10), inb(iobase + FE_MAR11), - inb(iobase + FE_MAR12), inb(iobase + FE_MAR13), - inb(iobase + FE_MAR14), inb(iobase + FE_MAR15)); - - outb(iobase + FE_DLCR7, (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_BMPR); - log(level, "\tBMPR = xx xx %02x %02x %02x %02x %02x %02x %02x %02x xx %02x.", - inb(iobase + FE_BMPR10), inb(iobase + FE_BMPR11), - inb(iobase + FE_BMPR12), inb(iobase + FE_BMPR13), - inb(iobase + FE_BMPR14), inb(iobase + FE_BMPR15), - inb(iobase + FE_BMPR16), inb(iobase + FE_BMPR17), - inb(iobase + FE_BMPR19)); - - outb(iobase + FE_DLCR7, save_dlcr7); -} -#endif diff --git a/sys/dev/isa/if_fereg.h b/sys/dev/isa/if_fereg.h deleted file mode 100644 index b09f09497f1..00000000000 --- a/sys/dev/isa/if_fereg.h +++ /dev/null @@ -1,114 +0,0 @@ -/* $OpenBSD: if_fereg.h,v 1.2 1997/11/07 08:06:55 niklas Exp $ */ - -/* - * All Rights Reserved, Copyright (C) Fujitsu Limited 1995 - * - * This software may be used, modified, copied, distributed, and sold, - * in both source and binary form provided that the above copyright, - * these terms and the following disclaimer are retained. The name of - * the author and/or the contributor may not be used to endorse or - * promote products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#define FE_REG_VERSION "if_fereg.h ver. 0.8" - -/* - * Hardware specification of various 86960/86965 based Ethernet cards. - * Contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp> - */ - -/* - * Registers on FMV-180 series' ISA bus interface ASIC. - * I'm not sure the following register names are appropriate. - * Doesn't it look silly, eh? FIXME. - */ - -#define FE_FMV0 16 /* Hardware status. */ -#define FE_FMV1 17 /* Hardrare type? Always 0 */ -#define FE_FMV2 18 /* Hardware configuration. */ -#define FE_FMV3 19 /* Hardware enable. */ -#define FE_FMV4 20 /* Station address #1 */ -#define FE_FMV5 21 /* Station address #2 */ -#define FE_FMV6 22 /* Station address #3 */ -#define FE_FMV7 23 /* Station address #4 */ -#define FE_FMV8 24 /* Station address #5 */ -#define FE_FMV9 25 /* Station address #6 */ -#define FE_FMV10 26 /* Unknown; to be set to 0. */ - -/* - * FMV-180 series' ASIC register values. - */ - -/* Magic value in FMV0 register. */ -#define FE_FMV0_MAGIC_MASK 0x78 -#define FE_FMV0_MAGIC_VALUE 0x50 - -/* Model identification. */ -#define FE_FMV0_MODEL 0x07 -#define FE_FMV0_MODEL_FMV181 0x05 -#define FE_FMV0_MODEL_FMV182 0x03 - -/* Card type ID? Always 0? */ -#define FE_FMV1_CARDID_MASK 0xFF -#define FE_FMV1_CARDID_ID 0x00 - -/* I/O port address assignment. */ -#define FE_FMV2_ADDR 0x07 -#define FE_FMV2_ADDR_SHIFT 0 - -/* Boot ROM address assignment. */ -#define FE_FMV2_ROM 0x38 -#define FE_FMV2_ROM_SHIFT 3 - -/* IRQ assignment. */ -#define FE_FMV2_IRQ 0xC0 -#define FE_FMV2_IRQ_SHIFT 6 - -/* Hardware(?) enable flag. */ -#define FE_FMV3_ENABLE_FLAG 0x80 - -/* Extra bits in FMV3 register. Always 0? */ -#define FE_FMV3_EXTRA_MASK 0x7F -#define FE_FMV3_EXTRA_VALUE 0x00 - -/* - * EEPROM allocation of AT1700/RE2000. - */ -#define FE_ATI_EEP_ADDR 0x08 /* Station address. (8-13) */ -#define FE_ATI_EEP_MEDIA 0x18 /* Media type. */ -#define FE_ATI_EEP_MAGIC 0x19 /* XXX Magic. */ -#define FE_ATI_EEP_MODEL 0x1e /* Hardware type. */ -#define FE_ATI_EEP_REVISION 0x1f /* Hardware revision. */ - -#define FE_ATI_MODEL_AT1700T 0x00 -#define FE_ATI_MODEL_AT1700BT 0x01 -#define FE_ATI_MODEL_AT1700FT 0x02 -#define FE_ATI_MODEL_AT1700AT 0x03 - -/* - * Registers on MBH10302. - */ - -#define FE_MBH0 0x10 /* ??? Including interrupt. */ -#define FE_MBH1 0x11 /* ??? */ -#define FE_MBH10 0x1A /* Station address. (10 - 15) */ - -/* Values to be set in MBH0 register. */ -#define FE_MBH0_MAGIC 0x0D /* Just a magic constant? */ -#define FE_MBH0_INTR 0x10 /* Master interrupt control. */ - -#define FE_MBH0_INTR_ENABLE 0x10 /* Enable interrupts. */ -#define FE_MBH0_INTR_DISABLE 0x00 /* Disable interrupts. */ |