if_ate.c revision 1.19
11.19Sperry/*	$NetBSD: if_ate.c,v 1.19 1998/01/05 07:31:08 perry Exp $	*/
21.19Sperry
31.1Smycroft/*
41.1Smycroft * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
51.1Smycroft *
61.1Smycroft * This software may be used, modified, copied, distributed, and sold, in
71.1Smycroft * both source and binary form provided that the above copyright, these
81.1Smycroft * terms and the following disclaimer are retained.  The name of the author
91.1Smycroft * and/or the contributor may not be used to endorse or promote products
101.1Smycroft * derived from this software without specific prior written permission.
111.1Smycroft *
121.1Smycroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
131.1Smycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
141.1Smycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
151.1Smycroft * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
161.1Smycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
171.1Smycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
181.1Smycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
191.1Smycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
201.1Smycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
211.1Smycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
221.1Smycroft * SUCH DAMAGE.
231.1Smycroft */
241.1Smycroft
251.1Smycroft/*
261.1Smycroft * Portions copyright (C) 1993, David Greenman.  This software may be used,
271.1Smycroft * modified, copied, distributed, and sold, in both source and binary form
281.1Smycroft * provided that the above copyright and these terms are retained.  Under no
291.1Smycroft * circumstances is the author responsible for the proper functioning of this
301.1Smycroft * software, nor does the author assume any responsibility for damages
311.1Smycroft * incurred with its use.
321.1Smycroft */
331.1Smycroft
341.1Smycroft#define FE_VERSION "if_fe.c ver. 0.8"
351.1Smycroft
361.1Smycroft/*
371.1Smycroft * Device driver for Fujitsu MB86960A/MB86965A based Ethernet cards.
381.1Smycroft * Contributed by M.S. <seki@sysrap.cs.fujitsu.co.jp>
391.1Smycroft *
401.1Smycroft * This version is intended to be a generic template for various
411.1Smycroft * MB86960A/MB86965A based Ethernet cards.  It currently supports
421.1Smycroft * Fujitsu FMV-180 series (i.e., FMV-181 and FMV-182) and Allied-
431.1Smycroft * Telesis AT1700 series and RE2000 series.  There are some
441.1Smycroft * unnecessary hooks embedded, which are primarily intended to support
451.1Smycroft * other types of Ethernet cards, but the author is not sure whether
461.1Smycroft * they are useful.
471.1Smycroft */
481.1Smycroft
491.1Smycroft#include "bpfilter.h"
501.18Sexplorer#include "rnd.h"
511.1Smycroft
521.1Smycroft#include <sys/param.h>
531.1Smycroft#include <sys/systm.h>
541.1Smycroft#include <sys/errno.h>
551.1Smycroft#include <sys/ioctl.h>
561.1Smycroft#include <sys/mbuf.h>
571.1Smycroft#include <sys/socket.h>
581.1Smycroft#include <sys/syslog.h>
591.1Smycroft#include <sys/device.h>
601.18Sexplorer#if NRND > 0
611.18Sexplorer#include <sys/rnd.h>
621.18Sexplorer#endif
631.1Smycroft
641.1Smycroft#include <net/if.h>
651.1Smycroft#include <net/if_dl.h>
661.1Smycroft#include <net/if_types.h>
671.17Sis
681.17Sis#include <net/if_ether.h>
691.1Smycroft
701.1Smycroft#ifdef INET
711.1Smycroft#include <netinet/in.h>
721.1Smycroft#include <netinet/in_systm.h>
731.1Smycroft#include <netinet/in_var.h>
741.1Smycroft#include <netinet/ip.h>
751.17Sis#include <netinet/if_inarp.h>
761.1Smycroft#endif
771.1Smycroft
781.1Smycroft#ifdef NS
791.1Smycroft#include <netns/ns.h>
801.1Smycroft#include <netns/ns_if.h>
811.1Smycroft#endif
821.1Smycroft
831.1Smycroft#if NBPFILTER > 0
841.1Smycroft#include <net/bpf.h>
851.1Smycroft#include <net/bpfdesc.h>
861.1Smycroft#endif
871.1Smycroft
881.1Smycroft#include <machine/cpu.h>
891.13Smycroft#include <machine/intr.h>
901.1Smycroft#include <machine/pio.h>
911.1Smycroft
921.1Smycroft#include <dev/isa/isareg.h>
931.1Smycroft#include <dev/isa/isavar.h>
941.3Scgd#include <dev/ic/mb86960reg.h>
951.1Smycroft#include <dev/isa/if_fereg.h>
961.1Smycroft
971.1Smycroft/*
981.1Smycroft * Default settings for fe driver specific options.
991.1Smycroft * They can be set in config file by "options" statements.
1001.1Smycroft */
1011.1Smycroft
1021.1Smycroft/*
1031.1Smycroft * Debug control.
1041.1Smycroft * 0: No debug at all.  All debug specific codes are stripped off.
1051.1Smycroft * 1: Silent.  No debug messages are logged except emergent ones.
1061.1Smycroft * 2: Brief.  Lair events and/or important information are logged.
1071.1Smycroft * 3: Detailed.  Logs all information which *may* be useful for debugging.
1081.1Smycroft * 4: Trace.  All actions in the driver is logged.  Super verbose.
1091.1Smycroft */
1101.1Smycroft#ifndef FE_DEBUG
1111.1Smycroft#define FE_DEBUG		1
1121.1Smycroft#endif
1131.1Smycroft
1141.1Smycroft/*
1151.1Smycroft * Delay padding of short transmission packets to minimum Ethernet size.
1161.1Smycroft * This may or may not gain performance.  An EXPERIMENTAL option.
1171.1Smycroft */
1181.1Smycroft#ifndef FE_DELAYED_PADDING
1191.1Smycroft#define FE_DELAYED_PADDING	0
1201.1Smycroft#endif
1211.1Smycroft
1221.1Smycroft/*
1231.1Smycroft * Transmit just one packet per a "send" command to 86960.
1241.1Smycroft * This option is intended for performance test.  An EXPERIMENTAL option.
1251.1Smycroft */
1261.1Smycroft#ifndef FE_SINGLE_TRANSMISSION
1271.1Smycroft#define FE_SINGLE_TRANSMISSION	0
1281.1Smycroft#endif
1291.1Smycroft
1301.1Smycroft/*
1311.1Smycroft * Device configuration flags.
1321.1Smycroft */
1331.1Smycroft
1341.1Smycroft/* DLCR6 settings. */
1351.1Smycroft#define FE_FLAGS_DLCR6_VALUE	0x007F
1361.1Smycroft
1371.1Smycroft/* Force DLCR6 override. */
1381.1Smycroft#define FE_FLAGS_OVERRIDE_DLCR6	0x0080
1391.1Smycroft
1401.1Smycroft/* A cludge for PCMCIA support. */
1411.1Smycroft#define FE_FLAGS_PCMCIA		0x8000
1421.1Smycroft
1431.1Smycroft/* Identification of the driver version. */
1441.1Smycroftstatic char const fe_version[] = FE_VERSION " / " FE_REG_VERSION;
1451.1Smycroft
1461.1Smycroft/*
1471.1Smycroft * Supported hardware (Ethernet card) types
1481.1Smycroft * This information is currently used only for debugging
1491.1Smycroft */
1501.1Smycroftenum fe_type {
1511.1Smycroft	/* For cards which are successfully probed but not identified. */
1521.1Smycroft	FE_TYPE_UNKNOWN,
1531.1Smycroft
1541.1Smycroft	/* Fujitsu FMV-180 series. */
1551.1Smycroft	FE_TYPE_FMV181,
1561.1Smycroft	FE_TYPE_FMV182,
1571.1Smycroft
1581.1Smycroft	/* Allied-Telesis AT1700 series and RE2000 series. */
1591.1Smycroft	FE_TYPE_AT1700T,
1601.1Smycroft	FE_TYPE_AT1700BT,
1611.1Smycroft	FE_TYPE_AT1700FT,
1621.1Smycroft	FE_TYPE_AT1700AT,
1631.1Smycroft	FE_TYPE_RE2000,
1641.1Smycroft
1651.1Smycroft	/* PCMCIA by Fujitsu. */
1661.1Smycroft	FE_TYPE_MBH10302,
1671.1Smycroft	FE_TYPE_MBH10304,
1681.1Smycroft};
1691.1Smycroft
1701.1Smycroft/*
1711.1Smycroft * fe_softc: per line info and status
1721.1Smycroft */
1731.1Smycroftstruct fe_softc {
1741.1Smycroft	struct	device sc_dev;
1751.1Smycroft	void	*sc_ih;
1761.1Smycroft
1771.17Sis	struct	ethercom sc_ethercom;	/* ethernet common */
1781.1Smycroft
1791.1Smycroft	/* Set by probe() and not modified in later phases. */
1801.1Smycroft	enum	fe_type type;	/* interface type code */
1811.1Smycroft	char	*typestr;	/* printable name of the interface. */
1821.1Smycroft	int	sc_iobase;	/* MB86960A I/O base address */
1831.1Smycroft
1841.1Smycroft	u_char	proto_dlcr4;	/* DLCR4 prototype. */
1851.1Smycroft	u_char	proto_dlcr5;	/* DLCR5 prototype. */
1861.1Smycroft	u_char	proto_dlcr6;	/* DLCR6 prototype. */
1871.1Smycroft	u_char	proto_dlcr7;	/* DLCR7 prototype. */
1881.1Smycroft	u_char	proto_bmpr13;	/* BMPR13 prototype. */
1891.1Smycroft
1901.1Smycroft	/* Vendor specific hooks. */
1911.1Smycroft	void	(*init) __P((struct fe_softc *)); /* Just before fe_init(). */
1921.1Smycroft	void	(*stop) __P((struct fe_softc *)); /* Just after fe_stop(). */
1931.1Smycroft
1941.1Smycroft	/* Transmission buffer management. */
1951.1Smycroft	u_short	txb_size;	/* total bytes in TX buffer */
1961.1Smycroft	u_short	txb_free;	/* free bytes in TX buffer */
1971.1Smycroft	u_char	txb_count;	/* number of packets in TX buffer */
1981.1Smycroft	u_char	txb_sched;	/* number of scheduled packets */
1991.1Smycroft	u_char	txb_padding;	/* number of delayed padding bytes */
2001.1Smycroft
2011.1Smycroft	/* Multicast address filter management. */
2021.1Smycroft	u_char	filter_change;	/* MARs must be changed ASAP. */
2031.1Smycroft	u_char	filter[FE_FILTER_LEN];	/* new filter value. */
2041.17Sis
2051.17Sis	u_int8_t sc_enaddr[ETHER_ADDR_LEN];
2061.18Sexplorer
2071.18Sexplorer#if NRND > 0
2081.18Sexplorer	rndsource_element_t rnd_source;
2091.18Sexplorer#endif
2101.1Smycroft};
2111.1Smycroft
2121.1Smycroft/* Standard driver entry points.  These can be static. */
2131.1Smycroftint	feprobe		__P((struct device *, void *, void *));
2141.1Smycroftvoid	feattach	__P((struct device *, struct device *, void *));
2151.1Smycroftint	feintr		__P((void *));
2161.1Smycroftvoid	fe_init		__P((struct fe_softc *));
2171.1Smycroftint	fe_ioctl	__P((struct ifnet *, u_long, caddr_t));
2181.1Smycroftvoid	fe_start	__P((struct ifnet *));
2191.1Smycroftvoid	fe_reset	__P((struct fe_softc *));
2201.12Sthorpejvoid	fe_watchdog	__P((struct ifnet *));
2211.1Smycroft
2221.1Smycroft/* Local functions.  Order of declaration is confused.  FIXME. */
2231.1Smycroftint	fe_probe_fmv	__P((struct fe_softc *, struct isa_attach_args *));
2241.1Smycroftint	fe_probe_ati	__P((struct fe_softc *, struct isa_attach_args *));
2251.1Smycroftint	fe_probe_mbh	__P((struct fe_softc *, struct isa_attach_args *));
2261.16Sthorpejvoid	fe_read_eeprom	__P((struct fe_softc *, u_char *));
2271.1Smycroftvoid	fe_init_mbh	__P((struct fe_softc *));
2281.1Smycroftint	fe_get_packet	__P((struct fe_softc *, int));
2291.1Smycroftvoid	fe_stop		__P((struct fe_softc *));
2301.16Sthorpejvoid	fe_tint		__P((struct fe_softc *, u_char));
2311.16Sthorpejvoid	fe_rint		__P((struct fe_softc *, u_char));
2321.1Smycroftstatic inline
2331.1Smycroftvoid	fe_xmit		__P((struct fe_softc *));
2341.1Smycroftvoid	fe_write_mbufs	__P((struct fe_softc *, struct mbuf *));
2351.16Sthorpejstatic inline
2361.16Sthorpejvoid	fe_droppacket	__P((struct fe_softc *));
2371.17Sisvoid	fe_getmcaf	__P((struct ethercom *, u_char *));
2381.1Smycroftvoid	fe_setmode	__P((struct fe_softc *));
2391.1Smycroftvoid	fe_loadmar	__P((struct fe_softc *));
2401.1Smycroft#if FE_DEBUG >= 1
2411.1Smycroftvoid	fe_dump		__P((int, struct fe_softc *));
2421.1Smycroft#endif
2431.1Smycroft
2441.9Sthorpejstruct cfattach fe_ca = {
2451.9Sthorpej	sizeof(struct fe_softc), feprobe, feattach
2461.9Sthorpej};
2471.9Sthorpej
2481.9Sthorpejstruct cfdriver fe_cd = {
2491.9Sthorpej	NULL, "fe", DV_IFNET
2501.1Smycroft};
2511.1Smycroft
2521.1Smycroft/* Ethernet constants.  To be defined in if_ehter.h?  FIXME. */
2531.1Smycroft#define ETHER_MIN_LEN	60	/* with header, without CRC. */
2541.1Smycroft#define ETHER_MAX_LEN	1514	/* with header, without CRC. */
2551.1Smycroft#define ETHER_ADDR_LEN	6	/* number of bytes in an address. */
2561.1Smycroft#define ETHER_HDR_SIZE	14	/* src addr, dst addr, and data type. */
2571.1Smycroft
2581.1Smycroft/*
2591.1Smycroft * Fe driver specific constants which relate to 86960/86965.
2601.1Smycroft */
2611.1Smycroft
2621.1Smycroft/* Interrupt masks. */
2631.1Smycroft#define FE_TMASK (FE_D2_COLL16 | FE_D2_TXDONE)
2641.1Smycroft#define FE_RMASK (FE_D3_OVRFLO | FE_D3_CRCERR | \
2651.1Smycroft		  FE_D3_ALGERR | FE_D3_SRTPKT | FE_D3_PKTRDY)
2661.1Smycroft
2671.1Smycroft/* Maximum number of iterrations for a receive interrupt. */
2681.1Smycroft#define FE_MAX_RECV_COUNT ((65536 - 2048 * 2) / 64)
2691.1Smycroft	/* Maximum size of SRAM is 65536,
2701.1Smycroft	 * minimum size of transmission buffer in fe is 2x2KB,
2711.1Smycroft	 * and minimum amount of received packet including headers
2721.1Smycroft	 * added by the chip is 64 bytes.
2731.1Smycroft	 * Hence FE_MAX_RECV_COUNT is the upper limit for number
2741.1Smycroft	 * of packets in the receive buffer. */
2751.1Smycroft
2761.1Smycroft/*
2771.1Smycroft * Convenient routines to access contiguous I/O ports.
2781.1Smycroft */
2791.1Smycroft
2801.1Smycroftstatic inline void
2811.1Smycroftinblk (int addr, u_char * mem, int len)
2821.1Smycroft{
2831.1Smycroft	while (--len >= 0) {
2841.1Smycroft		*mem++ = inb(addr++);
2851.1Smycroft	}
2861.1Smycroft}
2871.1Smycroft
2881.1Smycroftstatic inline void
2891.1Smycroftoutblk (int addr, u_char const * mem, int len)
2901.1Smycroft{
2911.1Smycroft	while (--len >= 0) {
2921.1Smycroft		outb(addr++, *mem++);
2931.1Smycroft	}
2941.1Smycroft}
2951.1Smycroft
2961.1Smycroft/*
2971.1Smycroft * Hardware probe routines.
2981.1Smycroft */
2991.1Smycroft
3001.1Smycroft/*
3011.1Smycroft * Determine if the device is present.
3021.1Smycroft */
3031.1Smycroftint
3041.1Smycroftfeprobe(parent, match, aux)
3051.1Smycroft	struct device *parent;
3061.1Smycroft	void *match, *aux;
3071.1Smycroft{
3081.1Smycroft	struct fe_softc *sc = match;
3091.1Smycroft	struct isa_attach_args *ia = aux;
3101.1Smycroft
3111.1Smycroft#if FE_DEBUG >= 2
3121.1Smycroft	log(LOG_INFO, "%s: %s\n", sc->sc_dev.dv_xname, fe_version);
3131.1Smycroft#endif
3141.1Smycroft
3151.1Smycroft	/* Probe an address. */
3161.1Smycroft	sc->sc_iobase = ia->ia_iobase;
3171.1Smycroft
3181.1Smycroft	if (fe_probe_fmv(sc, ia))
3191.1Smycroft		return (1);
3201.1Smycroft	if (fe_probe_ati(sc, ia))
3211.1Smycroft		return (1);
3221.1Smycroft	if (fe_probe_mbh(sc, ia))
3231.1Smycroft		return (1);
3241.1Smycroft	return (0);
3251.1Smycroft}
3261.1Smycroft
3271.1Smycroft/*
3281.1Smycroft * Check for specific bits in specific registers have specific values.
3291.1Smycroft */
3301.1Smycroftstruct fe_simple_probe_struct {
3311.1Smycroft	u_char port;	/* Offset from the base I/O address. */
3321.1Smycroft	u_char mask;	/* Bits to be checked. */
3331.1Smycroft	u_char bits;	/* Values to be compared against. */
3341.1Smycroft};
3351.1Smycroft
3361.1Smycroftstatic inline int
3371.1Smycroftfe_simple_probe (int addr, struct fe_simple_probe_struct const * sp)
3381.1Smycroft{
3391.1Smycroft	struct fe_simple_probe_struct const * p;
3401.1Smycroft
3411.1Smycroft	for (p = sp; p->mask != 0; p++) {
3421.1Smycroft		if ((inb(addr + p->port) & p->mask) != p->bits) {
3431.1Smycroft			return (0);
3441.1Smycroft		}
3451.1Smycroft	}
3461.1Smycroft	return (1);
3471.1Smycroft}
3481.1Smycroft
3491.1Smycroft/*
3501.1Smycroft * Routines to read all bytes from the config EEPROM through MB86965A.
3511.1Smycroft * I'm not sure what exactly I'm doing here...  I was told just to follow
3521.1Smycroft * the steps, and it worked.  Could someone tell me why the following
3531.1Smycroft * code works?  (Or, why all similar codes I tried previously doesn't
3541.1Smycroft * work.)  FIXME.
3551.1Smycroft */
3561.1Smycroft
3571.1Smycroftstatic inline void
3581.1Smycroftstrobe (int bmpr16)
3591.1Smycroft{
3601.1Smycroft	/*
3611.1Smycroft	 * Output same value twice.  To speed-down execution?
3621.1Smycroft	 */
3631.1Smycroft	outb(bmpr16, FE_B16_SELECT);
3641.1Smycroft	outb(bmpr16, FE_B16_SELECT);
3651.1Smycroft	outb(bmpr16, FE_B16_SELECT | FE_B16_CLOCK);
3661.1Smycroft	outb(bmpr16, FE_B16_SELECT | FE_B16_CLOCK);
3671.1Smycroft	outb(bmpr16, FE_B16_SELECT);
3681.1Smycroft	outb(bmpr16, FE_B16_SELECT);
3691.1Smycroft}
3701.1Smycroft
3711.1Smycroftvoid
3721.1Smycroftfe_read_eeprom(sc, data)
3731.1Smycroft	struct fe_softc *sc;
3741.1Smycroft	u_char *data;
3751.1Smycroft{
3761.1Smycroft	int iobase = sc->sc_iobase;
3771.1Smycroft	int bmpr16 = iobase + FE_BMPR16;
3781.1Smycroft	int bmpr17 = iobase + FE_BMPR17;
3791.1Smycroft	u_char n, val, bit;
3801.1Smycroft
3811.1Smycroft	/* Read bytes from EEPROM; two bytes per an iterration. */
3821.1Smycroft	for (n = 0; n < FE_EEPROM_SIZE / 2; n++) {
3831.1Smycroft		/* Reset the EEPROM interface. */
3841.1Smycroft		outb(bmpr16, 0x00);
3851.1Smycroft		outb(bmpr17, 0x00);
3861.1Smycroft		outb(bmpr16, FE_B16_SELECT);
3871.1Smycroft
3881.1Smycroft		/* Start EEPROM access. */
3891.1Smycroft		outb(bmpr17, FE_B17_DATA);
3901.1Smycroft		strobe(bmpr16);
3911.1Smycroft
3921.1Smycroft		/* Pass the iterration count to the chip. */
3931.1Smycroft		val = 0x80 | n;
3941.1Smycroft		for (bit = 0x80; bit != 0x00; bit >>= 1) {
3951.1Smycroft			outb(bmpr17, (val & bit) ? FE_B17_DATA : 0);
3961.1Smycroft			strobe(bmpr16);
3971.1Smycroft		}
3981.1Smycroft		outb(bmpr17, 0x00);
3991.1Smycroft
4001.1Smycroft		/* Read a byte. */
4011.1Smycroft		val = 0;
4021.1Smycroft		for (bit = 0x80; bit != 0x00; bit >>= 1) {
4031.1Smycroft			strobe(bmpr16);
4041.1Smycroft			if (inb(bmpr17) & FE_B17_DATA)
4051.1Smycroft				val |= bit;
4061.1Smycroft		}
4071.1Smycroft		*data++ = val;
4081.1Smycroft
4091.1Smycroft		/* Read one more byte. */
4101.1Smycroft		val = 0;
4111.1Smycroft		for (bit = 0x80; bit != 0x00; bit >>= 1) {
4121.1Smycroft			strobe(bmpr16);
4131.1Smycroft			if (inb(bmpr17) & FE_B17_DATA)
4141.1Smycroft				val |= bit;
4151.1Smycroft		}
4161.1Smycroft		*data++ = val;
4171.1Smycroft	}
4181.1Smycroft
4191.1Smycroft#if FE_DEBUG >= 3
4201.1Smycroft	/* Report what we got. */
4211.1Smycroft	data -= FE_EEPROM_SIZE;
4221.1Smycroft	log(LOG_INFO, "%s: EEPROM at %04x:"
4231.1Smycroft	    " %02x%02x%02x%02x %02x%02x%02x%02x -"
4241.1Smycroft	    " %02x%02x%02x%02x %02x%02x%02x%02x -"
4251.1Smycroft	    " %02x%02x%02x%02x %02x%02x%02x%02x -"
4261.1Smycroft	    " %02x%02x%02x%02x %02x%02x%02x%02x\n",
4271.1Smycroft	    sc->sc_dev.dv_xname, iobase,
4281.1Smycroft	    data[ 0], data[ 1], data[ 2], data[ 3],
4291.1Smycroft	    data[ 4], data[ 5], data[ 6], data[ 7],
4301.1Smycroft	    data[ 8], data[ 9], data[10], data[11],
4311.1Smycroft	    data[12], data[13], data[14], data[15],
4321.1Smycroft	    data[16], data[17], data[18], data[19],
4331.1Smycroft	    data[20], data[21], data[22], data[23],
4341.1Smycroft	    data[24], data[25], data[26], data[27],
4351.1Smycroft	    data[28], data[29], data[30], data[31]);
4361.1Smycroft#endif
4371.1Smycroft}
4381.1Smycroft
4391.1Smycroft/*
4401.1Smycroft * Hardware (vendor) specific probe routines.
4411.1Smycroft */
4421.1Smycroft
4431.1Smycroft/*
4441.1Smycroft * Probe and initialization for Fujitsu FMV-180 series boards
4451.1Smycroft */
4461.1Smycroftint
4471.1Smycroftfe_probe_fmv(sc, ia)
4481.1Smycroft	struct fe_softc *sc;
4491.1Smycroft	struct isa_attach_args *ia;
4501.1Smycroft{
4511.1Smycroft	int i, n;
4521.1Smycroft	int iobase = sc->sc_iobase;
4531.1Smycroft	int irq;
4541.1Smycroft
4551.1Smycroft	static int const iomap[8] =
4561.1Smycroft		{ 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x300, 0x340 };
4571.1Smycroft	static int const irqmap[4] =
4581.1Smycroft		{ 3, 7, 10, 15 };
4591.1Smycroft
4601.1Smycroft	static struct fe_simple_probe_struct const probe_table[] = {
4611.1Smycroft		{ FE_DLCR2, 0x70, 0x00 },
4621.1Smycroft		{ FE_DLCR4, 0x08, 0x00 },
4631.1Smycroft	    /*	{ FE_DLCR5, 0x80, 0x00 },	Doesn't work. */
4641.1Smycroft
4651.1Smycroft		{ FE_FMV0, FE_FMV0_MAGIC_MASK,  FE_FMV0_MAGIC_VALUE },
4661.1Smycroft		{ FE_FMV1, FE_FMV1_CARDID_MASK, FE_FMV1_CARDID_ID   },
4671.1Smycroft		{ FE_FMV3, FE_FMV3_EXTRA_MASK,  FE_FMV3_EXTRA_VALUE },
4681.1Smycroft#if 1
4691.1Smycroft	/*
4701.1Smycroft	 * Test *vendor* part of the station address for Fujitsu.
4711.1Smycroft	 * The test will gain reliability of probe process, but
4721.1Smycroft	 * it rejects FMV-180 clone boards manufactured by other vendors.
4731.1Smycroft	 * We have to turn the test off when such cards are made available.
4741.1Smycroft	 */
4751.1Smycroft		{ FE_FMV4, 0xFF, 0x00 },
4761.1Smycroft		{ FE_FMV5, 0xFF, 0x00 },
4771.1Smycroft		{ FE_FMV6, 0xFF, 0x0E },
4781.1Smycroft#else
4791.1Smycroft	/*
4801.1Smycroft	 * We can always verify the *first* 2 bits (in Ehternet
4811.1Smycroft	 * bit order) are "no multicast" and "no local" even for
4821.1Smycroft	 * unknown vendors.
4831.1Smycroft	 */
4841.1Smycroft		{ FE_FMV4, 0x03, 0x00 },
4851.1Smycroft#endif
4861.1Smycroft		{ 0 }
4871.1Smycroft	};
4881.1Smycroft
4891.1Smycroft#if 0
4901.1Smycroft	/*
4911.1Smycroft	 * Dont probe at all if the config says we are PCMCIA...
4921.1Smycroft	 */
4931.1Smycroft	if ((cf->cf_flags & FE_FLAGS_PCMCIA) != 0)
4941.1Smycroft		return (0);
4951.1Smycroft#endif
4961.1Smycroft
4971.1Smycroft	/*
4981.1Smycroft	 * See if the sepcified address is possible for FMV-180 series.
4991.1Smycroft	 */
5001.1Smycroft	for (i = 0; i < 8; i++) {
5011.1Smycroft		if (iomap[i] == iobase)
5021.1Smycroft			break;
5031.1Smycroft	}
5041.1Smycroft	if (i == 8)
5051.1Smycroft		return (0);
5061.1Smycroft
5071.1Smycroft	/* Simple probe. */
5081.1Smycroft	if (!fe_simple_probe(iobase, probe_table))
5091.1Smycroft		return (0);
5101.1Smycroft
5111.1Smycroft	/* Check if our I/O address matches config info on EEPROM. */
5121.1Smycroft	n = (inb(iobase + FE_FMV2) & FE_FMV2_ADDR) >> FE_FMV2_ADDR_SHIFT;
5131.1Smycroft	if (iomap[n] != iobase)
5141.1Smycroft		return (0);
5151.1Smycroft
5161.1Smycroft	/* Determine the card type. */
5171.1Smycroft	switch (inb(iobase + FE_FMV0) & FE_FMV0_MODEL) {
5181.1Smycroft	case FE_FMV0_MODEL_FMV181:
5191.1Smycroft		sc->type = FE_TYPE_FMV181;
5201.1Smycroft		sc->typestr = "FMV-181";
5211.1Smycroft		break;
5221.1Smycroft	case FE_FMV0_MODEL_FMV182:
5231.1Smycroft		sc->type = FE_TYPE_FMV182;
5241.1Smycroft		sc->typestr = "FMV-182";
5251.1Smycroft		break;
5261.1Smycroft	default:
5271.1Smycroft	  	/* Unknown card type: maybe a new model, but... */
5281.1Smycroft		return (0);
5291.1Smycroft	}
5301.1Smycroft
5311.1Smycroft	/*
5321.1Smycroft	 * An FMV-180 has successfully been proved.
5331.1Smycroft	 * Determine which IRQ to be used.
5341.1Smycroft	 *
5351.1Smycroft	 * In this version, we always get an IRQ assignment from the
5361.1Smycroft	 * FMV-180's configuration EEPROM, ignoring that specified in
5371.1Smycroft	 * config file.
5381.1Smycroft	 */
5391.1Smycroft	n = (inb(iobase + FE_FMV2) & FE_FMV2_IRQ) >> FE_FMV2_IRQ_SHIFT;
5401.1Smycroft	irq = irqmap[n];
5411.1Smycroft
5421.1Smycroft	if (ia->ia_irq != IRQUNK) {
5431.1Smycroft		if (ia->ia_irq != irq) {
5441.15Schristos			printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
5451.1Smycroft			    sc->sc_dev.dv_xname, ia->ia_irq, irq);
5461.1Smycroft			return (0);
5471.1Smycroft		}
5481.1Smycroft	} else
5491.1Smycroft		ia->ia_irq = irq;
5501.1Smycroft
5511.1Smycroft	/*
5521.1Smycroft	 * Initialize constants in the per-line structure.
5531.1Smycroft	 */
5541.1Smycroft
5551.1Smycroft	/* Get our station address from EEPROM. */
5561.1Smycroft	inblk(iobase + FE_FMV4, sc->sc_enaddr, ETHER_ADDR_LEN);
5571.1Smycroft
5581.1Smycroft	/* Make sure we got a valid station address. */
5591.1Smycroft	if ((sc->sc_enaddr[0] & 0x03) != 0x00
5601.1Smycroft	  || (sc->sc_enaddr[0] == 0x00
5611.1Smycroft	    && sc->sc_enaddr[1] == 0x00
5621.1Smycroft	    && sc->sc_enaddr[2] == 0x00))
5631.1Smycroft		return (0);
5641.1Smycroft
5651.1Smycroft	/* Register values which depend on board design. */
5661.1Smycroft	sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL;
5671.1Smycroft	sc->proto_dlcr5 = 0;
5681.1Smycroft	sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC;
5691.1Smycroft	sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO;
5701.1Smycroft
5711.1Smycroft	/*
5721.1Smycroft	 * Program the 86960 as follows:
5731.1Smycroft	 *	SRAM: 32KB, 100ns, byte-wide access.
5741.1Smycroft	 *	Transmission buffer: 4KB x 2.
5751.1Smycroft	 *	System bus interface: 16 bits.
5761.1Smycroft	 * We cannot change these values but TXBSIZE, because they
5771.1Smycroft	 * are hard-wired on the board.  Modifying TXBSIZE will affect
5781.1Smycroft	 * the driver performance.
5791.1Smycroft	 */
5801.1Smycroft	sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB
5811.1Smycroft		| FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns;
5821.1Smycroft
5831.1Smycroft	/*
5841.1Smycroft	 * Minimum initialization of the hardware.
5851.1Smycroft	 * We write into registers; hope I/O ports have no
5861.1Smycroft	 * overlap with other boards.
5871.1Smycroft	 */
5881.1Smycroft
5891.1Smycroft	/* Initialize ASIC. */
5901.1Smycroft	outb(iobase + FE_FMV3, 0);
5911.1Smycroft	outb(iobase + FE_FMV10, 0);
5921.1Smycroft
5931.1Smycroft	/* Wait for a while.  I'm not sure this is necessary.  FIXME. */
5941.1Smycroft	delay(200);
5951.1Smycroft
5961.1Smycroft	/* Initialize 86960. */
5971.1Smycroft	outb(iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
5981.1Smycroft	delay(200);
5991.1Smycroft
6001.1Smycroft	/* Disable all interrupts. */
6011.1Smycroft	outb(iobase + FE_DLCR2, 0);
6021.1Smycroft	outb(iobase + FE_DLCR3, 0);
6031.1Smycroft
6041.1Smycroft	/* Turn the "master interrupt control" flag of ASIC on. */
6051.1Smycroft	outb(iobase + FE_FMV3, FE_FMV3_ENABLE_FLAG);
6061.1Smycroft
6071.1Smycroft	/*
6081.1Smycroft	 * That's all.  FMV-180 occupies 32 I/O addresses, by the way.
6091.1Smycroft	 */
6101.1Smycroft	ia->ia_iosize = 32;
6111.1Smycroft	ia->ia_msize = 0;
6121.1Smycroft	return (1);
6131.1Smycroft}
6141.1Smycroft
6151.1Smycroft/*
6161.1Smycroft * Probe and initialization for Allied-Telesis AT1700/RE2000 series.
6171.1Smycroft */
6181.1Smycroftint
6191.1Smycroftfe_probe_ati(sc, ia)
6201.1Smycroft	struct fe_softc *sc;
6211.1Smycroft	struct isa_attach_args *ia;
6221.1Smycroft{
6231.1Smycroft	int i, n;
6241.1Smycroft	int iobase = sc->sc_iobase;
6251.1Smycroft	u_char eeprom[FE_EEPROM_SIZE];
6261.1Smycroft	u_char save16, save17;
6271.1Smycroft	int irq;
6281.1Smycroft
6291.1Smycroft	static int const iomap[8] =
6301.1Smycroft		{ 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300 };
6311.1Smycroft	static int const irqmap[4][4] = {
6321.1Smycroft		{  3,  4,  5,  9 },
6331.1Smycroft		{ 10, 11, 12, 15 },
6341.1Smycroft		{  3, 11,  5, 15 },
6351.1Smycroft		{ 10, 11, 14, 15 },
6361.1Smycroft	};
6371.1Smycroft	static struct fe_simple_probe_struct const probe_table[] = {
6381.1Smycroft		{ FE_DLCR2,  0x70, 0x00 },
6391.1Smycroft		{ FE_DLCR4,  0x08, 0x00 },
6401.1Smycroft		{ FE_DLCR5,  0x80, 0x00 },
6411.1Smycroft#if 0
6421.1Smycroft		{ FE_BMPR16, 0x1B, 0x00 },
6431.1Smycroft		{ FE_BMPR17, 0x7F, 0x00 },
6441.1Smycroft#endif
6451.1Smycroft		{ 0 }
6461.1Smycroft	};
6471.1Smycroft
6481.1Smycroft#if 0
6491.1Smycroft	/*
6501.1Smycroft	 * Don't probe at all if the config says we are PCMCIA...
6511.1Smycroft	 */
6521.1Smycroft	if ((cf->cf_flags & FE_FLAGS_PCMCIA) != 0)
6531.1Smycroft		return (0);
6541.1Smycroft#endif
6551.1Smycroft
6561.1Smycroft#if FE_DEBUG >= 4
6571.1Smycroft	log(LOG_INFO, "%s: probe (0x%x) for ATI\n", sc->sc_dev.dv_xname, iobase);
6581.1Smycroft	fe_dump(LOG_INFO, sc);
6591.1Smycroft#endif
6601.1Smycroft
6611.1Smycroft	/*
6621.1Smycroft	 * See if the sepcified address is possible for MB86965A JLI mode.
6631.1Smycroft	 */
6641.1Smycroft	for (i = 0; i < 8; i++) {
6651.1Smycroft		if (iomap[i] == iobase)
6661.1Smycroft			break;
6671.1Smycroft	}
6681.1Smycroft	if (i == 8)
6691.1Smycroft		return (0);
6701.1Smycroft
6711.1Smycroft	/*
6721.1Smycroft	 * We should test if MB86965A is on the base address now.
6731.1Smycroft	 * Unfortunately, it is very hard to probe it reliably, since
6741.1Smycroft	 * we have no way to reset the chip under software control.
6751.1Smycroft	 * On cold boot, we could check the "signature" bit patterns
6761.1Smycroft	 * described in the Fujitsu document.  On warm boot, however,
6771.1Smycroft	 * we can predict almost nothing about register values.
6781.1Smycroft	 */
6791.1Smycroft	if (!fe_simple_probe(iobase, probe_table))
6801.1Smycroft		return (0);
6811.1Smycroft
6821.1Smycroft	/* Save old values of the registers. */
6831.1Smycroft	save16 = inb(iobase + FE_BMPR16);
6841.1Smycroft	save17 = inb(iobase + FE_BMPR17);
6851.1Smycroft
6861.1Smycroft	/* Check if our I/O address matches config info on 86965. */
6871.1Smycroft	n = (inb(iobase + FE_BMPR19) & FE_B19_ADDR) >> FE_B19_ADDR_SHIFT;
6881.1Smycroft	if (iomap[n] != iobase)
6891.1Smycroft		goto fail;
6901.1Smycroft
6911.1Smycroft	/*
6921.1Smycroft	 * We are now almost sure we have an AT1700 at the given
6931.1Smycroft	 * address.  So, read EEPROM through 86965.  We have to write
6941.1Smycroft	 * into LSI registers to read from EEPROM.  I want to avoid it
6951.1Smycroft	 * at this stage, but I cannot test the presense of the chip
6961.1Smycroft	 * any further without reading EEPROM.  FIXME.
6971.1Smycroft	 */
6981.1Smycroft	fe_read_eeprom(sc, eeprom);
6991.1Smycroft
7001.1Smycroft	/* Make sure the EEPROM is turned off. */
7011.1Smycroft	outb(iobase + FE_BMPR16, 0);
7021.1Smycroft	outb(iobase + FE_BMPR17, 0);
7031.1Smycroft
7041.1Smycroft	/* Make sure that config info in EEPROM and 86965 agree. */
7051.1Smycroft	if (eeprom[FE_EEPROM_CONF] != inb(iobase + FE_BMPR19))
7061.1Smycroft		goto fail;
7071.1Smycroft
7081.1Smycroft	/*
7091.1Smycroft	 * Determine the card type.
7101.1Smycroft	 */
7111.1Smycroft	switch (eeprom[FE_ATI_EEP_MODEL]) {
7121.1Smycroft	case FE_ATI_MODEL_AT1700T:
7131.1Smycroft		sc->type = FE_TYPE_AT1700T;
7141.1Smycroft		sc->typestr = "AT-1700T";
7151.1Smycroft		break;
7161.1Smycroft	case FE_ATI_MODEL_AT1700BT:
7171.1Smycroft		sc->type = FE_TYPE_AT1700BT;
7181.1Smycroft		sc->typestr = "AT-1700BT";
7191.1Smycroft		break;
7201.1Smycroft	case FE_ATI_MODEL_AT1700FT:
7211.1Smycroft		sc->type = FE_TYPE_AT1700FT;
7221.1Smycroft		sc->typestr = "AT-1700FT";
7231.1Smycroft		break;
7241.1Smycroft	case FE_ATI_MODEL_AT1700AT:
7251.1Smycroft		sc->type = FE_TYPE_AT1700AT;
7261.1Smycroft		sc->typestr = "AT-1700AT";
7271.1Smycroft		break;
7281.1Smycroft	default:
7291.1Smycroft		sc->type = FE_TYPE_RE2000;
7301.1Smycroft		sc->typestr = "unknown (RE-2000?)";
7311.1Smycroft		break;
7321.1Smycroft	}
7331.1Smycroft
7341.1Smycroft	/*
7351.1Smycroft	 * Try to determine IRQ settings.
7361.1Smycroft	 * Different models use different ranges of IRQs.
7371.1Smycroft	 */
7381.1Smycroft	n = (inb(iobase + FE_BMPR19) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT;
7391.1Smycroft	switch (eeprom[FE_ATI_EEP_REVISION] & 0xf0) {
7401.1Smycroft	case 0x30:
7411.1Smycroft		irq = irqmap[3][n];
7421.1Smycroft		break;
7431.1Smycroft	case 0x10:
7441.1Smycroft	case 0x50:
7451.1Smycroft		irq = irqmap[2][n];
7461.1Smycroft		break;
7471.1Smycroft	case 0x40:
7481.1Smycroft	case 0x60:
7491.1Smycroft		if (eeprom[FE_ATI_EEP_MAGIC] & 0x04) {
7501.1Smycroft			irq = irqmap[1][n];
7511.1Smycroft			break;
7521.1Smycroft		}
7531.1Smycroft	default:
7541.1Smycroft		irq = irqmap[0][n];
7551.1Smycroft		break;
7561.1Smycroft	}
7571.1Smycroft
7581.1Smycroft	if (ia->ia_irq != IRQUNK) {
7591.1Smycroft		if (ia->ia_irq != irq) {
7601.15Schristos			printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
7611.1Smycroft			    sc->sc_dev.dv_xname, ia->ia_irq, irq);
7621.1Smycroft			return (0);
7631.1Smycroft		}
7641.1Smycroft	} else
7651.1Smycroft		ia->ia_irq = irq;
7661.1Smycroft
7671.1Smycroft	/*
7681.1Smycroft	 * Initialize constants in the per-line structure.
7691.1Smycroft	 */
7701.1Smycroft
7711.1Smycroft	/* Get our station address from EEPROM. */
7721.1Smycroft	bcopy(eeprom + FE_ATI_EEP_ADDR, sc->sc_enaddr, ETHER_ADDR_LEN);
7731.1Smycroft
7741.1Smycroft	/* Make sure we got a valid station address. */
7751.1Smycroft	if ((sc->sc_enaddr[0] & 0x03) != 0x00
7761.1Smycroft	  || (sc->sc_enaddr[0] == 0x00
7771.1Smycroft	    && sc->sc_enaddr[1] == 0x00
7781.1Smycroft	    && sc->sc_enaddr[2] == 0x00))
7791.1Smycroft		goto fail;
7801.1Smycroft
7811.1Smycroft	/* Should find all register prototypes here.  FIXME. */
7821.1Smycroft	sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL;  /* FIXME */
7831.1Smycroft	sc->proto_dlcr5 = 0;
7841.1Smycroft	sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_EC;
7851.1Smycroft#if 0	/* XXXX Should we use this? */
7861.1Smycroft	sc->proto_bmpr13 = eeprom[FE_ATI_EEP_MEDIA];
7871.1Smycroft#else
7881.1Smycroft	sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO;
7891.1Smycroft#endif
7901.1Smycroft
7911.1Smycroft	/*
7921.1Smycroft	 * Program the 86965 as follows:
7931.1Smycroft	 *	SRAM: 32KB, 100ns, byte-wide access.
7941.1Smycroft	 *	Transmission buffer: 4KB x 2.
7951.1Smycroft	 *	System bus interface: 16 bits.
7961.1Smycroft	 * We cannot change these values but TXBSIZE, because they
7971.1Smycroft	 * are hard-wired on the board.  Modifying TXBSIZE will affect
7981.1Smycroft	 * the driver performance.
7991.1Smycroft	 */
8001.1Smycroft	sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB
8011.1Smycroft		| FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns;
8021.1Smycroft
8031.1Smycroft#if FE_DEBUG >= 3
8041.1Smycroft	log(LOG_INFO, "%s: ATI found\n", sc->sc_dev.dv_xname);
8051.1Smycroft	fe_dump(LOG_INFO, sc);
8061.1Smycroft#endif
8071.1Smycroft
8081.1Smycroft	/* Initialize 86965. */
8091.1Smycroft	outb(iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
8101.1Smycroft	delay(200);
8111.1Smycroft
8121.1Smycroft	/* Disable all interrupts. */
8131.1Smycroft	outb(iobase + FE_DLCR2, 0);
8141.1Smycroft	outb(iobase + FE_DLCR3, 0);
8151.1Smycroft
8161.1Smycroft#if FE_DEBUG >= 3
8171.1Smycroft	log(LOG_INFO, "%s: end of fe_probe_ati()\n", sc->sc_dev.dv_xname);
8181.1Smycroft	fe_dump(LOG_INFO, sc);
8191.1Smycroft#endif
8201.1Smycroft
8211.1Smycroft	/*
8221.1Smycroft	 * That's all.  AT1700 occupies 32 I/O addresses, by the way.
8231.1Smycroft	 */
8241.1Smycroft	ia->ia_iosize = 32;
8251.1Smycroft	ia->ia_msize = 0;
8261.1Smycroft	return (1);
8271.1Smycroft
8281.1Smycroftfail:
8291.1Smycroft	/* Restore register values, in the case we had no 86965. */
8301.1Smycroft	outb(iobase + FE_BMPR16, save16);
8311.1Smycroft	outb(iobase + FE_BMPR17, save17);
8321.1Smycroft	return (0);
8331.1Smycroft}
8341.1Smycroft
8351.1Smycroft/*
8361.1Smycroft * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface.
8371.1Smycroft */
8381.1Smycroftint
8391.1Smycroftfe_probe_mbh(sc, ia)
8401.1Smycroft	struct fe_softc *sc;
8411.1Smycroft	struct isa_attach_args *ia;
8421.1Smycroft{
8431.1Smycroft	int iobase = sc->sc_iobase;
8441.1Smycroft
8451.1Smycroft	static struct fe_simple_probe_struct probe_table[] = {
8461.1Smycroft		{ FE_DLCR2, 0x70, 0x00 },
8471.1Smycroft		{ FE_DLCR4, 0x08, 0x00 },
8481.1Smycroft	    /*	{ FE_DLCR5, 0x80, 0x00 },	Does not work well. */
8491.1Smycroft#if 0
8501.1Smycroft	/*
8511.1Smycroft	 * Test *vendor* part of the address for Fujitsu.
8521.1Smycroft	 * The test will gain reliability of probe process, but
8531.1Smycroft	 * it rejects clones by other vendors, or OEM product
8541.1Smycroft	 * supplied by resalers other than Fujitsu.
8551.1Smycroft	 */
8561.1Smycroft		{ FE_MBH10, 0xFF, 0x00 },
8571.1Smycroft		{ FE_MBH11, 0xFF, 0x00 },
8581.1Smycroft		{ FE_MBH12, 0xFF, 0x0E },
8591.1Smycroft#else
8601.1Smycroft	/*
8611.1Smycroft	 * We can always verify the *first* 2 bits (in Ehternet
8621.1Smycroft	 * bit order) are "global" and "unicast" even for
8631.1Smycroft	 * unknown vendors.
8641.1Smycroft	 */
8651.1Smycroft		{ FE_MBH10, 0x03, 0x00 },
8661.1Smycroft#endif
8671.1Smycroft        /* Just a gap?  Seems reliable, anyway. */
8681.1Smycroft		{ 0x12, 0xFF, 0x00 },
8691.1Smycroft		{ 0x13, 0xFF, 0x00 },
8701.1Smycroft		{ 0x14, 0xFF, 0x00 },
8711.1Smycroft		{ 0x15, 0xFF, 0x00 },
8721.1Smycroft		{ 0x16, 0xFF, 0x00 },
8731.1Smycroft		{ 0x17, 0xFF, 0x00 },
8741.1Smycroft		{ 0x18, 0xFF, 0xFF },
8751.1Smycroft		{ 0x19, 0xFF, 0xFF },
8761.1Smycroft
8771.1Smycroft		{ 0 }
8781.1Smycroft	};
8791.1Smycroft
8801.1Smycroft#if 0
8811.1Smycroft	/*
8821.1Smycroft	 * We need a PCMCIA flag.
8831.1Smycroft	 */
8841.1Smycroft	if ((cf->cf_flags & FE_FLAGS_PCMCIA) == 0)
8851.1Smycroft		return (0);
8861.1Smycroft#endif
8871.1Smycroft
8881.1Smycroft	/*
8891.1Smycroft	 * We need explicit IRQ and supported address.
8901.1Smycroft	 */
8911.1Smycroft	if (ia->ia_irq == IRQUNK || (iobase & ~0x3E0) != 0)
8921.1Smycroft		return (0);
8931.1Smycroft
8941.1Smycroft#if FE_DEBUG >= 3
8951.1Smycroft	log(LOG_INFO, "%s: top of fe_probe_mbh()\n", sc->sc_dev.dv_xname);
8961.1Smycroft	fe_dump(LOG_INFO, sc);
8971.1Smycroft#endif
8981.1Smycroft
8991.1Smycroft	/*
9001.1Smycroft	 * See if MBH10302 is on its address.
9011.1Smycroft	 * I'm not sure the following probe code works.  FIXME.
9021.1Smycroft	 */
9031.1Smycroft	if (!fe_simple_probe(iobase, probe_table))
9041.1Smycroft		return (0);
9051.1Smycroft
9061.1Smycroft	/* Determine the card type. */
9071.1Smycroft	sc->type = FE_TYPE_MBH10302;
9081.1Smycroft	sc->typestr = "MBH10302 (PCMCIA)";
9091.1Smycroft
9101.1Smycroft	/*
9111.1Smycroft	 * Initialize constants in the per-line structure.
9121.1Smycroft	 */
9131.1Smycroft
9141.1Smycroft	/* Get our station address from EEPROM. */
9151.1Smycroft	inblk(iobase + FE_MBH10, sc->sc_enaddr, ETHER_ADDR_LEN);
9161.1Smycroft
9171.1Smycroft	/* Make sure we got a valid station address. */
9181.1Smycroft	if ((sc->sc_enaddr[0] & 0x03) != 0x00
9191.1Smycroft	  || (sc->sc_enaddr[0] == 0x00
9201.1Smycroft	    && sc->sc_enaddr[1] == 0x00
9211.1Smycroft	    && sc->sc_enaddr[2] == 0x00))
9221.1Smycroft		return (0);
9231.1Smycroft
9241.1Smycroft	/* Should find all register prototypes here.  FIXME. */
9251.1Smycroft	sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL;
9261.1Smycroft	sc->proto_dlcr5 = 0;
9271.1Smycroft	sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;
9281.1Smycroft	sc->proto_bmpr13 = FE_B13_TPTYPE_UTP | FE_B13_PORT_AUTO;
9291.1Smycroft
9301.1Smycroft	/*
9311.1Smycroft	 * Program the 86960 as follows:
9321.1Smycroft	 *	SRAM: 32KB, 100ns, byte-wide access.
9331.1Smycroft	 *	Transmission buffer: 4KB x 2.
9341.1Smycroft	 *	System bus interface: 16 bits.
9351.1Smycroft	 * We cannot change these values but TXBSIZE, because they
9361.1Smycroft	 * are hard-wired on the board.  Modifying TXBSIZE will affect
9371.1Smycroft	 * the driver performance.
9381.1Smycroft	 */
9391.1Smycroft	sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB
9401.1Smycroft		| FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns;
9411.1Smycroft
9421.1Smycroft	/* Setup hooks.  We need a special initialization procedure. */
9431.1Smycroft	sc->init = fe_init_mbh;
9441.1Smycroft
9451.1Smycroft	/*
9461.1Smycroft	 * Minimum initialization.
9471.1Smycroft	 */
9481.1Smycroft
9491.1Smycroft	/* Wait for a while.  I'm not sure this is necessary.  FIXME. */
9501.1Smycroft	delay(200);
9511.1Smycroft
9521.1Smycroft	/* Minimul initialization of 86960. */
9531.1Smycroft	outb(iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
9541.1Smycroft	delay(200);
9551.1Smycroft
9561.1Smycroft	/* Disable all interrupts. */
9571.1Smycroft	outb(iobase + FE_DLCR2, 0);
9581.1Smycroft	outb(iobase + FE_DLCR3, 0);
9591.1Smycroft
9601.1Smycroft#if 1	/* FIXME. */
9611.1Smycroft	/* Initialize system bus interface and encoder/decoder operation. */
9621.1Smycroft	outb(iobase + FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_DISABLE);
9631.1Smycroft#endif
9641.1Smycroft
9651.1Smycroft	/*
9661.1Smycroft	 * That's all.  MBH10302 occupies 32 I/O addresses, by the way.
9671.1Smycroft	 */
9681.1Smycroft	ia->ia_iosize = 32;
9691.1Smycroft	ia->ia_msize = 0;
9701.1Smycroft	return (1);
9711.1Smycroft}
9721.1Smycroft
9731.1Smycroft/* MBH specific initialization routine. */
9741.1Smycroftvoid
9751.1Smycroftfe_init_mbh(sc)
9761.1Smycroft	struct fe_softc *sc;
9771.1Smycroft{
9781.1Smycroft
9791.1Smycroft	/* Probably required after hot-insertion... */
9801.1Smycroft
9811.1Smycroft	/* Wait for a while.  I'm not sure this is necessary.  FIXME. */
9821.1Smycroft	delay(200);
9831.1Smycroft
9841.1Smycroft	/* Minimul initialization of 86960. */
9851.1Smycroft	outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
9861.1Smycroft	delay(200);
9871.1Smycroft
9881.1Smycroft	/* Disable all interrupts. */
9891.1Smycroft	outb(sc->sc_iobase + FE_DLCR2, 0);
9901.1Smycroft	outb(sc->sc_iobase + FE_DLCR3, 0);
9911.1Smycroft
9921.1Smycroft	/* Enable master interrupt flag. */
9931.1Smycroft	outb(sc->sc_iobase + FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE);
9941.1Smycroft}
9951.1Smycroft
9961.1Smycroft/*
9971.1Smycroft * Install interface into kernel networking data structures
9981.1Smycroft */
9991.1Smycroftvoid
10001.1Smycroftfeattach(parent, self, aux)
10011.1Smycroft	struct device *parent, *self;
10021.1Smycroft	void *aux;
10031.1Smycroft{
10041.1Smycroft	struct fe_softc *sc = (void *)self;
10051.1Smycroft	struct isa_attach_args *ia = aux;
10061.1Smycroft	struct cfdata *cf = sc->sc_dev.dv_cfdata;
10071.17Sis	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
10081.1Smycroft
10091.1Smycroft	/* Stop the 86960. */
10101.1Smycroft	fe_stop(sc);
10111.1Smycroft
10121.1Smycroft	/* Initialize ifnet structure. */
10131.12Sthorpej	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
10141.12Sthorpej	ifp->if_softc = sc;
10151.1Smycroft	ifp->if_start = fe_start;
10161.1Smycroft	ifp->if_ioctl = fe_ioctl;
10171.1Smycroft	ifp->if_watchdog = fe_watchdog;
10181.6Smycroft	ifp->if_flags =
10191.6Smycroft	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
10201.1Smycroft
10211.1Smycroft	/*
10221.1Smycroft	 * Set maximum size of output queue, if it has not been set.
10231.1Smycroft	 * It is done here as this driver may be started after the
10241.1Smycroft	 * system intialization (i.e., the interface is PCMCIA.)
10251.1Smycroft	 *
10261.1Smycroft	 * I'm not sure this is really necessary, but, even if it is,
10271.1Smycroft	 * it should be done somewhere else, e.g., in if_attach(),
10281.1Smycroft	 * since it must be a common workaround for all network drivers.
10291.1Smycroft	 * FIXME.
10301.1Smycroft	 */
10311.1Smycroft	if (ifp->if_snd.ifq_maxlen == 0) {
10321.1Smycroft		extern int ifqmaxlen;		/* Don't be so shocked... */
10331.1Smycroft		ifp->if_snd.ifq_maxlen = ifqmaxlen;
10341.1Smycroft	}
10351.1Smycroft
10361.1Smycroft#if FE_DEBUG >= 3
10371.1Smycroft	log(LOG_INFO, "%s: feattach()\n", sc->sc_dev.dv_xname);
10381.1Smycroft	fe_dump(LOG_INFO, sc);
10391.1Smycroft#endif
10401.1Smycroft
10411.1Smycroft#if FE_SINGLE_TRANSMISSION
10421.1Smycroft	/* Override txb config to allocate minimum. */
10431.1Smycroft	sc->proto_dlcr6 &= ~FE_D6_TXBSIZ
10441.1Smycroft	sc->proto_dlcr6 |=  FE_D6_TXBSIZ_2x2KB;
10451.1Smycroft#endif
10461.1Smycroft
10471.1Smycroft	/* Modify hardware config if it is requested. */
10481.1Smycroft	if ((cf->cf_flags & FE_FLAGS_OVERRIDE_DLCR6) != 0)
10491.1Smycroft		sc->proto_dlcr6 = cf->cf_flags & FE_FLAGS_DLCR6_VALUE;
10501.1Smycroft
10511.1Smycroft	/* Find TX buffer size, based on the hardware dependent proto. */
10521.1Smycroft	switch (sc->proto_dlcr6 & FE_D6_TXBSIZ) {
10531.1Smycroft	case FE_D6_TXBSIZ_2x2KB:
10541.1Smycroft		sc->txb_size = 2048;
10551.1Smycroft		break;
10561.1Smycroft	case FE_D6_TXBSIZ_2x4KB:
10571.1Smycroft		sc->txb_size = 4096;
10581.1Smycroft		break;
10591.1Smycroft	case FE_D6_TXBSIZ_2x8KB:
10601.1Smycroft		sc->txb_size = 8192;
10611.1Smycroft		break;
10621.1Smycroft	default:
10631.1Smycroft		/* Oops, we can't work with single buffer configuration. */
10641.1Smycroft#if FE_DEBUG >= 2
10651.1Smycroft		log(LOG_WARNING, "%s: strange TXBSIZ config; fixing\n",
10661.1Smycroft		    sc->sc_dev.dv_xname);
10671.1Smycroft#endif
10681.1Smycroft		sc->proto_dlcr6 &= ~FE_D6_TXBSIZ;
10691.1Smycroft		sc->proto_dlcr6 |=  FE_D6_TXBSIZ_2x2KB;
10701.1Smycroft		sc->txb_size = 2048;
10711.1Smycroft		break;
10721.1Smycroft	}
10731.1Smycroft
10741.1Smycroft	/* Attach the interface. */
10751.1Smycroft	if_attach(ifp);
10761.17Sis	ether_ifattach(ifp, sc->sc_enaddr);
10771.1Smycroft
10781.1Smycroft	/* Print additional info when attached. */
10791.15Schristos	printf(": address %s, type %s\n",
10801.17Sis	    ether_sprintf(sc->sc_enaddr), sc->typestr);
10811.1Smycroft#if FE_DEBUG >= 3
10821.1Smycroft	{
10831.1Smycroft		int buf, txb, bbw, sbw, ram;
10841.1Smycroft
10851.1Smycroft		buf = txb = bbw = sbw = ram = -1;
10861.1Smycroft		switch (sc->proto_dlcr6 & FE_D6_BUFSIZ) {
10871.1Smycroft		case FE_D6_BUFSIZ_8KB:
10881.1Smycroft			buf = 8;
10891.1Smycroft			break;
10901.1Smycroft		case FE_D6_BUFSIZ_16KB:
10911.1Smycroft			buf = 16;
10921.1Smycroft			break;
10931.1Smycroft		case FE_D6_BUFSIZ_32KB:
10941.1Smycroft			buf = 32;
10951.1Smycroft			break;
10961.1Smycroft		case FE_D6_BUFSIZ_64KB:
10971.1Smycroft			buf = 64;
10981.1Smycroft			break;
10991.1Smycroft		}
11001.1Smycroft		switch (sc->proto_dlcr6 & FE_D6_TXBSIZ) {
11011.1Smycroft		case FE_D6_TXBSIZ_2x2KB:
11021.1Smycroft			txb = 2;
11031.1Smycroft			break;
11041.1Smycroft		case FE_D6_TXBSIZ_2x4KB:
11051.1Smycroft			txb = 4;
11061.1Smycroft			break;
11071.1Smycroft		case FE_D6_TXBSIZ_2x8KB:
11081.1Smycroft			txb = 8;
11091.1Smycroft			break;
11101.1Smycroft		}
11111.1Smycroft		switch (sc->proto_dlcr6 & FE_D6_BBW) {
11121.1Smycroft		case FE_D6_BBW_BYTE:
11131.1Smycroft			bbw = 8;
11141.1Smycroft			break;
11151.1Smycroft		case FE_D6_BBW_WORD:
11161.1Smycroft			bbw = 16;
11171.1Smycroft			break;
11181.1Smycroft		}
11191.1Smycroft		switch (sc->proto_dlcr6 & FE_D6_SBW) {
11201.1Smycroft		case FE_D6_SBW_BYTE:
11211.1Smycroft			sbw = 8;
11221.1Smycroft			break;
11231.1Smycroft		case FE_D6_SBW_WORD:
11241.1Smycroft			sbw = 16;
11251.1Smycroft			break;
11261.1Smycroft		}
11271.1Smycroft		switch (sc->proto_dlcr6 & FE_D6_SRAM) {
11281.1Smycroft		case FE_D6_SRAM_100ns:
11291.1Smycroft			ram = 100;
11301.1Smycroft			break;
11311.1Smycroft		case FE_D6_SRAM_150ns:
11321.1Smycroft			ram = 150;
11331.1Smycroft			break;
11341.1Smycroft		}
11351.15Schristos		printf("%s: SRAM %dKB %dbit %dns, TXB %dKBx2, %dbit I/O\n",
11361.1Smycroft		    sc->sc_dev.dv_xname, buf, bbw, ram, txb, sbw);
11371.1Smycroft	}
11381.1Smycroft#endif
11391.1Smycroft
11401.1Smycroft#if NBPFILTER > 0
11411.1Smycroft	/* If BPF is in the kernel, call the attach for it. */
11421.1Smycroft	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
11431.1Smycroft#endif
11441.1Smycroft
11451.11Scgd	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
11461.11Scgd	    IPL_NET, feintr, sc);
11471.18Sexplorer
11481.18Sexplorer#if NRND > 0
11491.18Sexplorer	rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
11501.18Sexplorer			  RND_TYPE_NET);
11511.18Sexplorer#endif
11521.1Smycroft}
11531.1Smycroft
11541.1Smycroft/*
11551.1Smycroft * Reset interface.
11561.1Smycroft */
11571.1Smycroftvoid
11581.1Smycroftfe_reset(sc)
11591.1Smycroft	struct fe_softc *sc;
11601.1Smycroft{
11611.1Smycroft	int s;
11621.1Smycroft
11631.8Smycroft	s = splnet();
11641.1Smycroft	fe_stop(sc);
11651.1Smycroft	fe_init(sc);
11661.1Smycroft	splx(s);
11671.1Smycroft}
11681.1Smycroft
11691.1Smycroft/*
11701.1Smycroft * Stop everything on the interface.
11711.1Smycroft *
11721.1Smycroft * All buffered packets, both transmitting and receiving,
11731.1Smycroft * if any, will be lost by stopping the interface.
11741.1Smycroft */
11751.1Smycroftvoid
11761.1Smycroftfe_stop(sc)
11771.1Smycroft	struct fe_softc *sc;
11781.1Smycroft{
11791.1Smycroft
11801.1Smycroft#if FE_DEBUG >= 3
11811.1Smycroft	log(LOG_INFO, "%s: top of fe_stop()\n", sc->sc_dev.dv_xname);
11821.1Smycroft	fe_dump(LOG_INFO, sc);
11831.1Smycroft#endif
11841.1Smycroft
11851.1Smycroft	/* Disable interrupts. */
11861.1Smycroft	outb(sc->sc_iobase + FE_DLCR2, 0x00);
11871.1Smycroft	outb(sc->sc_iobase + FE_DLCR3, 0x00);
11881.1Smycroft
11891.1Smycroft	/* Stop interface hardware. */
11901.1Smycroft	delay(200);
11911.1Smycroft	outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
11921.1Smycroft	delay(200);
11931.1Smycroft
11941.1Smycroft	/* Clear all interrupt status. */
11951.1Smycroft	outb(sc->sc_iobase + FE_DLCR0, 0xFF);
11961.1Smycroft	outb(sc->sc_iobase + FE_DLCR1, 0xFF);
11971.1Smycroft
11981.1Smycroft	/* Put the chip in stand-by mode. */
11991.1Smycroft	delay(200);
12001.1Smycroft	outb(sc->sc_iobase + FE_DLCR7, sc->proto_dlcr7 | FE_D7_POWER_DOWN);
12011.1Smycroft	delay(200);
12021.1Smycroft
12031.1Smycroft	/* MAR loading can be delayed. */
12041.1Smycroft	sc->filter_change = 0;
12051.1Smycroft
12061.1Smycroft	/* Call a hook. */
12071.1Smycroft	if (sc->stop)
12081.1Smycroft		sc->stop(sc);
12091.1Smycroft
12101.1Smycroft#if DEBUG >= 3
12111.1Smycroft	log(LOG_INFO, "%s: end of fe_stop()\n", sc->sc_dev.dv_xname);
12121.1Smycroft	fe_dump(LOG_INFO, sc);
12131.1Smycroft#endif
12141.1Smycroft}
12151.1Smycroft
12161.1Smycroft/*
12171.1Smycroft * Device timeout/watchdog routine. Entered if the device neglects to
12181.1Smycroft * generate an interrupt after a transmit has been started on it.
12191.1Smycroft */
12201.1Smycroftvoid
12211.12Sthorpejfe_watchdog(ifp)
12221.12Sthorpej	struct ifnet *ifp;
12231.1Smycroft{
12241.12Sthorpej	struct fe_softc *sc = ifp->if_softc;
12251.1Smycroft
12261.1Smycroft	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
12271.1Smycroft#if FE_DEBUG >= 3
12281.1Smycroft	fe_dump(LOG_INFO, sc);
12291.1Smycroft#endif
12301.1Smycroft
12311.1Smycroft	/* Record how many packets are lost by this accident. */
12321.17Sis	sc->sc_ethercom.ec_if.if_oerrors += sc->txb_sched + sc->txb_count;
12331.1Smycroft
12341.1Smycroft	fe_reset(sc);
12351.1Smycroft}
12361.1Smycroft
12371.1Smycroft/*
12381.6Smycroft * Drop (skip) a packet from receive buffer in 86960 memory.
12391.6Smycroft */
12401.6Smycroftstatic inline void
12411.6Smycroftfe_droppacket(sc)
12421.6Smycroft	struct fe_softc *sc;
12431.6Smycroft{
12441.6Smycroft
12451.6Smycroft	outb(sc->sc_iobase + FE_BMPR14, FE_B14_FILTER | FE_B14_SKIP);
12461.6Smycroft}
12471.6Smycroft
12481.6Smycroft/*
12491.1Smycroft * Initialize device.
12501.1Smycroft */
12511.1Smycroftvoid
12521.1Smycroftfe_init(sc)
12531.1Smycroft	struct fe_softc *sc;
12541.1Smycroft{
12551.17Sis	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
12561.5Smycroft	int i;
12571.1Smycroft
12581.1Smycroft#if FE_DEBUG >= 3
12591.1Smycroft	log(LOG_INFO, "%s: top of fe_init()\n", sc->sc_dev.dv_xname);
12601.1Smycroft	fe_dump(LOG_INFO, sc);
12611.1Smycroft#endif
12621.1Smycroft
12631.1Smycroft	/* Reset transmitter flags. */
12641.1Smycroft	ifp->if_flags &= ~IFF_OACTIVE;
12651.1Smycroft	ifp->if_timer = 0;
12661.1Smycroft
12671.1Smycroft	sc->txb_free = sc->txb_size;
12681.1Smycroft	sc->txb_count = 0;
12691.1Smycroft	sc->txb_sched = 0;
12701.1Smycroft
12711.1Smycroft	/* Call a hook. */
12721.1Smycroft	if (sc->init)
12731.1Smycroft		sc->init(sc);
12741.1Smycroft
12751.1Smycroft#if FE_DEBUG >= 3
12761.1Smycroft	log(LOG_INFO, "%s: after init hook\n", sc->sc_dev.dv_xname);
12771.1Smycroft	fe_dump(LOG_INFO, sc);
12781.1Smycroft#endif
12791.1Smycroft
12801.1Smycroft	/*
12811.1Smycroft	 * Make sure to disable the chip, also.
12821.1Smycroft	 * This may also help re-programming the chip after
12831.1Smycroft	 * hot insertion of PCMCIAs.
12841.1Smycroft	 */
12851.1Smycroft	outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
12861.1Smycroft
12871.1Smycroft	/* Power up the chip and select register bank for DLCRs. */
12881.1Smycroft	delay(200);
12891.1Smycroft	outb(sc->sc_iobase + FE_DLCR7,
12901.1Smycroft	    sc->proto_dlcr7 | FE_D7_RBS_DLCR | FE_D7_POWER_UP);
12911.1Smycroft	delay(200);
12921.1Smycroft
12931.1Smycroft	/* Feed the station address. */
12941.1Smycroft	outblk(sc->sc_iobase + FE_DLCR8, sc->sc_enaddr, ETHER_ADDR_LEN);
12951.1Smycroft
12961.1Smycroft	/* Select the BMPR bank for runtime register access. */
12971.1Smycroft	outb(sc->sc_iobase + FE_DLCR7,
12981.1Smycroft	    sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP);
12991.1Smycroft
13001.1Smycroft	/* Initialize registers. */
13011.1Smycroft	outb(sc->sc_iobase + FE_DLCR0, 0xFF);	/* Clear all bits. */
13021.1Smycroft	outb(sc->sc_iobase + FE_DLCR1, 0xFF);	/* ditto. */
13031.1Smycroft	outb(sc->sc_iobase + FE_DLCR2, 0x00);
13041.1Smycroft	outb(sc->sc_iobase + FE_DLCR3, 0x00);
13051.1Smycroft	outb(sc->sc_iobase + FE_DLCR4, sc->proto_dlcr4);
13061.1Smycroft	outb(sc->sc_iobase + FE_DLCR5, sc->proto_dlcr5);
13071.1Smycroft	outb(sc->sc_iobase + FE_BMPR10, 0x00);
13081.1Smycroft	outb(sc->sc_iobase + FE_BMPR11, FE_B11_CTRL_SKIP);
13091.1Smycroft	outb(sc->sc_iobase + FE_BMPR12, 0x00);
13101.1Smycroft	outb(sc->sc_iobase + FE_BMPR13, sc->proto_bmpr13);
13111.6Smycroft	outb(sc->sc_iobase + FE_BMPR14, FE_B14_FILTER);
13121.1Smycroft	outb(sc->sc_iobase + FE_BMPR15, 0x00);
13131.1Smycroft
13141.1Smycroft#if FE_DEBUG >= 3
13151.1Smycroft	log(LOG_INFO, "%s: just before enabling DLC\n", sc->sc_dev.dv_xname);
13161.1Smycroft	fe_dump(LOG_INFO, sc);
13171.1Smycroft#endif
13181.1Smycroft
13191.1Smycroft	/* Enable interrupts. */
13201.1Smycroft	outb(sc->sc_iobase + FE_DLCR2, FE_TMASK);
13211.1Smycroft	outb(sc->sc_iobase + FE_DLCR3, FE_RMASK);
13221.1Smycroft
13231.1Smycroft	/* Enable transmitter and receiver. */
13241.1Smycroft	delay(200);
13251.1Smycroft	outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_ENABLE);
13261.1Smycroft	delay(200);
13271.1Smycroft
13281.1Smycroft#if FE_DEBUG >= 3
13291.1Smycroft	log(LOG_INFO, "%s: just after enabling DLC\n", sc->sc_dev.dv_xname);
13301.1Smycroft	fe_dump(LOG_INFO, sc);
13311.1Smycroft#endif
13321.1Smycroft
13331.1Smycroft	/*
13341.1Smycroft	 * Make sure to empty the receive buffer.
13351.1Smycroft	 *
13361.1Smycroft	 * This may be redundant, but *if* the receive buffer were full
13371.1Smycroft	 * at this point, the driver would hang.  I have experienced
13381.1Smycroft	 * some strange hangups just after UP.  I hope the following
13391.1Smycroft	 * code solve the problem.
13401.1Smycroft	 *
13411.1Smycroft	 * I have changed the order of hardware initialization.
13421.1Smycroft	 * I think the receive buffer cannot have any packets at this
13431.1Smycroft	 * point in this version.  The following code *must* be
13441.1Smycroft	 * redundant now.  FIXME.
13451.1Smycroft	 */
13461.1Smycroft	for (i = 0; i < FE_MAX_RECV_COUNT; i++) {
13471.1Smycroft		if (inb(sc->sc_iobase + FE_DLCR5) & FE_D5_BUFEMP)
13481.1Smycroft			break;
13491.6Smycroft		fe_droppacket(sc);
13501.1Smycroft	}
13511.1Smycroft#if FE_DEBUG >= 1
13521.1Smycroft	if (i >= FE_MAX_RECV_COUNT) {
13531.1Smycroft		log(LOG_ERR, "%s: cannot empty receive buffer\n",
13541.1Smycroft		    sc->sc_dev.dv_xname);
13551.1Smycroft	}
13561.1Smycroft#endif
13571.1Smycroft#if FE_DEBUG >= 3
13581.1Smycroft	if (i < FE_MAX_RECV_COUNT) {
13591.1Smycroft		log(LOG_INFO, "%s: receive buffer emptied (%d)\n",
13601.1Smycroft		    sc->sc_dev.dv_xname, i);
13611.1Smycroft	}
13621.1Smycroft#endif
13631.1Smycroft
13641.1Smycroft#if FE_DEBUG >= 3
13651.1Smycroft	log(LOG_INFO, "%s: after ERB loop\n", sc->sc_dev.dv_xname);
13661.1Smycroft	fe_dump(LOG_INFO, sc);
13671.1Smycroft#endif
13681.1Smycroft
13691.1Smycroft	/* Do we need this here? */
13701.1Smycroft	outb(sc->sc_iobase + FE_DLCR0, 0xFF);	/* Clear all bits. */
13711.1Smycroft	outb(sc->sc_iobase + FE_DLCR1, 0xFF);	/* ditto. */
13721.1Smycroft
13731.1Smycroft#if FE_DEBUG >= 3
13741.1Smycroft	log(LOG_INFO, "%s: after FIXME\n", sc->sc_dev.dv_xname);
13751.1Smycroft	fe_dump(LOG_INFO, sc);
13761.1Smycroft#endif
13771.1Smycroft
13781.1Smycroft	/* Set 'running' flag. */
13791.1Smycroft	ifp->if_flags |= IFF_RUNNING;
13801.1Smycroft
13811.1Smycroft	/*
13821.1Smycroft	 * At this point, the interface is runnung properly,
13831.1Smycroft	 * except that it receives *no* packets.  we then call
13841.1Smycroft	 * fe_setmode() to tell the chip what packets to be
13851.1Smycroft	 * received, based on the if_flags and multicast group
13861.1Smycroft	 * list.  It completes the initialization process.
13871.1Smycroft	 */
13881.1Smycroft	fe_setmode(sc);
13891.1Smycroft
13901.1Smycroft#if FE_DEBUG >= 3
13911.1Smycroft	log(LOG_INFO, "%s: after setmode\n", sc->sc_dev.dv_xname);
13921.1Smycroft	fe_dump(LOG_INFO, sc);
13931.1Smycroft#endif
13941.1Smycroft
13951.1Smycroft	/* ...and attempt to start output. */
13961.1Smycroft	fe_start(ifp);
13971.1Smycroft
13981.1Smycroft#if FE_DEBUG >= 3
13991.1Smycroft	log(LOG_INFO, "%s: end of fe_init()\n", sc->sc_dev.dv_xname);
14001.1Smycroft	fe_dump(LOG_INFO, sc);
14011.1Smycroft#endif
14021.1Smycroft}
14031.1Smycroft
14041.1Smycroft/*
14051.1Smycroft * This routine actually starts the transmission on the interface
14061.1Smycroft */
14071.1Smycroftstatic inline void
14081.1Smycroftfe_xmit(sc)
14091.1Smycroft	struct fe_softc *sc;
14101.1Smycroft{
14111.1Smycroft
14121.1Smycroft	/*
14131.1Smycroft	 * Set a timer just in case we never hear from the board again.
14141.1Smycroft	 * We use longer timeout for multiple packet transmission.
14151.1Smycroft	 * I'm not sure this timer value is appropriate.  FIXME.
14161.1Smycroft	 */
14171.17Sis	sc->sc_ethercom.ec_if.if_timer = 1 + sc->txb_count;
14181.1Smycroft
14191.1Smycroft	/* Update txb variables. */
14201.1Smycroft	sc->txb_sched = sc->txb_count;
14211.1Smycroft	sc->txb_count = 0;
14221.1Smycroft	sc->txb_free = sc->txb_size;
14231.1Smycroft
14241.1Smycroft#if FE_DELAYED_PADDING
14251.1Smycroft	/* Omit the postponed padding process. */
14261.1Smycroft	sc->txb_padding = 0;
14271.1Smycroft#endif
14281.1Smycroft
14291.1Smycroft	/* Start transmitter, passing packets in TX buffer. */
14301.1Smycroft	outb(sc->sc_iobase + FE_BMPR10, sc->txb_sched | FE_B10_START);
14311.1Smycroft}
14321.1Smycroft
14331.1Smycroft/*
14341.1Smycroft * Start output on interface.
14351.1Smycroft * We make two assumptions here:
14361.8Smycroft *  1) that the current priority is set to splnet _before_ this code
14371.1Smycroft *     is called *and* is returned to the appropriate priority after
14381.1Smycroft *     return
14391.1Smycroft *  2) that the IFF_OACTIVE flag is checked before this code is called
14401.1Smycroft *     (i.e. that the output part of the interface is idle)
14411.1Smycroft */
14421.1Smycroftvoid
14431.1Smycroftfe_start(ifp)
14441.1Smycroft	struct ifnet *ifp;
14451.1Smycroft{
14461.12Sthorpej	struct fe_softc *sc = ifp->if_softc;
14471.1Smycroft	struct mbuf *m;
14481.1Smycroft
14491.1Smycroft#if FE_DEBUG >= 1
14501.1Smycroft	/* Just a sanity check. */
14511.1Smycroft	if ((sc->txb_count == 0) != (sc->txb_free == sc->txb_size)) {
14521.1Smycroft		/*
14531.1Smycroft		 * Txb_count and txb_free co-works to manage the
14541.1Smycroft		 * transmission buffer.  Txb_count keeps track of the
14551.1Smycroft		 * used potion of the buffer, while txb_free does unused
14561.1Smycroft		 * potion.  So, as long as the driver runs properly,
14571.1Smycroft		 * txb_count is zero if and only if txb_free is same
14581.1Smycroft		 * as txb_size (which represents whole buffer.)
14591.1Smycroft		 */
14601.1Smycroft		log(LOG_ERR, "%s: inconsistent txb variables (%d, %d)\n",
14611.1Smycroft		    sc->sc_dev.dv_xname, sc->txb_count, sc->txb_free);
14621.1Smycroft		/*
14631.1Smycroft		 * So, what should I do, then?
14641.1Smycroft		 *
14651.1Smycroft		 * We now know txb_count and txb_free contradicts.  We
14661.1Smycroft		 * cannot, however, tell which is wrong.  More
14671.1Smycroft		 * over, we cannot peek 86960 transmission buffer or
14681.1Smycroft		 * reset the transmission buffer.  (In fact, we can
14691.1Smycroft		 * reset the entire interface.  I don't want to do it.)
14701.1Smycroft		 *
14711.1Smycroft		 * If txb_count is incorrect, leaving it as is will cause
14721.1Smycroft		 * sending of gabages after next interrupt.  We have to
14731.1Smycroft		 * avoid it.  Hence, we reset the txb_count here.  If
14741.1Smycroft		 * txb_free was incorrect, resetting txb_count just loose
14751.1Smycroft		 * some packets.  We can live with it.
14761.1Smycroft		 */
14771.1Smycroft		sc->txb_count = 0;
14781.1Smycroft	}
14791.1Smycroft#endif
14801.1Smycroft
14811.1Smycroft#if FE_DEBUG >= 1
14821.1Smycroft	/*
14831.1Smycroft	 * First, see if there are buffered packets and an idle
14841.1Smycroft	 * transmitter - should never happen at this point.
14851.1Smycroft	 */
14861.1Smycroft	if ((sc->txb_count > 0) && (sc->txb_sched == 0)) {
14871.1Smycroft		log(LOG_ERR, "%s: transmitter idle with %d buffered packets\n",
14881.1Smycroft		    sc->sc_dev.dv_xname, sc->txb_count);
14891.1Smycroft		fe_xmit(sc);
14901.1Smycroft	}
14911.1Smycroft#endif
14921.1Smycroft
14931.1Smycroft	/*
14941.1Smycroft	 * Stop accepting more transmission packets temporarily, when
14951.1Smycroft	 * a filter change request is delayed.  Updating the MARs on
14961.1Smycroft	 * 86960 flushes the transmisstion buffer, so it is delayed
14971.1Smycroft	 * until all buffered transmission packets have been sent
14981.1Smycroft	 * out.
14991.1Smycroft	 */
15001.1Smycroft	if (sc->filter_change) {
15011.1Smycroft		/*
15021.1Smycroft		 * Filter change requst is delayed only when the DLC is
15031.1Smycroft		 * working.  DLC soon raise an interrupt after finishing
15041.1Smycroft		 * the work.
15051.1Smycroft		 */
15061.1Smycroft		goto indicate_active;
15071.1Smycroft	}
15081.1Smycroft
15091.1Smycroft	for (;;) {
15101.1Smycroft		/*
15111.1Smycroft		 * See if there is room to put another packet in the buffer.
15121.1Smycroft		 * We *could* do better job by peeking the send queue to
15131.1Smycroft		 * know the length of the next packet.  Current version just
15141.1Smycroft		 * tests against the worst case (i.e., longest packet).  FIXME.
15151.1Smycroft		 *
15161.1Smycroft		 * When adding the packet-peek feature, don't forget adding a
15171.1Smycroft		 * test on txb_count against QUEUEING_MAX.
15181.1Smycroft		 * There is a little chance the packet count exceeds
15191.1Smycroft		 * the limit.  Assume transmission buffer is 8KB (2x8KB
15201.1Smycroft		 * configuration) and an application sends a bunch of small
15211.1Smycroft		 * (i.e., minimum packet sized) packets rapidly.  An 8KB
15221.1Smycroft		 * buffer can hold 130 blocks of 62 bytes long...
15231.1Smycroft		 */
15241.1Smycroft		if (sc->txb_free < ETHER_MAX_LEN + FE_DATA_LEN_LEN) {
15251.1Smycroft			/* No room. */
15261.1Smycroft			goto indicate_active;
15271.1Smycroft		}
15281.1Smycroft
15291.1Smycroft#if FE_SINGLE_TRANSMISSION
15301.1Smycroft		if (sc->txb_count > 0) {
15311.1Smycroft			/* Just one packet per a transmission buffer. */
15321.1Smycroft			goto indicate_active;
15331.1Smycroft		}
15341.1Smycroft#endif
15351.1Smycroft
15361.1Smycroft		/*
15371.1Smycroft		 * Get the next mbuf chain for a packet to send.
15381.1Smycroft		 */
15391.1Smycroft		IF_DEQUEUE(&ifp->if_snd, m);
15401.1Smycroft		if (m == 0) {
15411.1Smycroft			/* No more packets to send. */
15421.1Smycroft			goto indicate_inactive;
15431.1Smycroft		}
15441.1Smycroft
15451.6Smycroft#if NBPFILTER > 0
15461.6Smycroft		/* Tap off here if there is a BPF listener. */
15471.6Smycroft		if (ifp->if_bpf)
15481.6Smycroft			bpf_mtap(ifp->if_bpf, m);
15491.6Smycroft#endif
15501.6Smycroft
15511.1Smycroft		/*
15521.1Smycroft		 * Copy the mbuf chain into the transmission buffer.
15531.1Smycroft		 * txb_* variables are updated as necessary.
15541.1Smycroft		 */
15551.1Smycroft		fe_write_mbufs(sc, m);
15561.1Smycroft
15571.6Smycroft		m_freem(m);
15581.6Smycroft
15591.1Smycroft		/* Start transmitter if it's idle. */
15601.1Smycroft		if (sc->txb_sched == 0)
15611.1Smycroft			fe_xmit(sc);
15621.1Smycroft	}
15631.1Smycroft
15641.1Smycroftindicate_inactive:
15651.1Smycroft	/*
15661.1Smycroft	 * We are using the !OACTIVE flag to indicate to
15671.1Smycroft	 * the outside world that we can accept an
15681.1Smycroft	 * additional packet rather than that the
15691.1Smycroft	 * transmitter is _actually_ active.  Indeed, the
15701.1Smycroft	 * transmitter may be active, but if we haven't
15711.1Smycroft	 * filled all the buffers with data then we still
15721.1Smycroft	 * want to accept more.
15731.1Smycroft	 */
15741.1Smycroft	ifp->if_flags &= ~IFF_OACTIVE;
15751.1Smycroft	return;
15761.1Smycroft
15771.1Smycroftindicate_active:
15781.1Smycroft	/*
15791.1Smycroft	 * The transmitter is active, and there are no room for
15801.1Smycroft	 * more outgoing packets in the transmission buffer.
15811.1Smycroft	 */
15821.1Smycroft	ifp->if_flags |= IFF_OACTIVE;
15831.1Smycroft	return;
15841.1Smycroft}
15851.1Smycroft
15861.1Smycroft/*
15871.1Smycroft * Transmission interrupt handler
15881.1Smycroft * The control flow of this function looks silly.  FIXME.
15891.1Smycroft */
15901.1Smycroftvoid
15911.1Smycroftfe_tint(sc, tstat)
15921.1Smycroft	struct fe_softc *sc;
15931.1Smycroft	u_char tstat;
15941.1Smycroft{
15951.17Sis	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
15961.1Smycroft	int left;
15971.1Smycroft	int col;
15981.1Smycroft
15991.1Smycroft	/*
16001.1Smycroft	 * Handle "excessive collision" interrupt.
16011.1Smycroft	 */
16021.1Smycroft	if (tstat & FE_D0_COLL16) {
16031.1Smycroft		/*
16041.1Smycroft		 * Find how many packets (including this collided one)
16051.1Smycroft		 * are left unsent in transmission buffer.
16061.1Smycroft		 */
16071.1Smycroft		left = inb(sc->sc_iobase + FE_BMPR10);
16081.1Smycroft
16091.1Smycroft#if FE_DEBUG >= 2
16101.1Smycroft		log(LOG_WARNING, "%s: excessive collision (%d/%d)\n",
16111.1Smycroft		    sc->sc_dev.dv_xname, left, sc->txb_sched);
16121.1Smycroft#endif
16131.1Smycroft#if FE_DEBUG >= 3
16141.1Smycroft		fe_dump(LOG_INFO, sc);
16151.1Smycroft#endif
16161.1Smycroft
16171.1Smycroft		/*
16181.1Smycroft		 * Update statistics.
16191.1Smycroft		 */
16201.1Smycroft		ifp->if_collisions += 16;
16211.1Smycroft		ifp->if_oerrors++;
16221.1Smycroft		ifp->if_opackets += sc->txb_sched - left;
16231.1Smycroft
16241.1Smycroft		/*
16251.1Smycroft		 * Collision statistics has been updated.
16261.1Smycroft		 * Clear the collision flag on 86960 now to avoid confusion.
16271.1Smycroft		 */
16281.1Smycroft		outb(sc->sc_iobase + FE_DLCR0, FE_D0_COLLID);
16291.1Smycroft
16301.1Smycroft		/*
16311.1Smycroft		 * Restart transmitter, skipping the
16321.1Smycroft		 * collided packet.
16331.1Smycroft		 *
16341.1Smycroft		 * We *must* skip the packet to keep network running
16351.1Smycroft		 * properly.  Excessive collision error is an
16361.1Smycroft		 * indication of the network overload.  If we
16371.1Smycroft		 * tried sending the same packet after excessive
16381.1Smycroft		 * collision, the network would be filled with
16391.1Smycroft		 * out-of-time packets.  Packets belonging
16401.1Smycroft		 * to reliable transport (such as TCP) are resent
16411.1Smycroft		 * by some upper layer.
16421.1Smycroft		 */
16431.1Smycroft		outb(sc->sc_iobase + FE_BMPR11,
16441.1Smycroft		    FE_B11_CTRL_SKIP | FE_B11_MODE1);
16451.1Smycroft		sc->txb_sched = left - 1;
16461.1Smycroft	}
16471.1Smycroft
16481.1Smycroft	/*
16491.1Smycroft	 * Handle "transmission complete" interrupt.
16501.1Smycroft	 */
16511.1Smycroft	if (tstat & FE_D0_TXDONE) {
16521.1Smycroft		/*
16531.1Smycroft		 * Add in total number of collisions on last
16541.1Smycroft		 * transmission.  We also clear "collision occurred" flag
16551.1Smycroft		 * here.
16561.1Smycroft		 *
16571.1Smycroft		 * 86960 has a design flow on collision count on multiple
16581.1Smycroft		 * packet transmission.  When we send two or more packets
16591.1Smycroft		 * with one start command (that's what we do when the
16601.1Smycroft		 * transmission queue is clauded), 86960 informs us number
16611.1Smycroft		 * of collisions occured on the last packet on the
16621.1Smycroft		 * transmission only.  Number of collisions on previous
16631.1Smycroft		 * packets are lost.  I have told that the fact is clearly
16641.1Smycroft		 * stated in the Fujitsu document.
16651.1Smycroft		 *
16661.1Smycroft		 * I considered not to mind it seriously.  Collision
16671.1Smycroft		 * count is not so important, anyway.  Any comments?  FIXME.
16681.1Smycroft		 */
16691.1Smycroft
16701.1Smycroft		if (inb(sc->sc_iobase + FE_DLCR0) & FE_D0_COLLID) {
16711.1Smycroft			/* Clear collision flag. */
16721.1Smycroft			outb(sc->sc_iobase + FE_DLCR0, FE_D0_COLLID);
16731.1Smycroft
16741.1Smycroft			/* Extract collision count from 86960. */
16751.1Smycroft			col = inb(sc->sc_iobase + FE_DLCR4) & FE_D4_COL;
16761.1Smycroft			if (col == 0) {
16771.1Smycroft				/*
16781.1Smycroft				 * Status register indicates collisions,
16791.1Smycroft				 * while the collision count is zero.
16801.1Smycroft				 * This can happen after multiple packet
16811.1Smycroft				 * transmission, indicating that one or more
16821.1Smycroft				 * previous packet(s) had been collided.
16831.1Smycroft				 *
16841.1Smycroft				 * Since the accurate number of collisions
16851.1Smycroft				 * has been lost, we just guess it as 1;
16861.1Smycroft				 * Am I too optimistic?  FIXME.
16871.1Smycroft				 */
16881.1Smycroft				col = 1;
16891.1Smycroft			} else
16901.1Smycroft				col >>= FE_D4_COL_SHIFT;
16911.1Smycroft			ifp->if_collisions += col;
16921.1Smycroft#if FE_DEBUG >= 4
16931.1Smycroft			log(LOG_WARNING, "%s: %d collision%s (%d)\n",
16941.1Smycroft			    sc->sc_dev.dv_xname, col, col == 1 ? "" : "s",
16951.1Smycroft			    sc->txb_sched);
16961.1Smycroft#endif
16971.1Smycroft		}
16981.1Smycroft
16991.1Smycroft		/*
17001.1Smycroft		 * Update total number of successfully
17011.1Smycroft		 * transmitted packets.
17021.1Smycroft		 */
17031.1Smycroft		ifp->if_opackets += sc->txb_sched;
17041.1Smycroft		sc->txb_sched = 0;
17051.10Smycroft	}
17061.1Smycroft
17071.10Smycroft	if (sc->txb_sched == 0) {
17081.1Smycroft		/*
17091.1Smycroft		 * The transmitter is no more active.
17101.1Smycroft		 * Reset output active flag and watchdog timer.
17111.1Smycroft		 */
17121.1Smycroft		ifp->if_flags &= ~IFF_OACTIVE;
17131.1Smycroft		ifp->if_timer = 0;
17141.1Smycroft
17151.1Smycroft		/*
17161.1Smycroft		 * If more data is ready to transmit in the buffer, start
17171.1Smycroft		 * transmitting them.  Otherwise keep transmitter idle,
17181.1Smycroft		 * even if more data is queued.  This gives receive
17191.1Smycroft		 * process a slight priority.
17201.1Smycroft		 */
17211.1Smycroft		if (sc->txb_count > 0)
17221.1Smycroft			fe_xmit(sc);
17231.1Smycroft	}
17241.1Smycroft}
17251.1Smycroft
17261.1Smycroft/*
17271.1Smycroft * Ethernet interface receiver interrupt.
17281.1Smycroft */
17291.1Smycroftvoid
17301.1Smycroftfe_rint(sc, rstat)
17311.1Smycroft	struct fe_softc *sc;
17321.1Smycroft	u_char rstat;
17331.1Smycroft{
17341.17Sis	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
17351.1Smycroft	int len;
17361.1Smycroft	u_char status;
17371.1Smycroft	int i;
17381.1Smycroft
17391.1Smycroft	/*
17401.1Smycroft	 * Update statistics if this interrupt is caused by an error.
17411.1Smycroft	 */
17421.1Smycroft	if (rstat & (FE_D1_OVRFLO | FE_D1_CRCERR |
17431.1Smycroft		     FE_D1_ALGERR | FE_D1_SRTPKT)) {
17441.1Smycroft#if FE_DEBUG >= 3
17451.1Smycroft		log(LOG_WARNING, "%s: receive error: %b\n",
17461.1Smycroft		    sc->sc_dev.dv_xname, rstat, FE_D1_ERRBITS);
17471.1Smycroft#endif
17481.1Smycroft		ifp->if_ierrors++;
17491.1Smycroft	}
17501.1Smycroft
17511.1Smycroft	/*
17521.1Smycroft	 * MB86960 has a flag indicating "receive queue empty."
17531.1Smycroft	 * We just loop cheking the flag to pull out all received
17541.1Smycroft	 * packets.
17551.1Smycroft	 *
17561.1Smycroft	 * We limit the number of iterrations to avoid infinite loop.
17571.1Smycroft	 * It can be caused by a very slow CPU (some broken
17581.1Smycroft	 * peripheral may insert incredible number of wait cycles)
17591.1Smycroft	 * or, worse, by a broken MB86960 chip.
17601.1Smycroft	 */
17611.1Smycroft	for (i = 0; i < FE_MAX_RECV_COUNT; i++) {
17621.1Smycroft		/* Stop the iterration if 86960 indicates no packets. */
17631.1Smycroft		if (inb(sc->sc_iobase + FE_DLCR5) & FE_D5_BUFEMP)
17641.1Smycroft			break;
17651.1Smycroft
17661.1Smycroft		/*
17671.1Smycroft		 * Extract A receive status byte.
17681.1Smycroft		 * As our 86960 is in 16 bit bus access mode, we have to
17691.1Smycroft		 * use inw() to get the status byte.  The significant
17701.1Smycroft		 * value is returned in lower 8 bits.
17711.1Smycroft		 */
17721.1Smycroft		status = (u_char)inw(sc->sc_iobase + FE_BMPR8);
17731.1Smycroft#if FE_DEBUG >= 4
17741.1Smycroft		log(LOG_INFO, "%s: receive status = %02x\n",
17751.1Smycroft		    sc->sc_dev.dv_xname, status);
17761.1Smycroft#endif
17771.1Smycroft
17781.1Smycroft		/*
17791.1Smycroft		 * If there was an error, update statistics and drop
17801.1Smycroft		 * the packet, unless the interface is in promiscuous
17811.1Smycroft		 * mode.
17821.1Smycroft		 */
17831.1Smycroft		if ((status & 0xF0) != 0x20) {	/* XXXX ? */
17841.1Smycroft			if ((ifp->if_flags & IFF_PROMISC) == 0) {
17851.1Smycroft				ifp->if_ierrors++;
17861.1Smycroft				fe_droppacket(sc);
17871.1Smycroft				continue;
17881.1Smycroft			}
17891.1Smycroft		}
17901.1Smycroft
17911.1Smycroft		/*
17921.1Smycroft		 * Extract the packet length.
17931.1Smycroft		 * It is a sum of a header (14 bytes) and a payload.
17941.1Smycroft		 * CRC has been stripped off by the 86960.
17951.1Smycroft		 */
17961.1Smycroft		len = inw(sc->sc_iobase + FE_BMPR8);
17971.1Smycroft
17981.1Smycroft		/*
17991.1Smycroft		 * MB86965 checks the packet length and drop big packet
18001.1Smycroft		 * before passing it to us.  There are no chance we can
18011.1Smycroft		 * get [crufty] packets.  Hence, if the length exceeds
18021.1Smycroft		 * the specified limit, it means some serious failure,
18031.1Smycroft		 * such as out-of-sync on receive buffer management.
18041.1Smycroft		 *
18051.1Smycroft		 * Is this statement true?  FIXME.
18061.1Smycroft		 */
18071.1Smycroft		if (len > ETHER_MAX_LEN || len < ETHER_HDR_SIZE) {
18081.1Smycroft#if FE_DEBUG >= 2
18091.1Smycroft			log(LOG_WARNING,
18101.1Smycroft			    "%s: received a %s packet? (%u bytes)\n",
18111.1Smycroft			    sc->sc_dev.dv_xname,
18121.1Smycroft			    len < ETHER_HDR_SIZE ? "partial" : "big", len);
18131.1Smycroft#endif
18141.1Smycroft			ifp->if_ierrors++;
18151.1Smycroft			fe_droppacket(sc);
18161.1Smycroft			continue;
18171.1Smycroft		}
18181.1Smycroft
18191.1Smycroft		/*
18201.1Smycroft		 * Check for a short (RUNT) packet.  We *do* check
18211.1Smycroft		 * but do nothing other than print a message.
18221.1Smycroft		 * Short packets are illegal, but does nothing bad
18231.1Smycroft		 * if it carries data for upper layer.
18241.1Smycroft		 */
18251.1Smycroft#if FE_DEBUG >= 2
18261.1Smycroft		if (len < ETHER_MIN_LEN) {
18271.1Smycroft			log(LOG_WARNING,
18281.1Smycroft			     "%s: received a short packet? (%u bytes)\n",
18291.1Smycroft			     sc->sc_dev.dv_xname, len);
18301.1Smycroft		}
18311.1Smycroft#endif
18321.1Smycroft
18331.1Smycroft		/*
18341.1Smycroft		 * Go get a packet.
18351.1Smycroft		 */
18361.1Smycroft		if (!fe_get_packet(sc, len)) {
18371.1Smycroft			/* Skip a packet, updating statistics. */
18381.1Smycroft#if FE_DEBUG >= 2
18391.1Smycroft			log(LOG_WARNING,
18401.1Smycroft			    "%s: out of mbufs; dropping packet (%u bytes)\n",
18411.1Smycroft			    sc->sc_dev.dv_xname, len);
18421.1Smycroft#endif
18431.1Smycroft			ifp->if_ierrors++;
18441.1Smycroft			fe_droppacket(sc);
18451.1Smycroft
18461.1Smycroft			/*
18471.1Smycroft			 * We stop receiving packets, even if there are
18481.1Smycroft			 * more in the buffer.  We hope we can get more
18491.1Smycroft			 * mbufs next time.
18501.1Smycroft			 */
18511.1Smycroft			return;
18521.1Smycroft		}
18531.1Smycroft
18541.1Smycroft		/* Successfully received a packet.  Update stat. */
18551.1Smycroft		ifp->if_ipackets++;
18561.1Smycroft	}
18571.1Smycroft}
18581.1Smycroft
18591.1Smycroft/*
18601.1Smycroft * Ethernet interface interrupt processor
18611.1Smycroft */
18621.1Smycroftint
18631.1Smycroftfeintr(arg)
18641.1Smycroft	void *arg;
18651.1Smycroft{
18661.1Smycroft	struct fe_softc *sc = arg;
18671.1Smycroft	u_char tstat, rstat;
18681.1Smycroft
18691.1Smycroft#if FE_DEBUG >= 4
18701.1Smycroft	log(LOG_INFO, "%s: feintr()\n", sc->sc_dev.dv_xname);
18711.1Smycroft	fe_dump(LOG_INFO, sc);
18721.1Smycroft#endif
18731.1Smycroft
18741.1Smycroft	/*
18751.1Smycroft	 * Get interrupt conditions, masking unneeded flags.
18761.1Smycroft	 */
18771.1Smycroft	tstat = inb(sc->sc_iobase + FE_DLCR0) & FE_TMASK;
18781.1Smycroft	rstat = inb(sc->sc_iobase + FE_DLCR1) & FE_RMASK;
18791.1Smycroft	if (tstat == 0 && rstat == 0)
18801.1Smycroft		return (0);
18811.1Smycroft
18821.1Smycroft	/*
18831.1Smycroft	 * Loop until there are no more new interrupt conditions.
18841.1Smycroft	 */
18851.1Smycroft	for (;;) {
18861.1Smycroft		/*
18871.1Smycroft		 * Reset the conditions we are acknowledging.
18881.1Smycroft		 */
18891.1Smycroft		outb(sc->sc_iobase + FE_DLCR0, tstat);
18901.1Smycroft		outb(sc->sc_iobase + FE_DLCR1, rstat);
18911.1Smycroft
18921.1Smycroft		/*
18931.1Smycroft		 * Handle transmitter interrupts. Handle these first because
18941.1Smycroft		 * the receiver will reset the board under some conditions.
18951.1Smycroft		 */
18961.1Smycroft		if (tstat != 0)
18971.1Smycroft			fe_tint(sc, tstat);
18981.1Smycroft
18991.1Smycroft		/*
19001.1Smycroft		 * Handle receiver interrupts.
19011.1Smycroft		 */
19021.1Smycroft		if (rstat != 0)
19031.1Smycroft			fe_rint(sc, rstat);
19041.1Smycroft
19051.1Smycroft		/*
19061.1Smycroft		 * Update the multicast address filter if it is
19071.1Smycroft		 * needed and possible.  We do it now, because
19081.1Smycroft		 * we can make sure the transmission buffer is empty,
19091.1Smycroft		 * and there is a good chance that the receive queue
19101.1Smycroft		 * is empty.  It will minimize the possibility of
19111.1Smycroft		 * packet lossage.
19121.1Smycroft		 */
19131.1Smycroft		if (sc->filter_change &&
19141.1Smycroft		    sc->txb_count == 0 && sc->txb_sched == 0) {
19151.1Smycroft			fe_loadmar(sc);
19161.17Sis			sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
19171.1Smycroft		}
19181.1Smycroft
19191.1Smycroft		/*
19201.1Smycroft		 * If it looks like the transmitter can take more data,
19211.1Smycroft		 * attempt to start output on the interface. This is done
19221.1Smycroft		 * after handling the receiver interrupt to give the
19231.1Smycroft		 * receive operation priority.
19241.1Smycroft		 */
19251.17Sis		if ((sc->sc_ethercom.ec_if.if_flags & IFF_OACTIVE) == 0)
19261.17Sis			fe_start(&sc->sc_ethercom.ec_if);
19271.18Sexplorer
19281.18Sexplorer#if NRND > 0
19291.18Sexplorer		if (rstat != 0 || tstat != 0)
19301.18Sexplorer			rnd_add_uint32(&sc->rnd_source, rstat + tstat);
19311.18Sexplorer#endif
19321.1Smycroft
19331.1Smycroft		/*
19341.1Smycroft		 * Get interrupt conditions, masking unneeded flags.
19351.1Smycroft		 */
19361.1Smycroft		tstat = inb(sc->sc_iobase + FE_DLCR0) & FE_TMASK;
19371.1Smycroft		rstat = inb(sc->sc_iobase + FE_DLCR1) & FE_RMASK;
19381.1Smycroft		if (tstat == 0 && rstat == 0)
19391.1Smycroft			return (1);
19401.1Smycroft	}
19411.1Smycroft}
19421.1Smycroft
19431.1Smycroft/*
19441.1Smycroft * Process an ioctl request.  This code needs some work - it looks pretty ugly.
19451.1Smycroft */
19461.1Smycroftint
19471.1Smycroftfe_ioctl(ifp, command, data)
19481.1Smycroft	register struct ifnet *ifp;
19491.1Smycroft	u_long command;
19501.1Smycroft	caddr_t data;
19511.1Smycroft{
19521.12Sthorpej	struct fe_softc *sc = ifp->if_softc;
19531.1Smycroft	register struct ifaddr *ifa = (struct ifaddr *)data;
19541.1Smycroft	struct ifreq *ifr = (struct ifreq *)data;
19551.1Smycroft	int s, error = 0;
19561.1Smycroft
19571.1Smycroft#if FE_DEBUG >= 3
19581.1Smycroft	log(LOG_INFO, "%s: ioctl(%x)\n", sc->sc_dev.dv_xname, command);
19591.1Smycroft#endif
19601.1Smycroft
19611.8Smycroft	s = splnet();
19621.1Smycroft
19631.1Smycroft	switch (command) {
19641.1Smycroft
19651.1Smycroft	case SIOCSIFADDR:
19661.1Smycroft		ifp->if_flags |= IFF_UP;
19671.1Smycroft
19681.1Smycroft		switch (ifa->ifa_addr->sa_family) {
19691.1Smycroft#ifdef INET
19701.1Smycroft		case AF_INET:
19711.1Smycroft			fe_init(sc);
19721.17Sis			arp_ifinit(ifp, ifa);
19731.1Smycroft			break;
19741.1Smycroft#endif
19751.1Smycroft#ifdef NS
19761.1Smycroft		case AF_NS:
19771.1Smycroft		    {
19781.1Smycroft			register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
19791.1Smycroft
19801.1Smycroft			if (ns_nullhost(*ina))
19811.1Smycroft				ina->x_host =
19821.17Sis				    *(union ns_host *)(sc->sc_enaddr);
19831.17Sis			else {
19841.17Sis				bcopy(ina->x_host.c_host, sc->sc_enaddr,
19851.17Sis				    ETHER_ADDR_LEN);
19861.17Sis				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
19871.17Sis				    ETHER_ADDR_LEN);
19881.17Sis			}
19891.1Smycroft			/* Set new address. */
19901.1Smycroft			fe_init(sc);
19911.1Smycroft			break;
19921.1Smycroft		    }
19931.1Smycroft#endif
19941.1Smycroft		default:
19951.1Smycroft			fe_init(sc);
19961.1Smycroft			break;
19971.1Smycroft		}
19981.1Smycroft		break;
19991.1Smycroft
20001.1Smycroft	case SIOCSIFFLAGS:
20011.1Smycroft		if ((ifp->if_flags & IFF_UP) == 0 &&
20021.1Smycroft		    (ifp->if_flags & IFF_RUNNING) != 0) {
20031.1Smycroft			/*
20041.1Smycroft			 * If interface is marked down and it is running, then
20051.1Smycroft			 * stop it.
20061.1Smycroft			 */
20071.1Smycroft			fe_stop(sc);
20081.1Smycroft			ifp->if_flags &= ~IFF_RUNNING;
20091.1Smycroft		} else if ((ifp->if_flags & IFF_UP) != 0 &&
20101.1Smycroft			   (ifp->if_flags & IFF_RUNNING) == 0) {
20111.1Smycroft			/*
20121.1Smycroft			 * If interface is marked up and it is stopped, then
20131.1Smycroft			 * start it.
20141.1Smycroft			 */
20151.1Smycroft			fe_init(sc);
20161.1Smycroft		} else {
20171.1Smycroft			/*
20181.1Smycroft			 * Reset the interface to pick up changes in any other
20191.1Smycroft			 * flags that affect hardware registers.
20201.1Smycroft			 */
20211.1Smycroft			fe_setmode(sc);
20221.1Smycroft		}
20231.1Smycroft#if DEBUG >= 1
20241.1Smycroft		/* "ifconfig fe0 debug" to print register dump. */
20251.1Smycroft		if (ifp->if_flags & IFF_DEBUG) {
20261.1Smycroft			log(LOG_INFO, "%s: SIOCSIFFLAGS(DEBUG)\n", sc->sc_dev.dv_xname);
20271.1Smycroft			fe_dump(LOG_DEBUG, sc);
20281.1Smycroft		}
20291.1Smycroft#endif
20301.1Smycroft		break;
20311.1Smycroft
20321.1Smycroft	case SIOCADDMULTI:
20331.1Smycroft	case SIOCDELMULTI:
20341.1Smycroft		/* Update our multicast list. */
20351.1Smycroft		error = (command == SIOCADDMULTI) ?
20361.17Sis		    ether_addmulti(ifr, &sc->sc_ethercom) :
20371.17Sis		    ether_delmulti(ifr, &sc->sc_ethercom);
20381.1Smycroft
20391.1Smycroft		if (error == ENETRESET) {
20401.1Smycroft			/*
20411.1Smycroft			 * Multicast list has changed; set the hardware filter
20421.1Smycroft			 * accordingly.
20431.1Smycroft			 */
20441.1Smycroft			fe_setmode(sc);
20451.1Smycroft			error = 0;
20461.1Smycroft		}
20471.1Smycroft		break;
20481.1Smycroft
20491.1Smycroft	default:
20501.1Smycroft		error = EINVAL;
20511.1Smycroft	}
20521.1Smycroft
20531.1Smycroft	splx(s);
20541.1Smycroft	return (error);
20551.1Smycroft}
20561.1Smycroft
20571.1Smycroft/*
20581.1Smycroft * Retreive packet from receive buffer and send to the next level up via
20591.1Smycroft * ether_input(). If there is a BPF listener, give a copy to BPF, too.
20601.1Smycroft * Returns 0 if success, -1 if error (i.e., mbuf allocation failure).
20611.1Smycroft */
20621.1Smycroftint
20631.1Smycroftfe_get_packet(sc, len)
20641.1Smycroft	struct fe_softc *sc;
20651.1Smycroft	int len;
20661.1Smycroft{
20671.1Smycroft	struct ether_header *eh;
20681.1Smycroft	struct mbuf *m;
20691.17Sis	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
20701.1Smycroft
20711.1Smycroft	/* Allocate a header mbuf. */
20721.1Smycroft	MGETHDR(m, M_DONTWAIT, MT_DATA);
20731.1Smycroft	if (m == 0)
20741.1Smycroft		return (0);
20751.1Smycroft	m->m_pkthdr.rcvif = ifp;
20761.1Smycroft	m->m_pkthdr.len = len;
20771.1Smycroft
20781.1Smycroft	/* The following silliness is to make NFS happy. */
20791.1Smycroft#define	EROUND	((sizeof(struct ether_header) + 3) & ~3)
20801.1Smycroft#define	EOFF	(EROUND - sizeof(struct ether_header))
20811.1Smycroft
20821.1Smycroft	/*
20831.1Smycroft	 * Our strategy has one more problem.  There is a policy on
20841.1Smycroft	 * mbuf cluster allocation.  It says that we must have at
20851.6Smycroft	 * least MINCLSIZE (208 bytes) to allocate a cluster.  For a
20861.6Smycroft	 * packet of a size between (MHLEN - 2) to (MINCLSIZE - 2),
20871.6Smycroft	 * our code violates the rule...
20881.1Smycroft	 * On the other hand, the current code is short, simle,
20891.1Smycroft	 * and fast, however.  It does no harmful thing, just waists
20901.1Smycroft	 * some memory.  Any comments?  FIXME.
20911.1Smycroft	 */
20921.1Smycroft
20931.1Smycroft	/* Attach a cluster if this packet doesn't fit in a normal mbuf. */
20941.1Smycroft	if (len > MHLEN - EOFF) {
20951.1Smycroft		MCLGET(m, M_DONTWAIT);
20961.1Smycroft		if ((m->m_flags & M_EXT) == 0) {
20971.1Smycroft			m_freem(m);
20981.1Smycroft			return (0);
20991.1Smycroft		}
21001.1Smycroft	}
21011.1Smycroft
21021.1Smycroft	/*
21031.1Smycroft	 * The following assumes there is room for the ether header in the
21041.1Smycroft	 * header mbuf.
21051.1Smycroft	 */
21061.1Smycroft	m->m_data += EOFF;
21071.1Smycroft	eh = mtod(m, struct ether_header *);
21081.1Smycroft
21091.1Smycroft	/* Set the length of this packet. */
21101.1Smycroft	m->m_len = len;
21111.1Smycroft
21121.1Smycroft	/* Get a packet. */
21131.1Smycroft	insw(sc->sc_iobase + FE_BMPR8, m->m_data, (len + 1) >> 1);
21141.1Smycroft
21151.1Smycroft#if NBPFILTER > 0
21161.1Smycroft	/*
21171.1Smycroft	 * Check if there's a BPF listener on this interface.  If so, hand off
21181.1Smycroft	 * the raw packet to bpf.
21191.1Smycroft	 */
21201.1Smycroft	if (ifp->if_bpf) {
21211.1Smycroft		bpf_mtap(ifp->if_bpf, m);
21221.1Smycroft
21231.1Smycroft		/*
21241.1Smycroft		 * Note that the interface cannot be in promiscuous mode if
21251.1Smycroft		 * there are no BPF listeners.  And if we are in promiscuous
21261.1Smycroft		 * mode, we have to check if this packet is really ours.
21271.1Smycroft		 */
21281.1Smycroft		if ((ifp->if_flags & IFF_PROMISC) != 0 &&
21291.1Smycroft		    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
21301.17Sis	  	    bcmp(eh->ether_dhost, sc->sc_enaddr,
21311.1Smycroft			    sizeof(eh->ether_dhost)) != 0) {
21321.1Smycroft			m_freem(m);
21331.1Smycroft			return (1);
21341.1Smycroft		}
21351.1Smycroft	}
21361.1Smycroft#endif
21371.1Smycroft
21381.1Smycroft	/* Fix up data start offset in mbuf to point past ether header. */
21391.1Smycroft	m_adj(m, sizeof(struct ether_header));
21401.1Smycroft	ether_input(ifp, eh, m);
21411.1Smycroft	return (1);
21421.1Smycroft}
21431.1Smycroft
21441.1Smycroft/*
21451.1Smycroft * Write an mbuf chain to the transmission buffer memory using 16 bit PIO.
21461.1Smycroft * Returns number of bytes actually written, including length word.
21471.1Smycroft *
21481.1Smycroft * If an mbuf chain is too long for an Ethernet frame, it is not sent.
21491.1Smycroft * Packets shorter than Ethernet minimum are legal, and we pad them
21501.1Smycroft * before sending out.  An exception is "partial" packets which are
21511.1Smycroft * shorter than mandatory Ethernet header.
21521.1Smycroft *
21531.1Smycroft * I wrote a code for an experimental "delayed padding" technique.
21541.1Smycroft * When employed, it postpones the padding process for short packets.
21551.1Smycroft * If xmit() occured at the moment, the padding process is omitted, and
21561.1Smycroft * garbages are sent as pad data.  If next packet is stored in the
21571.1Smycroft * transmission buffer before xmit(), write_mbuf() pads the previous
21581.1Smycroft * packet before transmitting new packet.  This *may* gain the
21591.1Smycroft * system performance (slightly).
21601.1Smycroft */
21611.1Smycroftvoid
21621.1Smycroftfe_write_mbufs(sc, m)
21631.1Smycroft	struct fe_softc *sc;
21641.1Smycroft	struct mbuf *m;
21651.1Smycroft{
21661.1Smycroft	int bmpr8 = sc->sc_iobase + FE_BMPR8;
21671.1Smycroft	u_char *data;
21681.1Smycroft	u_short savebyte;	/* WARNING: Architecture dependent! */
21691.1Smycroft	int totlen, len, wantbyte;
21701.16Sthorpej
21711.16Sthorpej	/* XXX thorpej 960116 - quiet bogus compiler warning. */
21721.16Sthorpej	savebyte = 0;
21731.1Smycroft
21741.1Smycroft#if FE_DELAYED_PADDING
21751.1Smycroft	/* Do the "delayed padding." */
21761.1Smycroft	len = sc->txb_padding >> 1;
21771.1Smycroft	if (len > 0) {
21781.1Smycroft		while (--len >= 0)
21791.1Smycroft			outw(bmpr8, 0);
21801.1Smycroft		sc->txb_padding = 0;
21811.1Smycroft	}
21821.1Smycroft#endif
21831.1Smycroft
21841.4Smycroft	/* We need to use m->m_pkthdr.len, so require the header */
21851.4Smycroft	if ((m->m_flags & M_PKTHDR) == 0)
21861.4Smycroft	  	panic("fe_write_mbufs: no header mbuf");
21871.4Smycroft
21881.1Smycroft#if FE_DEBUG >= 2
21891.1Smycroft	/* First, count up the total number of bytes to copy. */
21901.1Smycroft	for (totlen = 0, mp = m; mp != 0; mp = mp->m_next)
21911.1Smycroft		totlen += mp->m_len;
21921.1Smycroft	/* Check if this matches the one in the packet header. */
21931.1Smycroft	if (totlen != m->m_pkthdr.len)
21941.1Smycroft		log(LOG_WARNING, "%s: packet length mismatch? (%d/%d)\n",
21951.1Smycroft		    sc->sc_dev.dv_xname, totlen, m->m_pkthdr.len);
21961.1Smycroft#else
21971.1Smycroft	/* Just use the length value in the packet header. */
21981.1Smycroft	totlen = m->m_pkthdr.len;
21991.1Smycroft#endif
22001.1Smycroft
22011.1Smycroft#if FE_DEBUG >= 1
22021.1Smycroft	/*
22031.1Smycroft	 * Should never send big packets.  If such a packet is passed,
22041.1Smycroft	 * it should be a bug of upper layer.  We just ignore it.
22051.1Smycroft	 * ... Partial (too short) packets, neither.
22061.1Smycroft	 */
22071.1Smycroft	if (totlen > ETHER_MAX_LEN || totlen < ETHER_HDR_SIZE) {
22081.1Smycroft		log(LOG_ERR, "%s: got a %s packet (%u bytes) to send\n",
22091.1Smycroft		    sc->sc_dev.dv_xname,
22101.1Smycroft		    totlen < ETHER_HDR_SIZE ? "partial" : "big", totlen);
22111.17Sis		sc->sc_ethercom.ec_if.if_oerrors++;
22121.1Smycroft		return;
22131.1Smycroft	}
22141.1Smycroft#endif
22151.1Smycroft
22161.1Smycroft	/*
22171.1Smycroft	 * Put the length word for this frame.
22181.1Smycroft	 * Does 86960 accept odd length?  -- Yes.
22191.1Smycroft	 * Do we need to pad the length to minimum size by ourselves?
22201.1Smycroft	 * -- Generally yes.  But for (or will be) the last
22211.1Smycroft	 * packet in the transmission buffer, we can skip the
22221.1Smycroft	 * padding process.  It may gain performance slightly.  FIXME.
22231.1Smycroft	 */
22241.1Smycroft	outw(bmpr8, max(totlen, ETHER_MIN_LEN));
22251.1Smycroft
22261.1Smycroft	/*
22271.1Smycroft	 * Update buffer status now.
22281.1Smycroft	 * Truncate the length up to an even number, since we use outw().
22291.1Smycroft	 */
22301.1Smycroft	totlen = (totlen + 1) & ~1;
22311.1Smycroft	sc->txb_free -= FE_DATA_LEN_LEN + max(totlen, ETHER_MIN_LEN);
22321.1Smycroft	sc->txb_count++;
22331.1Smycroft
22341.1Smycroft#if FE_DELAYED_PADDING
22351.1Smycroft	/* Postpone the packet padding if necessary. */
22361.1Smycroft	if (totlen < ETHER_MIN_LEN)
22371.1Smycroft		sc->txb_padding = ETHER_MIN_LEN - totlen;
22381.1Smycroft#endif
22391.1Smycroft
22401.1Smycroft	/*
22411.1Smycroft	 * Transfer the data from mbuf chain to the transmission buffer.
22421.1Smycroft	 * MB86960 seems to require that data be transferred as words, and
22431.1Smycroft	 * only words.  So that we require some extra code to patch
22441.1Smycroft	 * over odd-length mbufs.
22451.1Smycroft	 */
22461.1Smycroft	wantbyte = 0;
22471.1Smycroft	for (; m != 0; m = m->m_next) {
22481.1Smycroft		/* Ignore empty mbuf. */
22491.1Smycroft		len = m->m_len;
22501.1Smycroft		if (len == 0)
22511.1Smycroft			continue;
22521.1Smycroft
22531.1Smycroft		/* Find the actual data to send. */
22541.1Smycroft		data = mtod(m, caddr_t);
22551.1Smycroft
22561.1Smycroft		/* Finish the last byte. */
22571.1Smycroft		if (wantbyte) {
22581.1Smycroft			outw(bmpr8, savebyte | (*data << 8));
22591.1Smycroft			data++;
22601.1Smycroft			len--;
22611.1Smycroft			wantbyte = 0;
22621.1Smycroft		}
22631.1Smycroft
22641.1Smycroft		/* Output contiguous words. */
22651.1Smycroft		if (len > 1)
22661.1Smycroft			outsw(bmpr8, data, len >> 1);
22671.1Smycroft
22681.1Smycroft		/* Save remaining byte, if there is one. */
22691.1Smycroft		if (len & 1) {
22701.1Smycroft			data += len & ~1;
22711.1Smycroft			savebyte = *data;
22721.1Smycroft			wantbyte = 1;
22731.1Smycroft		}
22741.1Smycroft	}
22751.1Smycroft
22761.1Smycroft	/* Spit the last byte, if the length is odd. */
22771.1Smycroft	if (wantbyte)
22781.1Smycroft		outw(bmpr8, savebyte);
22791.1Smycroft
22801.1Smycroft#if ! FE_DELAYED_PADDING
22811.1Smycroft	/*
22821.1Smycroft	 * Pad the packet to the minimum length if necessary.
22831.1Smycroft	 */
22841.1Smycroft	len = (ETHER_MIN_LEN >> 1) - (totlen >> 1);
22851.1Smycroft	while (--len >= 0)
22861.1Smycroft		outw(bmpr8, 0);
22871.1Smycroft#endif
22881.1Smycroft}
22891.1Smycroft
22901.1Smycroft/*
22911.1Smycroft * Compute the multicast address filter from the
22921.1Smycroft * list of multicast addresses we need to listen to.
22931.1Smycroft */
22941.1Smycroftvoid
22951.17Sisfe_getmcaf(ec, af)
22961.17Sis	struct ethercom *ec;
22971.1Smycroft	u_char *af;
22981.1Smycroft{
22991.17Sis	struct ifnet *ifp = &ec->ec_if;
23001.1Smycroft	struct ether_multi *enm;
23011.1Smycroft	register u_char *cp, c;
23021.1Smycroft	register u_long crc;
23031.1Smycroft	register int i, len;
23041.1Smycroft	struct ether_multistep step;
23051.1Smycroft
23061.1Smycroft	/*
23071.1Smycroft	 * Set up multicast address filter by passing all multicast addresses
23081.1Smycroft	 * through a crc generator, and then using the high order 6 bits as an
23091.1Smycroft	 * index into the 64 bit logical address filter.  The high order bit
23101.1Smycroft	 * selects the word, while the rest of the bits select the bit within
23111.1Smycroft	 * the word.
23121.1Smycroft	 */
23131.1Smycroft
23141.1Smycroft	if ((ifp->if_flags & IFF_PROMISC) != 0)
23151.1Smycroft		goto allmulti;
23161.1Smycroft
23171.1Smycroft	af[0] = af[1] = af[2] = af[3] = af[4] = af[5] = af[6] = af[7] = 0x00;
23181.17Sis	ETHER_FIRST_MULTI(step, ec, enm);
23191.1Smycroft	while (enm != NULL) {
23201.1Smycroft		if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
23211.1Smycroft		    sizeof(enm->enm_addrlo)) != 0) {
23221.1Smycroft			/*
23231.1Smycroft			 * We must listen to a range of multicast addresses.
23241.1Smycroft			 * For now, just accept all multicasts, rather than
23251.1Smycroft			 * trying to set only those filter bits needed to match
23261.1Smycroft			 * the range.  (At this time, the only use of address
23271.1Smycroft			 * ranges is for IP multicast routing, for which the
23281.1Smycroft			 * range is big enough to require all bits set.)
23291.1Smycroft			 */
23301.1Smycroft			goto allmulti;
23311.1Smycroft		}
23321.1Smycroft
23331.1Smycroft		cp = enm->enm_addrlo;
23341.1Smycroft		crc = 0xffffffff;
23351.1Smycroft		for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
23361.1Smycroft			c = *cp++;
23371.1Smycroft			for (i = 8; --i >= 0;) {
23381.1Smycroft				if ((crc & 0x01) ^ (c & 0x01)) {
23391.1Smycroft					crc >>= 1;
23401.1Smycroft					crc ^= 0xedb88320;
23411.1Smycroft				} else
23421.1Smycroft					crc >>= 1;
23431.1Smycroft				c >>= 1;
23441.1Smycroft			}
23451.1Smycroft		}
23461.1Smycroft		/* Just want the 6 most significant bits. */
23471.1Smycroft		crc >>= 26;
23481.1Smycroft
23491.1Smycroft		/* Turn on the corresponding bit in the filter. */
23501.1Smycroft		af[crc >> 3] |= 1 << (crc & 7);
23511.1Smycroft
23521.1Smycroft		ETHER_NEXT_MULTI(step, enm);
23531.1Smycroft	}
23541.1Smycroft	ifp->if_flags &= ~IFF_ALLMULTI;
23551.1Smycroft	return;
23561.1Smycroft
23571.1Smycroftallmulti:
23581.1Smycroft	ifp->if_flags |= IFF_ALLMULTI;
23591.1Smycroft	af[0] = af[1] = af[2] = af[3] = af[4] = af[5] = af[6] = af[7] = 0xff;
23601.1Smycroft}
23611.1Smycroft
23621.1Smycroft/*
23631.1Smycroft * Calculate a new "multicast packet filter" and put the 86960
23641.1Smycroft * receiver in appropriate mode.
23651.1Smycroft */
23661.1Smycroftvoid
23671.1Smycroftfe_setmode(sc)
23681.1Smycroft	struct fe_softc *sc;
23691.1Smycroft{
23701.17Sis	int flags = sc->sc_ethercom.ec_if.if_flags;
23711.1Smycroft
23721.1Smycroft	/*
23731.1Smycroft	 * If the interface is not running, we postpone the update
23741.1Smycroft	 * process for receive modes and multicast address filter
23751.1Smycroft	 * until the interface is restarted.  It reduces some
23761.1Smycroft	 * complicated job on maintaining chip states.  (Earlier versions
23771.1Smycroft	 * of this driver had a bug on that point...)
23781.1Smycroft	 *
23791.1Smycroft	 * To complete the trick, fe_init() calls fe_setmode() after
23801.1Smycroft	 * restarting the interface.
23811.1Smycroft	 */
23821.1Smycroft	if ((flags & IFF_RUNNING) == 0)
23831.1Smycroft		return;
23841.1Smycroft
23851.1Smycroft	/*
23861.1Smycroft	 * Promiscuous mode is handled separately.
23871.1Smycroft	 */
23881.1Smycroft	if ((flags & IFF_PROMISC) != 0) {
23891.1Smycroft		/*
23901.1Smycroft		 * Program 86960 to receive all packets on the segment
23911.1Smycroft		 * including those directed to other stations.
23921.1Smycroft		 * Multicast filter stored in MARs are ignored
23931.1Smycroft		 * under this setting, so we don't need to update it.
23941.1Smycroft		 *
23951.6Smycroft		 * Promiscuous mode is used solely by BPF, and BPF only
23961.6Smycroft		 * listens to valid (no error) packets.  So, we ignore
23971.6Smycroft		 * errornous ones even in this mode.
23981.1Smycroft		 */
23991.1Smycroft		outb(sc->sc_iobase + FE_DLCR5,
24001.1Smycroft		    sc->proto_dlcr5 | FE_D5_AFM0 | FE_D5_AFM1);
24011.1Smycroft		sc->filter_change = 0;
24021.1Smycroft
24031.1Smycroft#if FE_DEBUG >= 3
24041.1Smycroft		log(LOG_INFO, "%s: promiscuous mode\n", sc->sc_dev.dv_xname);
24051.1Smycroft#endif
24061.1Smycroft		return;
24071.1Smycroft	}
24081.1Smycroft
24091.1Smycroft	/*
24101.1Smycroft	 * Turn the chip to the normal (non-promiscuous) mode.
24111.1Smycroft	 */
24121.1Smycroft	outb(sc->sc_iobase + FE_DLCR5, sc->proto_dlcr5 | FE_D5_AFM1);
24131.1Smycroft
24141.1Smycroft	/*
24151.1Smycroft	 * Find the new multicast filter value.
24161.1Smycroft	 */
24171.17Sis	fe_getmcaf(&sc->sc_ethercom, sc->filter);
24181.1Smycroft	sc->filter_change = 1;
24191.1Smycroft
24201.1Smycroft#if FE_DEBUG >= 3
24211.1Smycroft	log(LOG_INFO,
24221.1Smycroft	    "%s: address filter: [%02x %02x %02x %02x %02x %02x %02x %02x]\n",
24231.1Smycroft	    sc->sc_dev.dv_xname,
24241.1Smycroft	    sc->filter[0], sc->filter[1], sc->filter[2], sc->filter[3],
24251.1Smycroft	    sc->filter[4], sc->filter[5], sc->filter[6], sc->filter[7]);
24261.1Smycroft#endif
24271.1Smycroft
24281.1Smycroft	/*
24291.1Smycroft	 * We have to update the multicast filter in the 86960, A.S.A.P.
24301.1Smycroft	 *
24311.1Smycroft	 * Note that the DLC (Data Linc Control unit, i.e. transmitter
24321.1Smycroft	 * and receiver) must be stopped when feeding the filter, and
24331.1Smycroft	 * DLC trushes all packets in both transmission and receive
24341.1Smycroft	 * buffers when stopped.
24351.1Smycroft	 *
24361.1Smycroft	 * ... Are the above sentenses correct?  I have to check the
24371.1Smycroft	 *     manual of the MB86960A.  FIXME.
24381.1Smycroft	 *
24391.1Smycroft	 * To reduce the packet lossage, we delay the filter update
24401.1Smycroft	 * process until buffers are empty.
24411.1Smycroft	 */
24421.1Smycroft	if (sc->txb_sched == 0 && sc->txb_count == 0 &&
24431.1Smycroft	    (inb(sc->sc_iobase + FE_DLCR1) & FE_D1_PKTRDY) == 0) {
24441.1Smycroft		/*
24451.1Smycroft		 * Buffers are (apparently) empty.  Load
24461.1Smycroft		 * the new filter value into MARs now.
24471.1Smycroft		 */
24481.1Smycroft		fe_loadmar(sc);
24491.1Smycroft	} else {
24501.1Smycroft		/*
24511.1Smycroft		 * Buffers are not empty.  Mark that we have to update
24521.1Smycroft		 * the MARs.  The new filter will be loaded by feintr()
24531.1Smycroft		 * later.
24541.1Smycroft		 */
24551.1Smycroft#if FE_DEBUG >= 4
24561.1Smycroft		log(LOG_INFO, "%s: filter change delayed\n", sc->sc_dev.dv_xname);
24571.1Smycroft#endif
24581.1Smycroft	}
24591.1Smycroft}
24601.1Smycroft
24611.1Smycroft/*
24621.1Smycroft * Load a new multicast address filter into MARs.
24631.1Smycroft *
24641.8Smycroft * The caller must have splnet'ed befor fe_loadmar.
24651.1Smycroft * This function starts the DLC upon return.  So it can be called only
24661.1Smycroft * when the chip is working, i.e., from the driver's point of view, when
24671.1Smycroft * a device is RUNNING.  (I mistook the point in previous versions.)
24681.1Smycroft */
24691.1Smycroftvoid
24701.1Smycroftfe_loadmar(sc)
24711.1Smycroft	struct fe_softc *sc;
24721.1Smycroft{
24731.1Smycroft
24741.1Smycroft	/* Stop the DLC (transmitter and receiver). */
24751.1Smycroft	outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
24761.1Smycroft
24771.1Smycroft	/* Select register bank 1 for MARs. */
24781.1Smycroft	outb(sc->sc_iobase + FE_DLCR7,
24791.1Smycroft	    sc->proto_dlcr7 | FE_D7_RBS_MAR | FE_D7_POWER_UP);
24801.1Smycroft
24811.1Smycroft	/* Copy filter value into the registers. */
24821.1Smycroft	outblk(sc->sc_iobase + FE_MAR8, sc->filter, FE_FILTER_LEN);
24831.1Smycroft
24841.1Smycroft	/* Restore the bank selection for BMPRs (i.e., runtime registers). */
24851.1Smycroft	outb(sc->sc_iobase + FE_DLCR7,
24861.1Smycroft	    sc->proto_dlcr7 | FE_D7_RBS_BMPR | FE_D7_POWER_UP);
24871.1Smycroft
24881.1Smycroft	/* Restart the DLC. */
24891.1Smycroft	outb(sc->sc_iobase + FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_ENABLE);
24901.1Smycroft
24911.1Smycroft	/* We have just updated the filter. */
24921.1Smycroft	sc->filter_change = 0;
24931.1Smycroft
24941.1Smycroft#if FE_DEBUG >= 3
24951.1Smycroft	log(LOG_INFO, "%s: address filter changed\n", sc->sc_dev.dv_xname);
24961.1Smycroft#endif
24971.1Smycroft}
24981.1Smycroft
24991.1Smycroft#if FE_DEBUG >= 1
25001.1Smycroftvoid
25011.1Smycroftfe_dump(level, sc)
25021.1Smycroft	int level;
25031.1Smycroft	struct fe_softc *sc;
25041.1Smycroft{
25051.1Smycroft	int iobase = sc->sc_iobase;
25061.1Smycroft	u_char save_dlcr7;
25071.1Smycroft
25081.1Smycroft	save_dlcr7 = inb(iobase + FE_DLCR7);
25091.1Smycroft
25101.1Smycroft	log(level, "\tDLCR = %02x %02x %02x %02x %02x %02x %02x %02x",
25111.1Smycroft	    inb(iobase + FE_DLCR0),  inb(iobase + FE_DLCR1),
25121.1Smycroft	    inb(iobase + FE_DLCR2),  inb(iobase + FE_DLCR3),
25131.1Smycroft	    inb(iobase + FE_DLCR4),  inb(iobase + FE_DLCR5),
25141.1Smycroft	    inb(iobase + FE_DLCR6),  inb(iobase + FE_DLCR7));
25151.1Smycroft
25161.1Smycroft	outb(iobase + FE_DLCR7, (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_DLCR);
25171.1Smycroft	log(level, "\t       %02x %02x %02x %02x %02x %02x %02x %02x,",
25181.1Smycroft	    inb(iobase + FE_DLCR8),  inb(iobase + FE_DLCR9),
25191.1Smycroft	    inb(iobase + FE_DLCR10), inb(iobase + FE_DLCR11),
25201.1Smycroft	    inb(iobase + FE_DLCR12), inb(iobase + FE_DLCR13),
25211.1Smycroft	    inb(iobase + FE_DLCR14), inb(iobase + FE_DLCR15));
25221.1Smycroft
25231.1Smycroft	outb(iobase + FE_DLCR7, (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_MAR);
25241.1Smycroft	log(level, "\tMAR  = %02x %02x %02x %02x %02x %02x %02x %02x,",
25251.1Smycroft	    inb(iobase + FE_MAR8),   inb(iobase + FE_MAR9),
25261.1Smycroft	    inb(iobase + FE_MAR10),  inb(iobase + FE_MAR11),
25271.1Smycroft	    inb(iobase + FE_MAR12),  inb(iobase + FE_MAR13),
25281.1Smycroft	    inb(iobase + FE_MAR14),  inb(iobase + FE_MAR15));
25291.1Smycroft
25301.1Smycroft	outb(iobase + FE_DLCR7, (save_dlcr7 & ~FE_D7_RBS) | FE_D7_RBS_BMPR);
25311.1Smycroft	log(level, "\tBMPR = xx xx %02x %02x %02x %02x %02x %02x %02x %02x xx %02x.",
25321.1Smycroft	    inb(iobase + FE_BMPR10), inb(iobase + FE_BMPR11),
25331.1Smycroft	    inb(iobase + FE_BMPR12), inb(iobase + FE_BMPR13),
25341.1Smycroft	    inb(iobase + FE_BMPR14), inb(iobase + FE_BMPR15),
25351.1Smycroft	    inb(iobase + FE_BMPR16), inb(iobase + FE_BMPR17),
25361.1Smycroft	    inb(iobase + FE_BMPR19));
25371.1Smycroft
25381.1Smycroft	outb(iobase + FE_DLCR7, save_dlcr7);
25391.1Smycroft}
25401.1Smycroft#endif
2541