Home | History | Annotate | Line # | Download | only in ic
elink3.c revision 1.16
      1  1.16  jonathan /*	$NetBSD: elink3.c,v 1.16 1996/12/29 17:01:58 jonathan Exp $	*/
      2   1.1   thorpej 
      3   1.1   thorpej /*
      4   1.6   thorpej  * Copyright (c) 1994 Herb Peyerl <hpeyerl (at) beer.org>
      5   1.1   thorpej  * All rights reserved.
      6   1.1   thorpej  *
      7   1.1   thorpej  * Redistribution and use in source and binary forms, with or without
      8   1.1   thorpej  * modification, are permitted provided that the following conditions
      9   1.1   thorpej  * are met:
     10   1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     11   1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     12   1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     14   1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     15   1.1   thorpej  * 3. All advertising materials mentioning features or use of this software
     16   1.1   thorpej  *    must display the following acknowledgement:
     17   1.1   thorpej  *      This product includes software developed by Herb Peyerl.
     18   1.1   thorpej  * 4. The name of Herb Peyerl may not be used to endorse or promote products
     19   1.1   thorpej  *    derived from this software without specific prior written permission.
     20   1.1   thorpej  *
     21   1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22   1.1   thorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23   1.1   thorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24   1.1   thorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25   1.1   thorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26   1.1   thorpej  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27   1.1   thorpej  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28   1.1   thorpej  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29   1.1   thorpej  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30   1.1   thorpej  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31   1.1   thorpej  */
     32   1.1   thorpej 
     33   1.1   thorpej #include "bpfilter.h"
     34   1.1   thorpej 
     35   1.1   thorpej #include <sys/param.h>
     36   1.3  christos #include <sys/systm.h>
     37   1.1   thorpej #include <sys/mbuf.h>
     38   1.1   thorpej #include <sys/socket.h>
     39   1.1   thorpej #include <sys/ioctl.h>
     40   1.1   thorpej #include <sys/errno.h>
     41   1.1   thorpej #include <sys/syslog.h>
     42   1.1   thorpej #include <sys/select.h>
     43   1.1   thorpej #include <sys/device.h>
     44   1.1   thorpej 
     45   1.1   thorpej #include <net/if.h>
     46   1.1   thorpej #include <net/netisr.h>
     47   1.1   thorpej #include <net/if_dl.h>
     48   1.1   thorpej #include <net/if_types.h>
     49   1.1   thorpej #include <net/netisr.h>
     50   1.1   thorpej 
     51   1.1   thorpej #ifdef INET
     52   1.1   thorpej #include <netinet/in.h>
     53   1.1   thorpej #include <netinet/in_systm.h>
     54   1.1   thorpej #include <netinet/in_var.h>
     55   1.1   thorpej #include <netinet/ip.h>
     56   1.1   thorpej #include <netinet/if_ether.h>
     57   1.1   thorpej #endif
     58   1.1   thorpej 
     59   1.1   thorpej #ifdef NS
     60   1.1   thorpej #include <netns/ns.h>
     61   1.1   thorpej #include <netns/ns_if.h>
     62   1.1   thorpej #endif
     63   1.1   thorpej 
     64   1.1   thorpej #if NBPFILTER > 0
     65   1.1   thorpej #include <net/bpf.h>
     66   1.1   thorpej #include <net/bpfdesc.h>
     67   1.1   thorpej #endif
     68   1.1   thorpej 
     69   1.1   thorpej #include <machine/cpu.h>
     70   1.2   thorpej #include <machine/bus.h>
     71   1.7   thorpej #include <machine/intr.h>
     72   1.1   thorpej 
     73   1.1   thorpej #include <dev/ic/elink3var.h>
     74   1.1   thorpej #include <dev/ic/elink3reg.h>
     75   1.1   thorpej 
     76   1.1   thorpej #define ETHER_MIN_LEN	64
     77   1.1   thorpej #define ETHER_MAX_LEN   1518
     78   1.1   thorpej #define ETHER_ADDR_LEN  6
     79   1.1   thorpej 
     80   1.1   thorpej struct cfdriver ep_cd = {
     81   1.1   thorpej 	NULL, "ep", DV_IFNET
     82   1.1   thorpej };
     83   1.1   thorpej 
     84  1.15  jonathan void	ep_internalconfig __P((struct ep_softc *sc));
     85  1.15  jonathan void	ep_vortex_internalconfig __P((struct ep_softc *sc));
     86   1.3  christos static void eptxstat __P((struct ep_softc *));
     87   1.1   thorpej static int epstatus __P((struct ep_softc *));
     88   1.1   thorpej void epinit __P((struct ep_softc *));
     89   1.1   thorpej int epioctl __P((struct ifnet *, u_long, caddr_t));
     90   1.1   thorpej void epstart __P((struct ifnet *));
     91   1.5   thorpej void epwatchdog __P((struct ifnet *));
     92   1.1   thorpej void epreset __P((struct ep_softc *));
     93  1.16  jonathan static void epshutdown __P((void *));
     94   1.1   thorpej void epread __P((struct ep_softc *));
     95   1.1   thorpej struct mbuf *epget __P((struct ep_softc *, int));
     96   1.3  christos void epmbuffill __P((void *));
     97   1.1   thorpej void epmbufempty __P((struct ep_softc *));
     98   1.1   thorpej void epsetfilter __P((struct ep_softc *));
     99   1.1   thorpej void epsetlink __P((struct ep_softc *));
    100   1.1   thorpej 
    101   1.1   thorpej static int epbusyeeprom __P((struct ep_softc *));
    102   1.1   thorpej 
    103  1.15  jonathan 
    104   1.1   thorpej void
    105   1.1   thorpej epconfig(sc, conn)
    106   1.1   thorpej 	struct ep_softc *sc;
    107   1.7   thorpej 	u_int16_t conn;
    108   1.1   thorpej {
    109   1.5   thorpej 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    110  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    111  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    112   1.7   thorpej 	u_int16_t i;
    113   1.1   thorpej 
    114  1.14       cjs 	printf("%s: ", sc->sc_dev.dv_xname);
    115  1.14       cjs 
    116  1.15  jonathan 
    117  1.14       cjs 	/* print RAM size */
    118  1.15  jonathan 	ep_internalconfig(sc);
    119  1.14       cjs 	GO_WINDOW(0);
    120  1.14       cjs 
    121  1.14       cjs 	/* determine connectors available */
    122   1.1   thorpej 	sc->ep_connectors = 0;
    123   1.1   thorpej 	if (conn & IS_AUI) {
    124  1.10  christos 		printf("aui");
    125   1.1   thorpej 		sc->ep_connectors |= AUI;
    126   1.1   thorpej 	}
    127   1.1   thorpej 	if (conn & IS_BNC) {
    128   1.1   thorpej 		if (sc->ep_connectors)
    129  1.10  christos 			printf("/");
    130  1.10  christos 		printf("bnc");
    131   1.1   thorpej 		sc->ep_connectors |= BNC;
    132   1.1   thorpej 	}
    133   1.1   thorpej 	if (conn & IS_UTP) {
    134   1.1   thorpej 		if (sc->ep_connectors)
    135  1.10  christos 			printf("/");
    136  1.15  jonathan 		printf("10baseT");
    137   1.1   thorpej 		sc->ep_connectors |= UTP;
    138   1.1   thorpej 	}
    139  1.15  jonathan 	if (conn & IS_100BASE_TX) {
    140  1.15  jonathan 		if (sc->ep_connectors)
    141  1.15  jonathan 			printf("/");
    142  1.15  jonathan 		printf("100base-TX");
    143  1.15  jonathan 		sc->ep_connectors |= TX;
    144  1.15  jonathan 	}
    145  1.15  jonathan 	if (conn & IS_100BASE_T4) {
    146  1.15  jonathan 		if (sc->ep_connectors)
    147  1.15  jonathan 			printf("/");
    148  1.15  jonathan 		printf("100base-T4");
    149  1.15  jonathan 		sc->ep_connectors |= T4;
    150  1.15  jonathan 	}
    151  1.15  jonathan 	if (conn & IS_100BASE_FX) {
    152  1.15  jonathan 		if (sc->ep_connectors)
    153  1.15  jonathan 			printf("/");
    154  1.15  jonathan 		printf("100base-FX");
    155  1.15  jonathan 		sc->ep_connectors |= FX;
    156  1.15  jonathan 	}
    157  1.15  jonathan 	if (conn & IS_100BASE_MII) {
    158  1.15  jonathan 		if (sc->ep_connectors)
    159  1.15  jonathan 			printf("/");
    160  1.15  jonathan 		printf("MII");
    161  1.15  jonathan 		sc->ep_connectors |= MII;
    162  1.15  jonathan 	}
    163  1.15  jonathan 
    164   1.1   thorpej 	if (!sc->ep_connectors)
    165  1.10  christos 		printf("no connectors!");
    166  1.15  jonathan 	printf("\n");
    167   1.1   thorpej 
    168   1.1   thorpej 	/*
    169   1.1   thorpej 	 * Read the station address from the eeprom
    170   1.1   thorpej 	 */
    171   1.1   thorpej 	for (i = 0; i < 3; i++) {
    172   1.7   thorpej 		u_int16_t x;
    173   1.1   thorpej 		if (epbusyeeprom(sc))
    174   1.1   thorpej 			return;
    175  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
    176  1.11   thorpej 		    READ_EEPROM | i);
    177   1.1   thorpej 		if (epbusyeeprom(sc))
    178   1.1   thorpej 			return;
    179  1.11   thorpej 		x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA);
    180   1.1   thorpej 		sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8;
    181   1.1   thorpej 		sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x;
    182   1.1   thorpej 	}
    183   1.1   thorpej 
    184  1.16  jonathan 	printf("%s: MAC address %s\n", sc->sc_dev.dv_xname,
    185  1.15  jonathan 	    ether_sprintf(sc->sc_arpcom.ac_enaddr));
    186   1.1   thorpej 
    187  1.12  jonathan 	/*
    188  1.12  jonathan 	 * Vortex-based (3c59x, eisa)? and Boomerang (3c900)cards allow
    189  1.12  jonathan 	 * FDDI-sized (4500) byte packets.  Commands only take an 11-bit
    190  1.12  jonathan 	 * parameter, and  11 bits isn't enough to hold a full-size pkt length.
    191  1.12  jonathan 	 * Commands to these cards implicitly upshift a packet size
    192  1.12  jonathan 	 * or threshold by 2 bits.
    193  1.12  jonathan 	 * To detect  cards with large-packet support, we probe by setting
    194  1.12  jonathan 	 * the transmit threshold register, then change windows and
    195  1.12  jonathan 	 * read back the threshold register directly, and see if the
    196  1.12  jonathan 	 * threshold value was shifted or not.
    197  1.12  jonathan 	 */
    198  1.12  jonathan 	bus_space_write_2(iot, ioh, EP_COMMAND,
    199  1.13  jonathan 			  SET_TX_AVAIL_THRESH | EP_LARGEWIN_PROBE );
    200  1.12  jonathan 	GO_WINDOW(5);
    201  1.12  jonathan 	i = bus_space_read_2(iot, ioh, EP_W5_TX_AVAIL_THRESH);
    202  1.12  jonathan 	GO_WINDOW(1);
    203  1.12  jonathan 	switch (i)  {
    204  1.13  jonathan 	case EP_LARGEWIN_PROBE:
    205  1.13  jonathan 	case (EP_LARGEWIN_PROBE & EP_LARGEWIN_MASK):
    206  1.12  jonathan 		sc->ep_pktlenshift = 0;
    207  1.12  jonathan 		break;
    208  1.12  jonathan 
    209  1.13  jonathan 	case (EP_LARGEWIN_PROBE << 2):
    210  1.12  jonathan 		sc->ep_pktlenshift = 2;
    211  1.16  jonathan 		/* XXX do 3c579, 3c515 support Vortex-style RESET_OPTIONS? */
    212  1.16  jonathan 		if (sc->bustype == EP_BUS_PCI)
    213  1.16  jonathan 			ep_vortex_internalconfig(sc);
    214  1.12  jonathan 		break;
    215  1.12  jonathan 
    216  1.12  jonathan 	default:
    217  1.14       cjs 		printf("%s: wrote %d to TX_AVAIL_THRESH, read back %d. "
    218  1.14       cjs 		    "Interface disabled\n",
    219  1.12  jonathan 		    sc->sc_dev.dv_xname, EP_THRESH_DISABLE, (int) i);
    220  1.12  jonathan 		return;
    221  1.12  jonathan 	}
    222  1.12  jonathan 	/*
    223  1.12  jonathan 	 * Ensure Tx-available interrupts are enabled for
    224  1.12  jonathan 	 * start the interface.
    225  1.12  jonathan 	 * XXX should be in epinit().
    226  1.12  jonathan 	 */
    227  1.12  jonathan 	bus_space_write_2(iot, ioh, EP_COMMAND,
    228  1.12  jonathan 	    SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift));
    229  1.12  jonathan 
    230   1.5   thorpej 	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
    231   1.5   thorpej 	ifp->if_softc = sc;
    232   1.1   thorpej 	ifp->if_start = epstart;
    233   1.1   thorpej 	ifp->if_ioctl = epioctl;
    234   1.1   thorpej 	ifp->if_watchdog = epwatchdog;
    235   1.1   thorpej 	ifp->if_flags =
    236   1.1   thorpej 	    IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
    237   1.1   thorpej 
    238   1.1   thorpej 	if_attach(ifp);
    239   1.1   thorpej 	ether_ifattach(ifp);
    240   1.1   thorpej 
    241   1.1   thorpej #if NBPFILTER > 0
    242   1.1   thorpej 	bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
    243   1.1   thorpej 		  sizeof(struct ether_header));
    244   1.1   thorpej #endif
    245   1.1   thorpej 
    246   1.1   thorpej 	sc->tx_start_thresh = 20;	/* probably a good starting point. */
    247  1.12  jonathan 
    248  1.16  jonathan 	/*  Establish callback to reset card when we reboot. */
    249  1.16  jonathan 	shutdownhook_establish(epshutdown, sc);
    250  1.16  jonathan 
    251  1.12  jonathan #if 0
    252  1.12  jonathan 	/* XXX */
    253  1.12  jonathan 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET);
    254  1.12  jonathan 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
    255  1.12  jonathan #else
    256  1.12  jonathan 
    257  1.12  jonathan 	epinit(sc);		/*XXX fix up after probe */
    258  1.12  jonathan 	DELAY(20000);
    259  1.12  jonathan 	epstop(sc);		/*XXX reset after probe, stop interface. */
    260  1.12  jonathan 	DELAY(20000);
    261  1.12  jonathan #endif
    262   1.1   thorpej }
    263   1.1   thorpej 
    264   1.1   thorpej /*
    265  1.15  jonathan  * Show interface-model-independent info from window 3
    266  1.15  jonathan  * internal-configuration register.
    267  1.15  jonathan  */
    268  1.15  jonathan void
    269  1.15  jonathan ep_internalconfig(sc)
    270  1.15  jonathan 	struct ep_softc *sc;
    271  1.15  jonathan {
    272  1.15  jonathan 	bus_space_tag_t iot = sc->sc_iot;
    273  1.15  jonathan 	bus_space_handle_t ioh = sc->sc_ioh;
    274  1.15  jonathan 
    275  1.15  jonathan 	u_int config0;
    276  1.15  jonathan 	u_int config1;
    277  1.15  jonathan 
    278  1.15  jonathan 	int  ram_size, ram_width, ram_speed, rom_size, ram_split;
    279  1.15  jonathan 	/*
    280  1.15  jonathan 	 * NVRAM buffer Rx:Tx config names for busmastering cards
    281  1.15  jonathan 	 * (Demon, Vortex, and later).
    282  1.15  jonathan 	 */
    283  1.15  jonathan 	const char *onboard_ram_config[] = {
    284  1.15  jonathan 		"5:3", "3:1", "1:1", "(undefined)" };
    285  1.15  jonathan 
    286  1.15  jonathan 	GO_WINDOW(3);
    287  1.15  jonathan 	config0 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG);
    288  1.15  jonathan 	config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG+2);
    289  1.15  jonathan 	GO_WINDOW(0);
    290  1.15  jonathan 
    291  1.15  jonathan 	ram_size  = (config0 & CONFIG_RAMSIZE) >> CONFIG_RAMSIZE_SHIFT;
    292  1.15  jonathan 	ram_width = (config0 & CONFIG_RAMWIDTH) >> CONFIG_RAMWIDTH_SHIFT;
    293  1.15  jonathan 	ram_speed = (config0 & CONFIG_RAMSPEED) >> CONFIG_RAMSPEED_SHIFT;
    294  1.15  jonathan 	rom_size  = (config0 & CONFIG_ROMSIZE) >> CONFIG_ROMSIZE_SHIFT;
    295  1.15  jonathan 
    296  1.15  jonathan 	ram_split  = (config1 & CONFIG_RAMSPLIT) >> CONFIG_RAMSPLIT_SHIFT;
    297  1.15  jonathan 
    298  1.15  jonathan 	printf("%dKB %s-wide FIFO, %s Rx:Tx split, ",
    299  1.15  jonathan 	    8 << ram_size,
    300  1.15  jonathan 	    (ram_width) ? "word" : "byte",
    301  1.15  jonathan 	    onboard_ram_config[ram_split]);
    302  1.15  jonathan }
    303  1.15  jonathan 
    304  1.15  jonathan 
    305  1.15  jonathan /*
    306  1.15  jonathan  * Show onboard configuration of large-packet-capable elink3 devices (Demon,
    307  1.15  jonathan  * Vortex, Boomerang),  using media and card-version info in window 3.
    308  1.15  jonathan  *
    309  1.15  jonathan  * XXX how much of this works with 3c515, pcmcia 10/100?  With 3c509, 3c589?
    310  1.15  jonathan  */
    311  1.15  jonathan void
    312  1.15  jonathan ep_vortex_internalconfig(sc)
    313  1.15  jonathan 	struct ep_softc *sc;
    314  1.15  jonathan {
    315  1.15  jonathan 	bus_space_tag_t iot = sc->sc_iot;
    316  1.15  jonathan 	bus_space_handle_t ioh = sc->sc_ioh;
    317  1.15  jonathan 	u_int config0;
    318  1.15  jonathan 	u_int config1;
    319  1.15  jonathan 	int reset_options;
    320  1.15  jonathan 
    321  1.15  jonathan 	int  media_mask, autoselect;
    322  1.15  jonathan 	/*  Names for  media in the media bitmask field. */
    323  1.15  jonathan 	const char *medium_name;
    324  1.15  jonathan 	const char *media_names[8] ={
    325  1.15  jonathan 		"10baseT",
    326  1.15  jonathan 		"10base AUI",
    327  1.15  jonathan 		"undefined",
    328  1.15  jonathan 		"10base2",
    329  1.15  jonathan 		"100baseTX",
    330  1.15  jonathan 		"100baseFX",
    331  1.15  jonathan 		"MII",
    332  1.15  jonathan 		"100baseT4"};
    333  1.15  jonathan 
    334  1.15  jonathan 	GO_WINDOW(3);
    335  1.15  jonathan 	config0 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG);
    336  1.15  jonathan 	config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG+2);
    337  1.15  jonathan 	reset_options  = (int)bus_space_read_1(iot, ioh, EP_W3_RESET_OPTIONS);
    338  1.15  jonathan 	GO_WINDOW(0);
    339  1.15  jonathan 
    340  1.15  jonathan 	media_mask = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
    341  1.15  jonathan         autoselect = (config1 & CONFIG_AUTOSELECT) >> CONFIG_AUTOSELECT_SHIFT;
    342  1.15  jonathan 
    343  1.15  jonathan 	medium_name = (media_mask > 8) ? "(unknown/impossible media)"
    344  1.15  jonathan 		                       : media_names[media_mask];
    345  1.15  jonathan 
    346  1.15  jonathan 	media_mask = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
    347  1.15  jonathan         autoselect = (config1 & CONFIG_AUTOSELECT) >> CONFIG_AUTOSELECT_SHIFT;
    348  1.15  jonathan 
    349  1.15  jonathan 
    350  1.15  jonathan 	printf("%s: default medium %s, autoselect %s\n",
    351  1.15  jonathan 	       sc->sc_dev.dv_xname,
    352  1.15  jonathan 	       medium_name,  (autoselect)? "on" : "off" );
    353  1.15  jonathan }
    354  1.15  jonathan 
    355  1.15  jonathan /*
    356   1.1   thorpej  * The order in here seems important. Otherwise we may not receive
    357   1.1   thorpej  * interrupts. ?!
    358   1.1   thorpej  */
    359   1.1   thorpej void
    360   1.1   thorpej epinit(sc)
    361   1.1   thorpej 	register struct ep_softc *sc;
    362   1.1   thorpej {
    363   1.1   thorpej 	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    364  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    365  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    366   1.1   thorpej 	int i;
    367   1.1   thorpej 
    368  1.11   thorpej 	while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
    369   1.1   thorpej 		;
    370   1.1   thorpej 
    371   1.1   thorpej 	if (sc->bustype != EP_BUS_PCI) {
    372   1.1   thorpej 		GO_WINDOW(0);
    373  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, 0);
    374  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
    375   1.1   thorpej 	}
    376   1.1   thorpej 
    377   1.1   thorpej 	if (sc->bustype == EP_BUS_PCMCIA) {
    378   1.1   thorpej #ifdef EP_COAX_DEFAULT
    379  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,3<<14);
    380   1.1   thorpej #else
    381  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,0<<14);
    382   1.1   thorpej #endif
    383  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_W0_RESOURCE_CFG, 0x3f00);
    384   1.1   thorpej 	}
    385   1.1   thorpej 
    386   1.1   thorpej 	GO_WINDOW(2);
    387   1.1   thorpej 	for (i = 0; i < 6; i++)	/* Reload the ether_addr. */
    388  1.11   thorpej 		bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
    389   1.2   thorpej 		    sc->sc_arpcom.ac_enaddr[i]);
    390   1.8  christos 
    391  1.12  jonathan 	/*
    392  1.12  jonathan 	 * Reset the station-address receive filter.
    393  1.12  jonathan 	 * A bug workaround for busmastering  (Vortex, Demon) cards.
    394  1.12  jonathan 	 */
    395  1.12  jonathan 	for (i = 0; i < 6; i++)
    396  1.12  jonathan 		bus_space_write_1(iot, ioh, EP_W2_RECVMASK_0 + i, 0);
    397   1.1   thorpej 
    398  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET);
    399  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
    400   1.1   thorpej 
    401   1.1   thorpej 	GO_WINDOW(1);		/* Window 1 is operating window */
    402   1.1   thorpej 	for (i = 0; i < 31; i++)
    403  1.11   thorpej 		bus_space_read_1(iot, ioh, EP_W1_TX_STATUS);
    404   1.1   thorpej 
    405  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE |
    406   1.1   thorpej 				S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
    407  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE |
    408   1.1   thorpej 				S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
    409   1.1   thorpej 
    410   1.1   thorpej 	/*
    411   1.1   thorpej 	 * Attempt to get rid of any stray interrupts that occured during
    412   1.1   thorpej 	 * configuration.  On the i386 this isn't possible because one may
    413   1.1   thorpej 	 * already be queued.  However, a single stray interrupt is
    414   1.1   thorpej 	 * unimportant.
    415   1.1   thorpej 	 */
    416  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff);
    417   1.1   thorpej 
    418   1.1   thorpej 	epsetfilter(sc);
    419   1.1   thorpej 	epsetlink(sc);
    420   1.1   thorpej 
    421  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
    422  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
    423   1.1   thorpej 
    424   1.1   thorpej 	epmbuffill(sc);
    425   1.1   thorpej 
    426   1.1   thorpej 	/* Interface is now `running', with no output active. */
    427   1.1   thorpej 	ifp->if_flags |= IFF_RUNNING;
    428   1.1   thorpej 	ifp->if_flags &= ~IFF_OACTIVE;
    429   1.1   thorpej 
    430   1.1   thorpej 	/* Attempt to start output, if any. */
    431   1.1   thorpej 	epstart(ifp);
    432   1.1   thorpej }
    433   1.1   thorpej 
    434   1.1   thorpej void
    435   1.1   thorpej epsetfilter(sc)
    436   1.1   thorpej 	register struct ep_softc *sc;
    437   1.1   thorpej {
    438   1.1   thorpej 	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    439   1.1   thorpej 
    440   1.1   thorpej 	GO_WINDOW(1);		/* Window 1 is operating window */
    441  1.11   thorpej 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_COMMAND, SET_RX_FILTER |
    442   1.1   thorpej 	    FIL_INDIVIDUAL | FIL_BRDCST |
    443   1.1   thorpej 	    ((ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0 ) |
    444   1.1   thorpej 	    ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 ));
    445   1.1   thorpej }
    446   1.1   thorpej 
    447  1.15  jonathan /*
    448  1.15  jonathan  * select media based on link{0,1,2} switches.
    449  1.15  jonathan  * Assumes 10Mbit interface, totatlly broken for 10/100 adaptors.
    450  1.15  jonathan  */
    451   1.1   thorpej void
    452   1.1   thorpej epsetlink(sc)
    453   1.1   thorpej 	register struct ep_softc *sc;
    454   1.1   thorpej {
    455   1.1   thorpej 	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    456  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    457  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    458   1.1   thorpej 
    459   1.1   thorpej 	/*
    460   1.1   thorpej 	 * you can `ifconfig (link0|-link0) ep0' to get the following
    461   1.1   thorpej 	 * behaviour:
    462   1.1   thorpej 	 *	-link0	disable AUI/UTP. enable BNC.
    463   1.1   thorpej 	 *	link0	disable BNC. enable AUI.
    464   1.1   thorpej 	 *	link1	if the card has a UTP connector, and link0 is
    465   1.1   thorpej 	 *		set too, then you get the UTP port.
    466   1.1   thorpej 	 */
    467   1.1   thorpej 	GO_WINDOW(4);
    468  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, DISABLE_UTP);
    469   1.1   thorpej 	if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) {
    470   1.1   thorpej 		if (sc->bustype == EP_BUS_PCMCIA) {
    471   1.1   thorpej 			GO_WINDOW(0);
    472  1.11   thorpej 			bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,3<<14);
    473   1.1   thorpej 			GO_WINDOW(1);
    474   1.1   thorpej 		}
    475  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER);
    476   1.1   thorpej 		delay(1000);
    477   1.1   thorpej 	}
    478   1.1   thorpej 	if (ifp->if_flags & IFF_LINK0) {
    479  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
    480   1.1   thorpej 		delay(1000);
    481   1.1   thorpej 		if ((ifp->if_flags & IFF_LINK1) && (sc->ep_connectors & UTP)) {
    482   1.1   thorpej 			if (sc->bustype == EP_BUS_PCMCIA) {
    483   1.1   thorpej 				GO_WINDOW(0);
    484  1.11   thorpej 				bus_space_write_2(iot, ioh,
    485   1.2   thorpej 				    EP_W0_ADDRESS_CFG,0<<14);
    486   1.1   thorpej 				GO_WINDOW(4);
    487   1.1   thorpej 			}
    488  1.11   thorpej 			bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, ENABLE_UTP);
    489   1.1   thorpej 		}
    490   1.1   thorpej 	}
    491   1.1   thorpej 	GO_WINDOW(1);
    492   1.1   thorpej }
    493   1.1   thorpej 
    494   1.1   thorpej /*
    495   1.1   thorpej  * Start outputting on the interface.
    496   1.1   thorpej  * Always called as splnet().
    497   1.1   thorpej  */
    498   1.1   thorpej void
    499   1.1   thorpej epstart(ifp)
    500   1.1   thorpej 	struct ifnet *ifp;
    501   1.1   thorpej {
    502   1.5   thorpej 	register struct ep_softc *sc = ifp->if_softc;
    503  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    504  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    505   1.1   thorpej 	struct mbuf *m, *m0;
    506   1.1   thorpej 	int sh, len, pad;
    507   1.1   thorpej 
    508   1.1   thorpej 	/* Don't transmit if interface is busy or not running */
    509   1.1   thorpej 	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
    510   1.1   thorpej 		return;
    511   1.1   thorpej 
    512   1.1   thorpej startagain:
    513   1.1   thorpej 	/* Sneak a peek at the next packet */
    514   1.1   thorpej 	m0 = ifp->if_snd.ifq_head;
    515   1.1   thorpej 	if (m0 == 0)
    516   1.1   thorpej 		return;
    517   1.1   thorpej 
    518   1.1   thorpej 	/* We need to use m->m_pkthdr.len, so require the header */
    519   1.1   thorpej 	if ((m0->m_flags & M_PKTHDR) == 0)
    520   1.1   thorpej 		panic("epstart: no header mbuf");
    521   1.1   thorpej 	len = m0->m_pkthdr.len;
    522   1.1   thorpej 
    523   1.1   thorpej 	pad = (4 - len) & 3;
    524   1.1   thorpej 
    525   1.1   thorpej 	/*
    526   1.1   thorpej 	 * The 3c509 automatically pads short packets to minimum ethernet
    527   1.1   thorpej 	 * length, but we drop packets that are too large. Perhaps we should
    528   1.1   thorpej 	 * truncate them instead?
    529   1.1   thorpej 	 */
    530   1.1   thorpej 	if (len + pad > ETHER_MAX_LEN) {
    531   1.1   thorpej 		/* packet is obviously too large: toss it */
    532   1.1   thorpej 		++ifp->if_oerrors;
    533   1.1   thorpej 		IF_DEQUEUE(&ifp->if_snd, m0);
    534   1.1   thorpej 		m_freem(m0);
    535   1.1   thorpej 		goto readcheck;
    536   1.1   thorpej 	}
    537   1.1   thorpej 
    538  1.11   thorpej 	if (bus_space_read_2(iot, ioh, EP_W1_FREE_TX) < len + pad + 4) {
    539  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND,
    540  1.12  jonathan 		    SET_TX_AVAIL_THRESH |
    541  1.12  jonathan 		    ((len + pad + 4) >> sc->ep_pktlenshift));
    542   1.1   thorpej 		/* not enough room in FIFO */
    543   1.1   thorpej 		ifp->if_flags |= IFF_OACTIVE;
    544   1.1   thorpej 		return;
    545   1.1   thorpej 	} else {
    546  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND,
    547  1.12  jonathan 		    SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE );
    548   1.1   thorpej 	}
    549   1.1   thorpej 
    550   1.1   thorpej 	IF_DEQUEUE(&ifp->if_snd, m0);
    551   1.1   thorpej 	if (m0 == 0)		/* not really needed */
    552   1.1   thorpej 		return;
    553   1.1   thorpej 
    554  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
    555  1.12  jonathan 	    ((len / 4 + sc->tx_start_thresh) /* >> sc->ep_pktlenshift*/) );
    556   1.1   thorpej 
    557   1.1   thorpej #if NBPFILTER > 0
    558   1.1   thorpej 	if (ifp->if_bpf)
    559   1.1   thorpej 		bpf_mtap(ifp->if_bpf, m0);
    560   1.1   thorpej #endif
    561   1.1   thorpej 
    562   1.1   thorpej 	/*
    563   1.1   thorpej 	 * Do the output at splhigh() so that an interrupt from another device
    564   1.1   thorpej 	 * won't cause a FIFO underrun.
    565   1.1   thorpej 	 */
    566   1.1   thorpej 	sh = splhigh();
    567   1.1   thorpej 
    568  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_W1_TX_PIO_WR_1, len);
    569  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_W1_TX_PIO_WR_1,
    570   1.2   thorpej 	    0xffff);	/* Second dword meaningless */
    571   1.1   thorpej 	if (EP_IS_BUS_32(sc->bustype)) {
    572   1.1   thorpej 		for (m = m0; m; ) {
    573  1.14       cjs 			if (m->m_len > 3)  {
    574  1.14       cjs 				/* align our reads from core */
    575  1.14       cjs 				if (mtod(m, u_long) & 3)  {
    576  1.14       cjs 					u_long count =
    577  1.14       cjs 					    4 - (mtod(m, u_long) & 3);
    578  1.14       cjs 					bus_space_write_multi_1(iot, ioh,
    579  1.14       cjs 					    EP_W1_TX_PIO_WR_1,
    580  1.14       cjs 					    mtod(m, u_int8_t *), count);
    581  1.14       cjs 					m->m_data =
    582  1.14       cjs 					    (void *)(mtod(m, u_long) + count);
    583  1.14       cjs 					m->m_len -= count;
    584  1.14       cjs 				}
    585  1.11   thorpej 				bus_space_write_multi_4(iot, ioh,
    586  1.14       cjs 				    EP_W1_TX_PIO_WR_1,
    587  1.14       cjs 				    mtod(m, u_int32_t *), m->m_len >> 2);
    588  1.14       cjs 				m->m_data = (void *)(mtod(m, u_long) +
    589  1.14       cjs 					(u_long)(m->m_len & ~3));
    590  1.14       cjs 				m->m_len -= m->m_len & ~3;
    591  1.14       cjs 			}
    592  1.14       cjs 			if (m->m_len)  {
    593  1.11   thorpej 				bus_space_write_multi_1(iot, ioh,
    594   1.2   thorpej 				    EP_W1_TX_PIO_WR_1,
    595  1.14       cjs 				    mtod(m, u_int8_t *), m->m_len);
    596  1.14       cjs 			}
    597   1.1   thorpej 			MFREE(m, m0);
    598   1.1   thorpej 			m = m0;
    599   1.1   thorpej 		}
    600   1.1   thorpej 	} else {
    601   1.1   thorpej 		for (m = m0; m; ) {
    602  1.14       cjs 			if (m->m_len > 1)  {
    603  1.14       cjs 				if (mtod(m, u_long) & 1)  {
    604  1.14       cjs 					bus_space_write_1(iot, ioh,
    605  1.14       cjs 					    EP_W1_TX_PIO_WR_1,
    606  1.14       cjs 					    *(mtod(m, u_int8_t *)));
    607  1.14       cjs 					m->m_data =
    608  1.14       cjs 					    (void *)(mtod(m, u_long) + 1);
    609  1.14       cjs 					m->m_len -= 1;
    610  1.14       cjs 				}
    611  1.11   thorpej 				bus_space_write_multi_2(iot, ioh,
    612   1.2   thorpej 				    EP_W1_TX_PIO_WR_1, mtod(m, u_int16_t *),
    613  1.14       cjs 				    m->m_len >> 1);
    614  1.14       cjs 			}
    615  1.14       cjs 			if (m->m_len & 1)  {
    616  1.11   thorpej 				bus_space_write_1(iot, ioh, EP_W1_TX_PIO_WR_1,
    617   1.2   thorpej 				     *(mtod(m, u_int8_t *) + m->m_len - 1));
    618  1.14       cjs 			}
    619   1.1   thorpej 			MFREE(m, m0);
    620   1.1   thorpej 			m = m0;
    621   1.1   thorpej 		}
    622   1.1   thorpej 	}
    623   1.1   thorpej 	while (pad--)
    624  1.11   thorpej 		bus_space_write_1(iot, ioh, EP_W1_TX_PIO_WR_1, 0);
    625   1.1   thorpej 
    626   1.1   thorpej 	splx(sh);
    627   1.1   thorpej 
    628   1.1   thorpej 	++ifp->if_opackets;
    629   1.1   thorpej 
    630   1.1   thorpej readcheck:
    631  1.11   thorpej 	if ((bus_space_read_2(iot, ioh, EP_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
    632   1.1   thorpej 		/* We received a complete packet. */
    633  1.11   thorpej 		u_int16_t status = bus_space_read_2(iot, ioh, EP_STATUS);
    634   1.1   thorpej 
    635   1.1   thorpej 		if ((status & S_INTR_LATCH) == 0) {
    636   1.1   thorpej 			/*
    637   1.1   thorpej 			 * No interrupt, read the packet and continue
    638   1.1   thorpej 			 * Is  this supposed to happen? Is my motherboard
    639   1.1   thorpej 			 * completely busted?
    640   1.1   thorpej 			 */
    641   1.1   thorpej 			epread(sc);
    642   1.1   thorpej 		}
    643   1.1   thorpej 		else
    644   1.1   thorpej 			/* Got an interrupt, return so that it gets serviced. */
    645   1.1   thorpej 			return;
    646   1.1   thorpej 	}
    647   1.1   thorpej 	else {
    648   1.1   thorpej 		/* Check if we are stuck and reset [see XXX comment] */
    649   1.1   thorpej 		if (epstatus(sc)) {
    650   1.1   thorpej 			if (ifp->if_flags & IFF_DEBUG)
    651  1.10  christos 				printf("%s: adapter reset\n",
    652   1.9  christos 				    sc->sc_dev.dv_xname);
    653   1.1   thorpej 			epreset(sc);
    654   1.1   thorpej 		}
    655   1.1   thorpej 	}
    656   1.1   thorpej 
    657   1.1   thorpej 	goto startagain;
    658   1.1   thorpej }
    659   1.1   thorpej 
    660   1.1   thorpej 
    661   1.1   thorpej /*
    662   1.1   thorpej  * XXX: The 3c509 card can get in a mode where both the fifo status bit
    663   1.1   thorpej  *	FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
    664   1.1   thorpej  *	We detect this situation and we reset the adapter.
    665   1.1   thorpej  *	It happens at times when there is a lot of broadcast traffic
    666   1.1   thorpej  *	on the cable (once in a blue moon).
    667   1.1   thorpej  */
    668   1.1   thorpej static int
    669   1.1   thorpej epstatus(sc)
    670   1.1   thorpej 	register struct ep_softc *sc;
    671   1.1   thorpej {
    672  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    673  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    674   1.7   thorpej 	u_int16_t fifost;
    675   1.1   thorpej 
    676   1.1   thorpej 	/*
    677   1.1   thorpej 	 * Check the FIFO status and act accordingly
    678   1.1   thorpej 	 */
    679   1.1   thorpej 	GO_WINDOW(4);
    680  1.11   thorpej 	fifost = bus_space_read_2(iot, ioh, EP_W4_FIFO_DIAG);
    681   1.1   thorpej 	GO_WINDOW(1);
    682   1.1   thorpej 
    683   1.1   thorpej 	if (fifost & FIFOS_RX_UNDERRUN) {
    684   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    685  1.10  christos 			printf("%s: RX underrun\n", sc->sc_dev.dv_xname);
    686   1.1   thorpej 		epreset(sc);
    687   1.1   thorpej 		return 0;
    688   1.1   thorpej 	}
    689   1.1   thorpej 
    690   1.1   thorpej 	if (fifost & FIFOS_RX_STATUS_OVERRUN) {
    691   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    692  1.10  christos 			printf("%s: RX Status overrun\n", sc->sc_dev.dv_xname);
    693   1.1   thorpej 		return 1;
    694   1.1   thorpej 	}
    695   1.1   thorpej 
    696   1.1   thorpej 	if (fifost & FIFOS_RX_OVERRUN) {
    697   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    698  1.10  christos 			printf("%s: RX overrun\n", sc->sc_dev.dv_xname);
    699   1.1   thorpej 		return 1;
    700   1.1   thorpej 	}
    701   1.1   thorpej 
    702   1.1   thorpej 	if (fifost & FIFOS_TX_OVERRUN) {
    703   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    704  1.10  christos 			printf("%s: TX overrun\n", sc->sc_dev.dv_xname);
    705   1.1   thorpej 		epreset(sc);
    706   1.1   thorpej 		return 0;
    707   1.1   thorpej 	}
    708   1.1   thorpej 
    709   1.1   thorpej 	return 0;
    710   1.1   thorpej }
    711   1.1   thorpej 
    712   1.1   thorpej 
    713   1.1   thorpej static void
    714   1.1   thorpej eptxstat(sc)
    715   1.1   thorpej 	register struct ep_softc *sc;
    716   1.1   thorpej {
    717  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    718  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    719   1.1   thorpej 	int i;
    720   1.1   thorpej 
    721   1.1   thorpej 	/*
    722   1.1   thorpej 	 * We need to read+write TX_STATUS until we get a 0 status
    723   1.1   thorpej 	 * in order to turn off the interrupt flag.
    724   1.1   thorpej 	 */
    725  1.11   thorpej 	while ((i = bus_space_read_1(iot, ioh, EP_W1_TX_STATUS)) & TXS_COMPLETE) {
    726  1.11   thorpej 		bus_space_write_1(iot, ioh, EP_W1_TX_STATUS, 0x0);
    727   1.1   thorpej 
    728   1.1   thorpej 		if (i & TXS_JABBER) {
    729   1.1   thorpej 			++sc->sc_arpcom.ac_if.if_oerrors;
    730   1.1   thorpej 			if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    731  1.10  christos 				printf("%s: jabber (%x)\n",
    732   1.1   thorpej 				       sc->sc_dev.dv_xname, i);
    733   1.1   thorpej 			epreset(sc);
    734   1.1   thorpej 		} else if (i & TXS_UNDERRUN) {
    735   1.1   thorpej 			++sc->sc_arpcom.ac_if.if_oerrors;
    736   1.1   thorpej 			if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    737  1.10  christos 				printf("%s: fifo underrun (%x) @%d\n",
    738   1.1   thorpej 				       sc->sc_dev.dv_xname, i,
    739   1.1   thorpej 				       sc->tx_start_thresh);
    740   1.1   thorpej 			if (sc->tx_succ_ok < 100)
    741   1.1   thorpej 				    sc->tx_start_thresh = min(ETHER_MAX_LEN,
    742   1.1   thorpej 					    sc->tx_start_thresh + 20);
    743   1.1   thorpej 			sc->tx_succ_ok = 0;
    744   1.1   thorpej 			epreset(sc);
    745   1.1   thorpej 		} else if (i & TXS_MAX_COLLISION) {
    746   1.1   thorpej 			++sc->sc_arpcom.ac_if.if_collisions;
    747  1.11   thorpej 			bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
    748   1.1   thorpej 			sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    749   1.1   thorpej 		} else
    750   1.1   thorpej 			sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127;
    751   1.1   thorpej 	}
    752   1.1   thorpej }
    753   1.1   thorpej 
    754   1.1   thorpej int
    755   1.1   thorpej epintr(arg)
    756   1.1   thorpej 	void *arg;
    757   1.1   thorpej {
    758   1.1   thorpej 	register struct ep_softc *sc = arg;
    759  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    760  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    761   1.1   thorpej 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    762   1.7   thorpej 	u_int16_t status;
    763   1.1   thorpej 	int ret = 0;
    764   1.1   thorpej 
    765   1.1   thorpej 	for (;;) {
    766  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
    767   1.1   thorpej 
    768  1.11   thorpej 		status = bus_space_read_2(iot, ioh, EP_STATUS);
    769   1.1   thorpej 
    770   1.1   thorpej 		if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
    771   1.1   thorpej 			       S_RX_COMPLETE | S_CARD_FAILURE)) == 0)
    772   1.1   thorpej 			break;
    773   1.1   thorpej 
    774   1.1   thorpej 		ret = 1;
    775   1.1   thorpej 
    776   1.1   thorpej 		/*
    777   1.1   thorpej 		 * Acknowledge any interrupts.  It's important that we do this
    778   1.1   thorpej 		 * first, since there would otherwise be a race condition.
    779   1.1   thorpej 		 * Due to the i386 interrupt queueing, we may get spurious
    780   1.1   thorpej 		 * interrupts occasionally.
    781   1.1   thorpej 		 */
    782  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | status);
    783   1.1   thorpej 
    784   1.1   thorpej 		if (status & S_RX_COMPLETE)
    785   1.1   thorpej 			epread(sc);
    786   1.1   thorpej 		if (status & S_TX_AVAIL) {
    787   1.1   thorpej 			sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    788   1.1   thorpej 			epstart(&sc->sc_arpcom.ac_if);
    789   1.1   thorpej 		}
    790   1.1   thorpej 		if (status & S_CARD_FAILURE) {
    791  1.10  christos 			printf("%s: adapter failure (%x)\n",
    792   1.9  christos 			    sc->sc_dev.dv_xname, status);
    793   1.1   thorpej 			epreset(sc);
    794   1.1   thorpej 			return (1);
    795   1.1   thorpej 		}
    796   1.1   thorpej 		if (status & S_TX_COMPLETE) {
    797   1.1   thorpej 			eptxstat(sc);
    798   1.1   thorpej 			epstart(ifp);
    799   1.1   thorpej 		}
    800   1.1   thorpej 	}
    801   1.1   thorpej 
    802   1.1   thorpej 	/* no more interrupts */
    803   1.1   thorpej 	return (ret);
    804   1.1   thorpej }
    805   1.1   thorpej 
    806   1.1   thorpej void
    807   1.1   thorpej epread(sc)
    808   1.1   thorpej 	register struct ep_softc *sc;
    809   1.1   thorpej {
    810  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    811  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    812   1.1   thorpej 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    813   1.1   thorpej 	struct mbuf *m;
    814   1.1   thorpej 	struct ether_header *eh;
    815   1.1   thorpej 	int len;
    816   1.1   thorpej 
    817  1.11   thorpej 	len = bus_space_read_2(iot, ioh, EP_W1_RX_STATUS);
    818   1.1   thorpej 
    819   1.1   thorpej again:
    820   1.1   thorpej 	if (ifp->if_flags & IFF_DEBUG) {
    821   1.1   thorpej 		int err = len & ERR_MASK;
    822   1.1   thorpej 		char *s = NULL;
    823   1.1   thorpej 
    824   1.1   thorpej 		if (len & ERR_INCOMPLETE)
    825   1.1   thorpej 			s = "incomplete packet";
    826   1.1   thorpej 		else if (err == ERR_OVERRUN)
    827   1.1   thorpej 			s = "packet overrun";
    828   1.1   thorpej 		else if (err == ERR_RUNT)
    829   1.1   thorpej 			s = "runt packet";
    830   1.1   thorpej 		else if (err == ERR_ALIGNMENT)
    831   1.1   thorpej 			s = "bad alignment";
    832   1.1   thorpej 		else if (err == ERR_CRC)
    833   1.1   thorpej 			s = "bad crc";
    834   1.1   thorpej 		else if (err == ERR_OVERSIZE)
    835   1.1   thorpej 			s = "oversized packet";
    836   1.1   thorpej 		else if (err == ERR_DRIBBLE)
    837   1.1   thorpej 			s = "dribble bits";
    838   1.1   thorpej 
    839   1.1   thorpej 		if (s)
    840  1.10  christos 			printf("%s: %s\n", sc->sc_dev.dv_xname, s);
    841   1.1   thorpej 	}
    842   1.1   thorpej 
    843   1.1   thorpej 	if (len & ERR_INCOMPLETE)
    844   1.1   thorpej 		return;
    845   1.1   thorpej 
    846   1.1   thorpej 	if (len & ERR_RX) {
    847   1.1   thorpej 		++ifp->if_ierrors;
    848   1.1   thorpej 		goto abort;
    849   1.1   thorpej 	}
    850   1.1   thorpej 
    851   1.1   thorpej 	len &= RX_BYTES_MASK;	/* Lower 11 bits = RX bytes. */
    852   1.1   thorpej 
    853   1.1   thorpej 	/* Pull packet off interface. */
    854   1.1   thorpej 	m = epget(sc, len);
    855   1.1   thorpej 	if (m == 0) {
    856   1.1   thorpej 		ifp->if_ierrors++;
    857   1.1   thorpej 		goto abort;
    858   1.1   thorpej 	}
    859   1.1   thorpej 
    860   1.1   thorpej 	++ifp->if_ipackets;
    861   1.1   thorpej 
    862   1.1   thorpej 	/* We assume the header fit entirely in one mbuf. */
    863   1.1   thorpej 	eh = mtod(m, struct ether_header *);
    864   1.1   thorpej 
    865   1.1   thorpej #if NBPFILTER > 0
    866   1.1   thorpej 	/*
    867   1.1   thorpej 	 * Check if there's a BPF listener on this interface.
    868   1.1   thorpej 	 * If so, hand off the raw packet to BPF.
    869   1.1   thorpej 	 */
    870   1.1   thorpej 	if (ifp->if_bpf) {
    871   1.1   thorpej 		bpf_mtap(ifp->if_bpf, m);
    872   1.1   thorpej 
    873   1.1   thorpej 		/*
    874   1.1   thorpej 		 * Note that the interface cannot be in promiscuous mode if
    875   1.1   thorpej 		 * there are no BPF listeners.  And if we are in promiscuous
    876   1.1   thorpej 		 * mode, we have to check if this packet is really ours.
    877   1.1   thorpej 		 */
    878   1.1   thorpej 		if ((ifp->if_flags & IFF_PROMISC) &&
    879   1.1   thorpej 		    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
    880   1.1   thorpej 		    bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
    881   1.1   thorpej 			    sizeof(eh->ether_dhost)) != 0) {
    882   1.1   thorpej 			m_freem(m);
    883   1.1   thorpej 			return;
    884   1.1   thorpej 		}
    885   1.1   thorpej 	}
    886   1.1   thorpej #endif
    887   1.1   thorpej 
    888   1.1   thorpej 	/* We assume the header fit entirely in one mbuf. */
    889   1.1   thorpej 	m_adj(m, sizeof(struct ether_header));
    890   1.1   thorpej 	ether_input(ifp, eh, m);
    891   1.1   thorpej 
    892   1.1   thorpej 	/*
    893   1.1   thorpej 	 * In periods of high traffic we can actually receive enough
    894   1.1   thorpej 	 * packets so that the fifo overrun bit will be set at this point,
    895   1.1   thorpej 	 * even though we just read a packet. In this case we
    896   1.1   thorpej 	 * are not going to receive any more interrupts. We check for
    897   1.1   thorpej 	 * this condition and read again until the fifo is not full.
    898   1.1   thorpej 	 * We could simplify this test by not using epstatus(), but
    899   1.1   thorpej 	 * rechecking the RX_STATUS register directly. This test could
    900   1.1   thorpej 	 * result in unnecessary looping in cases where there is a new
    901   1.1   thorpej 	 * packet but the fifo is not full, but it will not fix the
    902   1.1   thorpej 	 * stuck behavior.
    903   1.1   thorpej 	 *
    904   1.1   thorpej 	 * Even with this improvement, we still get packet overrun errors
    905   1.1   thorpej 	 * which are hurting performance. Maybe when I get some more time
    906   1.1   thorpej 	 * I'll modify epread() so that it can handle RX_EARLY interrupts.
    907   1.1   thorpej 	 */
    908   1.1   thorpej 	if (epstatus(sc)) {
    909  1.11   thorpej 		len = bus_space_read_2(iot, ioh, EP_W1_RX_STATUS);
    910   1.1   thorpej 		/* Check if we are stuck and reset [see XXX comment] */
    911   1.1   thorpej 		if (len & ERR_INCOMPLETE) {
    912   1.1   thorpej 			if (ifp->if_flags & IFF_DEBUG)
    913  1.10  christos 				printf("%s: adapter reset\n",
    914   1.9  christos 				    sc->sc_dev.dv_xname);
    915   1.1   thorpej 			epreset(sc);
    916   1.1   thorpej 			return;
    917   1.1   thorpej 		}
    918   1.1   thorpej 		goto again;
    919   1.1   thorpej 	}
    920   1.1   thorpej 
    921   1.1   thorpej 	return;
    922   1.1   thorpej 
    923   1.1   thorpej abort:
    924  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
    925  1.11   thorpej 	while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
    926   1.1   thorpej 		;
    927   1.1   thorpej }
    928   1.1   thorpej 
    929   1.1   thorpej struct mbuf *
    930   1.1   thorpej epget(sc, totlen)
    931   1.1   thorpej 	struct ep_softc *sc;
    932   1.1   thorpej 	int totlen;
    933   1.1   thorpej {
    934  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    935  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    936   1.1   thorpej 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    937   1.1   thorpej 	struct mbuf *top, **mp, *m;
    938  1.14       cjs 	int len, remaining;
    939   1.1   thorpej 	int sh;
    940   1.1   thorpej 
    941   1.1   thorpej 	m = sc->mb[sc->next_mb];
    942   1.1   thorpej 	sc->mb[sc->next_mb] = 0;
    943   1.1   thorpej 	if (m == 0) {
    944   1.1   thorpej 		MGETHDR(m, M_DONTWAIT, MT_DATA);
    945   1.1   thorpej 		if (m == 0)
    946   1.1   thorpej 			return 0;
    947   1.1   thorpej 	} else {
    948   1.1   thorpej 		/* If the queue is no longer full, refill. */
    949   1.1   thorpej 		if (sc->last_mb == sc->next_mb)
    950   1.1   thorpej 			timeout(epmbuffill, sc, 1);
    951   1.1   thorpej 		/* Convert one of our saved mbuf's. */
    952   1.1   thorpej 		sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
    953   1.1   thorpej 		m->m_data = m->m_pktdat;
    954   1.1   thorpej 		m->m_flags = M_PKTHDR;
    955   1.1   thorpej 	}
    956   1.1   thorpej 	m->m_pkthdr.rcvif = ifp;
    957   1.1   thorpej 	m->m_pkthdr.len = totlen;
    958   1.1   thorpej 	len = MHLEN;
    959   1.1   thorpej 	top = 0;
    960   1.1   thorpej 	mp = &top;
    961   1.1   thorpej 
    962   1.1   thorpej 	/*
    963   1.1   thorpej 	 * We read the packet at splhigh() so that an interrupt from another
    964   1.1   thorpej 	 * device doesn't cause the card's buffer to overflow while we're
    965   1.1   thorpej 	 * reading it.  We may still lose packets at other times.
    966   1.1   thorpej 	 */
    967   1.1   thorpej 	sh = splhigh();
    968   1.1   thorpej 
    969   1.1   thorpej 	while (totlen > 0) {
    970   1.1   thorpej 		if (top) {
    971   1.1   thorpej 			m = sc->mb[sc->next_mb];
    972   1.1   thorpej 			sc->mb[sc->next_mb] = 0;
    973   1.1   thorpej 			if (m == 0) {
    974   1.1   thorpej 				MGET(m, M_DONTWAIT, MT_DATA);
    975   1.1   thorpej 				if (m == 0) {
    976   1.1   thorpej 					splx(sh);
    977   1.1   thorpej 					m_freem(top);
    978   1.1   thorpej 					return 0;
    979   1.1   thorpej 				}
    980   1.1   thorpej 			} else {
    981   1.1   thorpej 				sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
    982   1.1   thorpej 			}
    983   1.1   thorpej 			len = MLEN;
    984   1.1   thorpej 		}
    985   1.1   thorpej 		if (totlen >= MINCLSIZE) {
    986   1.1   thorpej 			MCLGET(m, M_DONTWAIT);
    987   1.1   thorpej 			if (m->m_flags & M_EXT)
    988   1.1   thorpej 				len = MCLBYTES;
    989   1.1   thorpej 		}
    990  1.14       cjs 		if (EP_IS_BUS_32(sc->bustype) )  {
    991  1.14       cjs 			u_long pad;
    992  1.14       cjs 			if (top == 0)  {
    993  1.14       cjs 			    /* align the struct ip header */
    994  1.14       cjs 			    pad = ALIGN(sizeof(struct ether_header))
    995  1.14       cjs 				 - sizeof(struct ether_header);
    996  1.14       cjs 			} else {
    997  1.14       cjs 			    /* XXX do we really need this? */
    998  1.14       cjs 			    pad = ALIGN(m->m_data) - (u_long) m->m_data;
    999  1.14       cjs 			}
   1000  1.14       cjs 			m->m_data += pad;
   1001  1.14       cjs 			len -= pad;
   1002  1.14       cjs 		}
   1003  1.14       cjs 		remaining = len = min(totlen, len);
   1004   1.1   thorpej 		if (EP_IS_BUS_32(sc->bustype)) {
   1005  1.14       cjs 			u_long offset = mtod(m, u_long);
   1006  1.14       cjs 			/*
   1007  1.14       cjs 			 * Read bytes up to the point where we are aligned.
   1008  1.14       cjs 			 * (We can align to 4 bytes, rather than ALIGNBYTES,
   1009  1.14       cjs 			 * here because we're later reading 4-byte chunks.)
   1010  1.14       cjs 			 */
   1011  1.14       cjs 			if ((remaining > 3) && (offset & 3))  {
   1012  1.14       cjs 				int count = (4 - (offset & 3));
   1013  1.14       cjs 				bus_space_read_multi_1(iot, ioh,
   1014  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1015  1.14       cjs 				    (u_int8_t *) offset, count);
   1016  1.14       cjs 				offset += count;
   1017  1.14       cjs 				remaining -= count;
   1018  1.14       cjs 			}
   1019  1.14       cjs 			if (remaining > 3) {
   1020  1.11   thorpej 				bus_space_read_multi_4(iot, ioh,
   1021  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1022  1.14       cjs 				    (u_int32_t *) offset, remaining >> 2);
   1023  1.14       cjs 				offset += remaining & ~3;
   1024  1.14       cjs 				remaining &= 3;
   1025  1.14       cjs 			}
   1026  1.14       cjs 			if (remaining)  {
   1027  1.11   thorpej 				bus_space_read_multi_1(iot, ioh,
   1028  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1029  1.14       cjs 				    (u_int8_t *) offset, remaining);
   1030  1.14       cjs 			}
   1031   1.1   thorpej 		} else {
   1032  1.14       cjs 			u_long offset = mtod(m, u_long);
   1033  1.14       cjs 			if ((remaining > 1) && (offset & 1))  {
   1034  1.14       cjs 				bus_space_read_multi_1(iot, ioh,
   1035  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1036  1.14       cjs 				    (u_int8_t *) offset, 1);
   1037  1.14       cjs 				remaining -= 1;
   1038  1.14       cjs 				offset += 1;
   1039  1.14       cjs 			}
   1040  1.14       cjs 			if (remaining > 1) {
   1041  1.11   thorpej 				bus_space_read_multi_2(iot, ioh,
   1042  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1043  1.14       cjs 				    (u_int16_t *) offset, remaining >> 1);
   1044  1.14       cjs 				offset += remaining & ~1;
   1045  1.14       cjs 			}
   1046  1.14       cjs 			if (remaining & 1)  {
   1047  1.14       cjs 				bus_space_read_multi_1(iot, ioh,
   1048  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1049  1.14       cjs 				    (u_int8_t *) offset, remaining & 1);
   1050  1.14       cjs 			}
   1051   1.1   thorpej 		}
   1052   1.1   thorpej 		m->m_len = len;
   1053   1.1   thorpej 		totlen -= len;
   1054   1.1   thorpej 		*mp = m;
   1055   1.1   thorpej 		mp = &m->m_next;
   1056   1.1   thorpej 	}
   1057   1.1   thorpej 
   1058  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
   1059  1.11   thorpej 	while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
   1060   1.1   thorpej 		;
   1061   1.1   thorpej 
   1062   1.1   thorpej 	splx(sh);
   1063   1.1   thorpej 
   1064   1.1   thorpej 	return top;
   1065   1.1   thorpej }
   1066   1.1   thorpej 
   1067   1.1   thorpej int
   1068   1.1   thorpej epioctl(ifp, cmd, data)
   1069   1.1   thorpej 	register struct ifnet *ifp;
   1070   1.1   thorpej 	u_long cmd;
   1071   1.1   thorpej 	caddr_t data;
   1072   1.1   thorpej {
   1073   1.5   thorpej 	struct ep_softc *sc = ifp->if_softc;
   1074   1.1   thorpej 	struct ifaddr *ifa = (struct ifaddr *)data;
   1075   1.1   thorpej 	struct ifreq *ifr = (struct ifreq *)data;
   1076   1.1   thorpej 	int s, error = 0;
   1077   1.1   thorpej 
   1078   1.1   thorpej 	s = splnet();
   1079   1.1   thorpej 
   1080   1.1   thorpej 	switch (cmd) {
   1081   1.1   thorpej 
   1082   1.1   thorpej 	case SIOCSIFADDR:
   1083   1.1   thorpej 		ifp->if_flags |= IFF_UP;
   1084   1.1   thorpej 
   1085   1.1   thorpej 		switch (ifa->ifa_addr->sa_family) {
   1086   1.1   thorpej #ifdef INET
   1087   1.1   thorpej 		case AF_INET:
   1088   1.1   thorpej 			epinit(sc);
   1089   1.1   thorpej 			arp_ifinit(&sc->sc_arpcom, ifa);
   1090   1.1   thorpej 			break;
   1091   1.1   thorpej #endif
   1092   1.1   thorpej #ifdef NS
   1093   1.1   thorpej 		case AF_NS:
   1094   1.1   thorpej 		    {
   1095   1.1   thorpej 			register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
   1096   1.1   thorpej 
   1097   1.1   thorpej 			if (ns_nullhost(*ina))
   1098   1.1   thorpej 				ina->x_host =
   1099   1.1   thorpej 				    *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
   1100   1.1   thorpej 			else
   1101   1.1   thorpej 				bcopy(ina->x_host.c_host,
   1102   1.1   thorpej 				    sc->sc_arpcom.ac_enaddr,
   1103   1.1   thorpej 				    sizeof(sc->sc_arpcom.ac_enaddr));
   1104   1.1   thorpej 			/* Set new address. */
   1105   1.1   thorpej 			epinit(sc);
   1106   1.1   thorpej 			break;
   1107   1.1   thorpej 		    }
   1108   1.1   thorpej #endif
   1109   1.1   thorpej 		default:
   1110   1.1   thorpej 			epinit(sc);
   1111   1.1   thorpej 			break;
   1112   1.1   thorpej 		}
   1113   1.1   thorpej 		break;
   1114   1.1   thorpej 
   1115   1.1   thorpej 	case SIOCSIFFLAGS:
   1116   1.1   thorpej 		if ((ifp->if_flags & IFF_UP) == 0 &&
   1117   1.1   thorpej 		    (ifp->if_flags & IFF_RUNNING) != 0) {
   1118   1.1   thorpej 			/*
   1119   1.1   thorpej 			 * If interface is marked down and it is running, then
   1120   1.1   thorpej 			 * stop it.
   1121   1.1   thorpej 			 */
   1122   1.1   thorpej 			epstop(sc);
   1123   1.1   thorpej 			ifp->if_flags &= ~IFF_RUNNING;
   1124   1.1   thorpej 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
   1125   1.1   thorpej 			   (ifp->if_flags & IFF_RUNNING) == 0) {
   1126   1.1   thorpej 			/*
   1127   1.1   thorpej 			 * If interface is marked up and it is stopped, then
   1128   1.1   thorpej 			 * start it.
   1129   1.1   thorpej 			 */
   1130   1.1   thorpej 			epinit(sc);
   1131   1.1   thorpej 		} else {
   1132   1.1   thorpej 			/*
   1133   1.1   thorpej 			 * deal with flags changes:
   1134   1.1   thorpej 			 * IFF_MULTICAST, IFF_PROMISC,
   1135   1.1   thorpej 			 * IFF_LINK0, IFF_LINK1,
   1136   1.1   thorpej 			 */
   1137   1.1   thorpej 			epsetfilter(sc);
   1138   1.1   thorpej 			epsetlink(sc);
   1139   1.1   thorpej 		}
   1140   1.1   thorpej 		break;
   1141   1.1   thorpej 
   1142   1.1   thorpej 	case SIOCADDMULTI:
   1143   1.1   thorpej 	case SIOCDELMULTI:
   1144   1.1   thorpej 		error = (cmd == SIOCADDMULTI) ?
   1145   1.1   thorpej 		    ether_addmulti(ifr, &sc->sc_arpcom) :
   1146   1.1   thorpej 		    ether_delmulti(ifr, &sc->sc_arpcom);
   1147   1.1   thorpej 
   1148   1.1   thorpej 		if (error == ENETRESET) {
   1149   1.1   thorpej 			/*
   1150   1.1   thorpej 			 * Multicast list has changed; set the hardware filter
   1151   1.1   thorpej 			 * accordingly.
   1152   1.1   thorpej 			 */
   1153   1.1   thorpej 			epreset(sc);
   1154   1.1   thorpej 			error = 0;
   1155   1.1   thorpej 		}
   1156   1.1   thorpej 		break;
   1157   1.1   thorpej 
   1158   1.1   thorpej 	default:
   1159   1.1   thorpej 		error = EINVAL;
   1160   1.1   thorpej 		break;
   1161   1.1   thorpej 	}
   1162   1.1   thorpej 
   1163   1.1   thorpej 	splx(s);
   1164   1.1   thorpej 	return (error);
   1165   1.1   thorpej }
   1166   1.1   thorpej 
   1167   1.1   thorpej void
   1168   1.1   thorpej epreset(sc)
   1169   1.1   thorpej 	struct ep_softc *sc;
   1170   1.1   thorpej {
   1171   1.1   thorpej 	int s;
   1172   1.1   thorpej 
   1173   1.1   thorpej 	s = splnet();
   1174   1.1   thorpej 	epstop(sc);
   1175   1.1   thorpej 	epinit(sc);
   1176   1.1   thorpej 	splx(s);
   1177   1.1   thorpej }
   1178   1.1   thorpej 
   1179   1.1   thorpej void
   1180   1.5   thorpej epwatchdog(ifp)
   1181   1.5   thorpej 	struct ifnet *ifp;
   1182   1.1   thorpej {
   1183   1.5   thorpej 	struct ep_softc *sc = ifp->if_softc;
   1184   1.1   thorpej 
   1185   1.1   thorpej 	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
   1186   1.1   thorpej 	++sc->sc_arpcom.ac_if.if_oerrors;
   1187   1.1   thorpej 
   1188   1.1   thorpej 	epreset(sc);
   1189   1.1   thorpej }
   1190   1.1   thorpej 
   1191   1.1   thorpej void
   1192   1.1   thorpej epstop(sc)
   1193   1.1   thorpej 	register struct ep_softc *sc;
   1194   1.1   thorpej {
   1195  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
   1196  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
   1197   1.1   thorpej 
   1198  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
   1199  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
   1200  1.11   thorpej 	while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
   1201   1.1   thorpej 		;
   1202  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
   1203  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
   1204  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET);
   1205  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
   1206  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
   1207  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
   1208  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
   1209  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
   1210   1.1   thorpej 
   1211   1.1   thorpej 	epmbufempty(sc);
   1212   1.1   thorpej }
   1213  1.16  jonathan 
   1214  1.16  jonathan 
   1215  1.16  jonathan /*
   1216  1.16  jonathan  * Before reboots, reset card completely.
   1217  1.16  jonathan  */
   1218  1.16  jonathan static void
   1219  1.16  jonathan epshutdown(arg)
   1220  1.16  jonathan 	void *arg;
   1221  1.16  jonathan {
   1222  1.16  jonathan 	register struct ep_softc *sc = arg;
   1223  1.16  jonathan 	bus_space_tag_t iot = sc->sc_iot;
   1224  1.16  jonathan 	bus_space_handle_t ioh = sc->sc_ioh;
   1225  1.16  jonathan 
   1226  1.16  jonathan 	epstop(sc);
   1227  1.16  jonathan 	bus_space_write_2(iot, ioh, EP_COMMAND, GLOBAL_RESET);
   1228  1.16  jonathan 	/*
   1229  1.16  jonathan 	 * should loop waiting for CMD_COMPLETE but some earlier cards
   1230  1.16  jonathan 	 * may not support that properly.
   1231  1.16  jonathan 	 */
   1232  1.16  jonathan 	DELAY(20000);	/* need at least 1 ms, but be generous. */
   1233  1.16  jonathan }
   1234  1.16  jonathan 
   1235   1.1   thorpej 
   1236   1.1   thorpej /*
   1237   1.1   thorpej  * We get eeprom data from the id_port given an offset into the
   1238   1.1   thorpej  * eeprom.  Basically; after the ID_sequence is sent to all of
   1239   1.1   thorpej  * the cards; they enter the ID_CMD state where they will accept
   1240   1.1   thorpej  * command requests. 0x80-0xbf loads the eeprom data.  We then
   1241   1.1   thorpej  * read the port 16 times and with every read; the cards check
   1242   1.1   thorpej  * for contention (ie: if one card writes a 0 bit and another
   1243   1.1   thorpej  * writes a 1 bit then the host sees a 0. At the end of the cycle;
   1244   1.1   thorpej  * each card compares the data on the bus; if there is a difference
   1245   1.1   thorpej  * then that card goes into ID_WAIT state again). In the meantime;
   1246   1.1   thorpej  * one bit of data is returned in the AX register which is conveniently
   1247  1.11   thorpej  * returned to us by bus_space_read_1().  Hence; we read 16 times getting one
   1248   1.1   thorpej  * bit of data with each read.
   1249   1.2   thorpej  *
   1250   1.2   thorpej  * NOTE: the caller must provide an i/o handle for ELINK_ID_PORT!
   1251   1.1   thorpej  */
   1252   1.2   thorpej u_int16_t
   1253  1.11   thorpej epreadeeprom(iot, ioh, offset)
   1254  1.11   thorpej 	bus_space_tag_t iot;
   1255  1.11   thorpej 	bus_space_handle_t ioh;
   1256   1.2   thorpej 	int offset;
   1257   1.1   thorpej {
   1258   1.2   thorpej 	u_int16_t data = 0;
   1259   1.2   thorpej 	int i;
   1260   1.1   thorpej 
   1261  1.11   thorpej 	bus_space_write_1(iot, ioh, 0, 0x80 + offset);
   1262   1.1   thorpej 	delay(1000);
   1263   1.1   thorpej 	for (i = 0; i < 16; i++)
   1264  1.11   thorpej 		data = (data << 1) | (bus_space_read_2(iot, ioh, 0) & 1);
   1265   1.1   thorpej 	return (data);
   1266   1.1   thorpej }
   1267   1.1   thorpej 
   1268   1.1   thorpej static int
   1269   1.1   thorpej epbusyeeprom(sc)
   1270   1.1   thorpej 	struct ep_softc *sc;
   1271   1.1   thorpej {
   1272  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
   1273  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
   1274   1.1   thorpej 	int i = 100, j;
   1275   1.1   thorpej 
   1276   1.1   thorpej 	if (sc->bustype == EP_BUS_PCMCIA) {
   1277   1.1   thorpej 		delay(1000);
   1278   1.1   thorpej 		return 0;
   1279   1.1   thorpej 	}
   1280   1.1   thorpej 
   1281   1.1   thorpej 	while (i--) {
   1282  1.11   thorpej 		j = bus_space_read_2(iot, ioh, EP_W0_EEPROM_COMMAND);
   1283   1.1   thorpej 		if (j & EEPROM_BUSY)
   1284   1.1   thorpej 			delay(100);
   1285   1.1   thorpej 		else
   1286   1.1   thorpej 			break;
   1287   1.1   thorpej 	}
   1288   1.1   thorpej 	if (!i) {
   1289  1.10  christos 		printf("\n%s: eeprom failed to come ready\n",
   1290   1.1   thorpej 		    sc->sc_dev.dv_xname);
   1291   1.1   thorpej 		return (1);
   1292   1.1   thorpej 	}
   1293   1.1   thorpej 	if (j & EEPROM_TST_MODE) {
   1294  1.10  christos 		printf("\n%s: erase pencil mark, or disable plug-n-play mode!\n",
   1295   1.1   thorpej 		    sc->sc_dev.dv_xname);
   1296   1.1   thorpej 		return (1);
   1297   1.1   thorpej 	}
   1298   1.1   thorpej 	return (0);
   1299   1.1   thorpej }
   1300   1.1   thorpej 
   1301   1.1   thorpej void
   1302   1.3  christos epmbuffill(v)
   1303   1.3  christos 	void *v;
   1304   1.1   thorpej {
   1305   1.3  christos 	struct ep_softc *sc = v;
   1306   1.1   thorpej 	int s, i;
   1307   1.1   thorpej 
   1308   1.1   thorpej 	s = splnet();
   1309   1.1   thorpej 	i = sc->last_mb;
   1310   1.1   thorpej 	do {
   1311   1.1   thorpej 		if (sc->mb[i] == NULL)
   1312   1.1   thorpej 			MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
   1313   1.1   thorpej 		if (sc->mb[i] == NULL)
   1314   1.1   thorpej 			break;
   1315   1.1   thorpej 		i = (i + 1) % MAX_MBS;
   1316   1.1   thorpej 	} while (i != sc->next_mb);
   1317   1.1   thorpej 	sc->last_mb = i;
   1318   1.1   thorpej 	/* If the queue was not filled, try again. */
   1319   1.1   thorpej 	if (sc->last_mb != sc->next_mb)
   1320   1.1   thorpej 		timeout(epmbuffill, sc, 1);
   1321   1.1   thorpej 	splx(s);
   1322   1.1   thorpej }
   1323   1.1   thorpej 
   1324   1.1   thorpej void
   1325   1.1   thorpej epmbufempty(sc)
   1326   1.1   thorpej 	struct ep_softc *sc;
   1327   1.1   thorpej {
   1328   1.1   thorpej 	int s, i;
   1329   1.1   thorpej 
   1330   1.1   thorpej 	s = splnet();
   1331   1.1   thorpej 	for (i = 0; i<MAX_MBS; i++) {
   1332   1.1   thorpej 		if (sc->mb[i]) {
   1333   1.1   thorpej 			m_freem(sc->mb[i]);
   1334   1.1   thorpej 			sc->mb[i] = NULL;
   1335   1.1   thorpej 		}
   1336   1.1   thorpej 	}
   1337   1.1   thorpej 	sc->last_mb = sc->next_mb = 0;
   1338   1.1   thorpej 	untimeout(epmbuffill, sc);
   1339   1.1   thorpej 	splx(s);
   1340   1.1   thorpej }
   1341