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