Home | History | Annotate | Line # | Download | only in ic
elink3.c revision 1.18
      1  1.18  jonathan /*	$NetBSD: elink3.c,v 1.18 1996/12/31 21:36:30 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.17  jonathan 	u_int 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.18  jonathan 	DELAY(100000);	/* need at least 1 ms, but be generous. */
    400  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
    401  1.18  jonathan 	DELAY(100000);	/* need at least 1 ms, but be generous. */
    402   1.1   thorpej 
    403   1.1   thorpej 	GO_WINDOW(1);		/* Window 1 is operating window */
    404   1.1   thorpej 	for (i = 0; i < 31; i++)
    405  1.11   thorpej 		bus_space_read_1(iot, ioh, EP_W1_TX_STATUS);
    406   1.1   thorpej 
    407  1.18  jonathan 	/* Enable interrupts. */
    408  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE |
    409   1.1   thorpej 				S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
    410  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE |
    411   1.1   thorpej 				S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
    412   1.1   thorpej 
    413   1.1   thorpej 	/*
    414   1.1   thorpej 	 * Attempt to get rid of any stray interrupts that occured during
    415   1.1   thorpej 	 * configuration.  On the i386 this isn't possible because one may
    416   1.1   thorpej 	 * already be queued.  However, a single stray interrupt is
    417   1.1   thorpej 	 * unimportant.
    418   1.1   thorpej 	 */
    419  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff);
    420   1.1   thorpej 
    421   1.1   thorpej 	epsetfilter(sc);
    422   1.1   thorpej 	epsetlink(sc);
    423   1.1   thorpej 
    424  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
    425  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
    426   1.1   thorpej 
    427   1.1   thorpej 	epmbuffill(sc);
    428   1.1   thorpej 
    429   1.1   thorpej 	/* Interface is now `running', with no output active. */
    430   1.1   thorpej 	ifp->if_flags |= IFF_RUNNING;
    431   1.1   thorpej 	ifp->if_flags &= ~IFF_OACTIVE;
    432   1.1   thorpej 
    433   1.1   thorpej 	/* Attempt to start output, if any. */
    434   1.1   thorpej 	epstart(ifp);
    435   1.1   thorpej }
    436   1.1   thorpej 
    437   1.1   thorpej void
    438   1.1   thorpej epsetfilter(sc)
    439   1.1   thorpej 	register struct ep_softc *sc;
    440   1.1   thorpej {
    441   1.1   thorpej 	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    442   1.1   thorpej 
    443   1.1   thorpej 	GO_WINDOW(1);		/* Window 1 is operating window */
    444  1.11   thorpej 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_COMMAND, SET_RX_FILTER |
    445   1.1   thorpej 	    FIL_INDIVIDUAL | FIL_BRDCST |
    446   1.1   thorpej 	    ((ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0 ) |
    447   1.1   thorpej 	    ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 ));
    448   1.1   thorpej }
    449   1.1   thorpej 
    450  1.15  jonathan /*
    451  1.15  jonathan  * select media based on link{0,1,2} switches.
    452  1.15  jonathan  * Assumes 10Mbit interface, totatlly broken for 10/100 adaptors.
    453  1.15  jonathan  */
    454   1.1   thorpej void
    455   1.1   thorpej epsetlink(sc)
    456   1.1   thorpej 	register struct ep_softc *sc;
    457   1.1   thorpej {
    458   1.1   thorpej 	register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    459  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    460  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    461   1.1   thorpej 
    462   1.1   thorpej 	/*
    463   1.1   thorpej 	 * you can `ifconfig (link0|-link0) ep0' to get the following
    464   1.1   thorpej 	 * behaviour:
    465   1.1   thorpej 	 *	-link0	disable AUI/UTP. enable BNC.
    466   1.1   thorpej 	 *	link0	disable BNC. enable AUI.
    467   1.1   thorpej 	 *	link1	if the card has a UTP connector, and link0 is
    468   1.1   thorpej 	 *		set too, then you get the UTP port.
    469   1.1   thorpej 	 */
    470   1.1   thorpej 	GO_WINDOW(4);
    471  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, DISABLE_UTP);
    472   1.1   thorpej 	if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) {
    473   1.1   thorpej 		if (sc->bustype == EP_BUS_PCMCIA) {
    474   1.1   thorpej 			GO_WINDOW(0);
    475  1.11   thorpej 			bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,3<<14);
    476   1.1   thorpej 			GO_WINDOW(1);
    477   1.1   thorpej 		}
    478  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER);
    479   1.1   thorpej 		delay(1000);
    480   1.1   thorpej 	}
    481   1.1   thorpej 	if (ifp->if_flags & IFF_LINK0) {
    482  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
    483   1.1   thorpej 		delay(1000);
    484   1.1   thorpej 		if ((ifp->if_flags & IFF_LINK1) && (sc->ep_connectors & UTP)) {
    485   1.1   thorpej 			if (sc->bustype == EP_BUS_PCMCIA) {
    486   1.1   thorpej 				GO_WINDOW(0);
    487  1.11   thorpej 				bus_space_write_2(iot, ioh,
    488   1.2   thorpej 				    EP_W0_ADDRESS_CFG,0<<14);
    489   1.1   thorpej 				GO_WINDOW(4);
    490   1.1   thorpej 			}
    491  1.11   thorpej 			bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, ENABLE_UTP);
    492   1.1   thorpej 		}
    493   1.1   thorpej 	}
    494   1.1   thorpej 	GO_WINDOW(1);
    495   1.1   thorpej }
    496   1.1   thorpej 
    497   1.1   thorpej /*
    498   1.1   thorpej  * Start outputting on the interface.
    499   1.1   thorpej  * Always called as splnet().
    500   1.1   thorpej  */
    501   1.1   thorpej void
    502   1.1   thorpej epstart(ifp)
    503   1.1   thorpej 	struct ifnet *ifp;
    504   1.1   thorpej {
    505   1.5   thorpej 	register struct ep_softc *sc = ifp->if_softc;
    506  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    507  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    508   1.1   thorpej 	struct mbuf *m, *m0;
    509   1.1   thorpej 	int sh, len, pad;
    510   1.1   thorpej 
    511   1.1   thorpej 	/* Don't transmit if interface is busy or not running */
    512   1.1   thorpej 	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
    513   1.1   thorpej 		return;
    514   1.1   thorpej 
    515   1.1   thorpej startagain:
    516   1.1   thorpej 	/* Sneak a peek at the next packet */
    517   1.1   thorpej 	m0 = ifp->if_snd.ifq_head;
    518   1.1   thorpej 	if (m0 == 0)
    519   1.1   thorpej 		return;
    520   1.1   thorpej 
    521   1.1   thorpej 	/* We need to use m->m_pkthdr.len, so require the header */
    522   1.1   thorpej 	if ((m0->m_flags & M_PKTHDR) == 0)
    523   1.1   thorpej 		panic("epstart: no header mbuf");
    524   1.1   thorpej 	len = m0->m_pkthdr.len;
    525   1.1   thorpej 
    526   1.1   thorpej 	pad = (4 - len) & 3;
    527   1.1   thorpej 
    528   1.1   thorpej 	/*
    529   1.1   thorpej 	 * The 3c509 automatically pads short packets to minimum ethernet
    530   1.1   thorpej 	 * length, but we drop packets that are too large. Perhaps we should
    531   1.1   thorpej 	 * truncate them instead?
    532   1.1   thorpej 	 */
    533   1.1   thorpej 	if (len + pad > ETHER_MAX_LEN) {
    534   1.1   thorpej 		/* packet is obviously too large: toss it */
    535   1.1   thorpej 		++ifp->if_oerrors;
    536   1.1   thorpej 		IF_DEQUEUE(&ifp->if_snd, m0);
    537   1.1   thorpej 		m_freem(m0);
    538   1.1   thorpej 		goto readcheck;
    539   1.1   thorpej 	}
    540   1.1   thorpej 
    541  1.11   thorpej 	if (bus_space_read_2(iot, ioh, EP_W1_FREE_TX) < len + pad + 4) {
    542  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND,
    543  1.12  jonathan 		    SET_TX_AVAIL_THRESH |
    544  1.12  jonathan 		    ((len + pad + 4) >> sc->ep_pktlenshift));
    545   1.1   thorpej 		/* not enough room in FIFO */
    546   1.1   thorpej 		ifp->if_flags |= IFF_OACTIVE;
    547   1.1   thorpej 		return;
    548   1.1   thorpej 	} else {
    549  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND,
    550  1.12  jonathan 		    SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE );
    551   1.1   thorpej 	}
    552   1.1   thorpej 
    553   1.1   thorpej 	IF_DEQUEUE(&ifp->if_snd, m0);
    554   1.1   thorpej 	if (m0 == 0)		/* not really needed */
    555   1.1   thorpej 		return;
    556   1.1   thorpej 
    557  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
    558  1.12  jonathan 	    ((len / 4 + sc->tx_start_thresh) /* >> sc->ep_pktlenshift*/) );
    559   1.1   thorpej 
    560   1.1   thorpej #if NBPFILTER > 0
    561   1.1   thorpej 	if (ifp->if_bpf)
    562   1.1   thorpej 		bpf_mtap(ifp->if_bpf, m0);
    563   1.1   thorpej #endif
    564   1.1   thorpej 
    565   1.1   thorpej 	/*
    566   1.1   thorpej 	 * Do the output at splhigh() so that an interrupt from another device
    567   1.1   thorpej 	 * won't cause a FIFO underrun.
    568   1.1   thorpej 	 */
    569   1.1   thorpej 	sh = splhigh();
    570   1.1   thorpej 
    571  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_W1_TX_PIO_WR_1, len);
    572  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_W1_TX_PIO_WR_1,
    573   1.2   thorpej 	    0xffff);	/* Second dword meaningless */
    574   1.1   thorpej 	if (EP_IS_BUS_32(sc->bustype)) {
    575   1.1   thorpej 		for (m = m0; m; ) {
    576  1.14       cjs 			if (m->m_len > 3)  {
    577  1.14       cjs 				/* align our reads from core */
    578  1.14       cjs 				if (mtod(m, u_long) & 3)  {
    579  1.14       cjs 					u_long count =
    580  1.14       cjs 					    4 - (mtod(m, u_long) & 3);
    581  1.14       cjs 					bus_space_write_multi_1(iot, ioh,
    582  1.14       cjs 					    EP_W1_TX_PIO_WR_1,
    583  1.14       cjs 					    mtod(m, u_int8_t *), count);
    584  1.14       cjs 					m->m_data =
    585  1.14       cjs 					    (void *)(mtod(m, u_long) + count);
    586  1.14       cjs 					m->m_len -= count;
    587  1.14       cjs 				}
    588  1.11   thorpej 				bus_space_write_multi_4(iot, ioh,
    589  1.14       cjs 				    EP_W1_TX_PIO_WR_1,
    590  1.14       cjs 				    mtod(m, u_int32_t *), m->m_len >> 2);
    591  1.14       cjs 				m->m_data = (void *)(mtod(m, u_long) +
    592  1.14       cjs 					(u_long)(m->m_len & ~3));
    593  1.14       cjs 				m->m_len -= m->m_len & ~3;
    594  1.14       cjs 			}
    595  1.14       cjs 			if (m->m_len)  {
    596  1.11   thorpej 				bus_space_write_multi_1(iot, ioh,
    597   1.2   thorpej 				    EP_W1_TX_PIO_WR_1,
    598  1.14       cjs 				    mtod(m, u_int8_t *), m->m_len);
    599  1.14       cjs 			}
    600   1.1   thorpej 			MFREE(m, m0);
    601   1.1   thorpej 			m = m0;
    602   1.1   thorpej 		}
    603   1.1   thorpej 	} else {
    604   1.1   thorpej 		for (m = m0; m; ) {
    605  1.14       cjs 			if (m->m_len > 1)  {
    606  1.14       cjs 				if (mtod(m, u_long) & 1)  {
    607  1.14       cjs 					bus_space_write_1(iot, ioh,
    608  1.14       cjs 					    EP_W1_TX_PIO_WR_1,
    609  1.14       cjs 					    *(mtod(m, u_int8_t *)));
    610  1.14       cjs 					m->m_data =
    611  1.14       cjs 					    (void *)(mtod(m, u_long) + 1);
    612  1.14       cjs 					m->m_len -= 1;
    613  1.14       cjs 				}
    614  1.11   thorpej 				bus_space_write_multi_2(iot, ioh,
    615   1.2   thorpej 				    EP_W1_TX_PIO_WR_1, mtod(m, u_int16_t *),
    616  1.14       cjs 				    m->m_len >> 1);
    617  1.14       cjs 			}
    618  1.14       cjs 			if (m->m_len & 1)  {
    619  1.11   thorpej 				bus_space_write_1(iot, ioh, EP_W1_TX_PIO_WR_1,
    620   1.2   thorpej 				     *(mtod(m, u_int8_t *) + m->m_len - 1));
    621  1.14       cjs 			}
    622   1.1   thorpej 			MFREE(m, m0);
    623   1.1   thorpej 			m = m0;
    624   1.1   thorpej 		}
    625   1.1   thorpej 	}
    626   1.1   thorpej 	while (pad--)
    627  1.11   thorpej 		bus_space_write_1(iot, ioh, EP_W1_TX_PIO_WR_1, 0);
    628   1.1   thorpej 
    629   1.1   thorpej 	splx(sh);
    630   1.1   thorpej 
    631   1.1   thorpej 	++ifp->if_opackets;
    632   1.1   thorpej 
    633   1.1   thorpej readcheck:
    634  1.11   thorpej 	if ((bus_space_read_2(iot, ioh, EP_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
    635   1.1   thorpej 		/* We received a complete packet. */
    636  1.11   thorpej 		u_int16_t status = bus_space_read_2(iot, ioh, EP_STATUS);
    637   1.1   thorpej 
    638   1.1   thorpej 		if ((status & S_INTR_LATCH) == 0) {
    639   1.1   thorpej 			/*
    640   1.1   thorpej 			 * No interrupt, read the packet and continue
    641   1.1   thorpej 			 * Is  this supposed to happen? Is my motherboard
    642   1.1   thorpej 			 * completely busted?
    643   1.1   thorpej 			 */
    644   1.1   thorpej 			epread(sc);
    645   1.1   thorpej 		}
    646   1.1   thorpej 		else
    647   1.1   thorpej 			/* Got an interrupt, return so that it gets serviced. */
    648   1.1   thorpej 			return;
    649   1.1   thorpej 	}
    650   1.1   thorpej 	else {
    651   1.1   thorpej 		/* Check if we are stuck and reset [see XXX comment] */
    652   1.1   thorpej 		if (epstatus(sc)) {
    653   1.1   thorpej 			if (ifp->if_flags & IFF_DEBUG)
    654  1.10  christos 				printf("%s: adapter reset\n",
    655   1.9  christos 				    sc->sc_dev.dv_xname);
    656   1.1   thorpej 			epreset(sc);
    657   1.1   thorpej 		}
    658   1.1   thorpej 	}
    659   1.1   thorpej 
    660   1.1   thorpej 	goto startagain;
    661   1.1   thorpej }
    662   1.1   thorpej 
    663   1.1   thorpej 
    664   1.1   thorpej /*
    665   1.1   thorpej  * XXX: The 3c509 card can get in a mode where both the fifo status bit
    666   1.1   thorpej  *	FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
    667   1.1   thorpej  *	We detect this situation and we reset the adapter.
    668   1.1   thorpej  *	It happens at times when there is a lot of broadcast traffic
    669   1.1   thorpej  *	on the cable (once in a blue moon).
    670   1.1   thorpej  */
    671   1.1   thorpej static int
    672   1.1   thorpej epstatus(sc)
    673   1.1   thorpej 	register struct ep_softc *sc;
    674   1.1   thorpej {
    675  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    676  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    677   1.7   thorpej 	u_int16_t fifost;
    678   1.1   thorpej 
    679   1.1   thorpej 	/*
    680   1.1   thorpej 	 * Check the FIFO status and act accordingly
    681   1.1   thorpej 	 */
    682   1.1   thorpej 	GO_WINDOW(4);
    683  1.11   thorpej 	fifost = bus_space_read_2(iot, ioh, EP_W4_FIFO_DIAG);
    684   1.1   thorpej 	GO_WINDOW(1);
    685   1.1   thorpej 
    686   1.1   thorpej 	if (fifost & FIFOS_RX_UNDERRUN) {
    687   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    688  1.10  christos 			printf("%s: RX underrun\n", sc->sc_dev.dv_xname);
    689   1.1   thorpej 		epreset(sc);
    690   1.1   thorpej 		return 0;
    691   1.1   thorpej 	}
    692   1.1   thorpej 
    693   1.1   thorpej 	if (fifost & FIFOS_RX_STATUS_OVERRUN) {
    694   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    695  1.10  christos 			printf("%s: RX Status overrun\n", sc->sc_dev.dv_xname);
    696   1.1   thorpej 		return 1;
    697   1.1   thorpej 	}
    698   1.1   thorpej 
    699   1.1   thorpej 	if (fifost & FIFOS_RX_OVERRUN) {
    700   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    701  1.10  christos 			printf("%s: RX overrun\n", sc->sc_dev.dv_xname);
    702   1.1   thorpej 		return 1;
    703   1.1   thorpej 	}
    704   1.1   thorpej 
    705   1.1   thorpej 	if (fifost & FIFOS_TX_OVERRUN) {
    706   1.1   thorpej 		if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    707  1.10  christos 			printf("%s: TX overrun\n", sc->sc_dev.dv_xname);
    708   1.1   thorpej 		epreset(sc);
    709   1.1   thorpej 		return 0;
    710   1.1   thorpej 	}
    711   1.1   thorpej 
    712   1.1   thorpej 	return 0;
    713   1.1   thorpej }
    714   1.1   thorpej 
    715   1.1   thorpej 
    716   1.1   thorpej static void
    717   1.1   thorpej eptxstat(sc)
    718   1.1   thorpej 	register struct ep_softc *sc;
    719   1.1   thorpej {
    720  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    721  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    722   1.1   thorpej 	int i;
    723   1.1   thorpej 
    724   1.1   thorpej 	/*
    725   1.1   thorpej 	 * We need to read+write TX_STATUS until we get a 0 status
    726   1.1   thorpej 	 * in order to turn off the interrupt flag.
    727   1.1   thorpej 	 */
    728  1.11   thorpej 	while ((i = bus_space_read_1(iot, ioh, EP_W1_TX_STATUS)) & TXS_COMPLETE) {
    729  1.11   thorpej 		bus_space_write_1(iot, ioh, EP_W1_TX_STATUS, 0x0);
    730   1.1   thorpej 
    731   1.1   thorpej 		if (i & TXS_JABBER) {
    732   1.1   thorpej 			++sc->sc_arpcom.ac_if.if_oerrors;
    733   1.1   thorpej 			if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    734  1.10  christos 				printf("%s: jabber (%x)\n",
    735   1.1   thorpej 				       sc->sc_dev.dv_xname, i);
    736   1.1   thorpej 			epreset(sc);
    737   1.1   thorpej 		} else if (i & TXS_UNDERRUN) {
    738   1.1   thorpej 			++sc->sc_arpcom.ac_if.if_oerrors;
    739   1.1   thorpej 			if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
    740  1.10  christos 				printf("%s: fifo underrun (%x) @%d\n",
    741   1.1   thorpej 				       sc->sc_dev.dv_xname, i,
    742   1.1   thorpej 				       sc->tx_start_thresh);
    743   1.1   thorpej 			if (sc->tx_succ_ok < 100)
    744   1.1   thorpej 				    sc->tx_start_thresh = min(ETHER_MAX_LEN,
    745   1.1   thorpej 					    sc->tx_start_thresh + 20);
    746   1.1   thorpej 			sc->tx_succ_ok = 0;
    747   1.1   thorpej 			epreset(sc);
    748   1.1   thorpej 		} else if (i & TXS_MAX_COLLISION) {
    749   1.1   thorpej 			++sc->sc_arpcom.ac_if.if_collisions;
    750  1.11   thorpej 			bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
    751   1.1   thorpej 			sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    752   1.1   thorpej 		} else
    753   1.1   thorpej 			sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127;
    754   1.1   thorpej 	}
    755   1.1   thorpej }
    756   1.1   thorpej 
    757   1.1   thorpej int
    758   1.1   thorpej epintr(arg)
    759   1.1   thorpej 	void *arg;
    760   1.1   thorpej {
    761   1.1   thorpej 	register struct ep_softc *sc = arg;
    762  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    763  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    764   1.1   thorpej 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    765   1.7   thorpej 	u_int16_t status;
    766   1.1   thorpej 	int ret = 0;
    767   1.1   thorpej 
    768   1.1   thorpej 	for (;;) {
    769  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
    770   1.1   thorpej 
    771  1.11   thorpej 		status = bus_space_read_2(iot, ioh, EP_STATUS);
    772   1.1   thorpej 
    773   1.1   thorpej 		if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
    774   1.1   thorpej 			       S_RX_COMPLETE | S_CARD_FAILURE)) == 0)
    775   1.1   thorpej 			break;
    776   1.1   thorpej 
    777   1.1   thorpej 		ret = 1;
    778   1.1   thorpej 
    779   1.1   thorpej 		/*
    780   1.1   thorpej 		 * Acknowledge any interrupts.  It's important that we do this
    781   1.1   thorpej 		 * first, since there would otherwise be a race condition.
    782   1.1   thorpej 		 * Due to the i386 interrupt queueing, we may get spurious
    783   1.1   thorpej 		 * interrupts occasionally.
    784   1.1   thorpej 		 */
    785  1.11   thorpej 		bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | status);
    786   1.1   thorpej 
    787   1.1   thorpej 		if (status & S_RX_COMPLETE)
    788   1.1   thorpej 			epread(sc);
    789   1.1   thorpej 		if (status & S_TX_AVAIL) {
    790   1.1   thorpej 			sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
    791   1.1   thorpej 			epstart(&sc->sc_arpcom.ac_if);
    792   1.1   thorpej 		}
    793   1.1   thorpej 		if (status & S_CARD_FAILURE) {
    794  1.10  christos 			printf("%s: adapter failure (%x)\n",
    795   1.9  christos 			    sc->sc_dev.dv_xname, status);
    796   1.1   thorpej 			epreset(sc);
    797   1.1   thorpej 			return (1);
    798   1.1   thorpej 		}
    799   1.1   thorpej 		if (status & S_TX_COMPLETE) {
    800   1.1   thorpej 			eptxstat(sc);
    801   1.1   thorpej 			epstart(ifp);
    802   1.1   thorpej 		}
    803   1.1   thorpej 	}
    804   1.1   thorpej 
    805   1.1   thorpej 	/* no more interrupts */
    806   1.1   thorpej 	return (ret);
    807   1.1   thorpej }
    808   1.1   thorpej 
    809   1.1   thorpej void
    810   1.1   thorpej epread(sc)
    811   1.1   thorpej 	register struct ep_softc *sc;
    812   1.1   thorpej {
    813  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    814  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    815   1.1   thorpej 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    816   1.1   thorpej 	struct mbuf *m;
    817   1.1   thorpej 	struct ether_header *eh;
    818   1.1   thorpej 	int len;
    819   1.1   thorpej 
    820  1.11   thorpej 	len = bus_space_read_2(iot, ioh, EP_W1_RX_STATUS);
    821   1.1   thorpej 
    822   1.1   thorpej again:
    823   1.1   thorpej 	if (ifp->if_flags & IFF_DEBUG) {
    824   1.1   thorpej 		int err = len & ERR_MASK;
    825   1.1   thorpej 		char *s = NULL;
    826   1.1   thorpej 
    827   1.1   thorpej 		if (len & ERR_INCOMPLETE)
    828   1.1   thorpej 			s = "incomplete packet";
    829   1.1   thorpej 		else if (err == ERR_OVERRUN)
    830   1.1   thorpej 			s = "packet overrun";
    831   1.1   thorpej 		else if (err == ERR_RUNT)
    832   1.1   thorpej 			s = "runt packet";
    833   1.1   thorpej 		else if (err == ERR_ALIGNMENT)
    834   1.1   thorpej 			s = "bad alignment";
    835   1.1   thorpej 		else if (err == ERR_CRC)
    836   1.1   thorpej 			s = "bad crc";
    837   1.1   thorpej 		else if (err == ERR_OVERSIZE)
    838   1.1   thorpej 			s = "oversized packet";
    839   1.1   thorpej 		else if (err == ERR_DRIBBLE)
    840   1.1   thorpej 			s = "dribble bits";
    841   1.1   thorpej 
    842   1.1   thorpej 		if (s)
    843  1.10  christos 			printf("%s: %s\n", sc->sc_dev.dv_xname, s);
    844   1.1   thorpej 	}
    845   1.1   thorpej 
    846   1.1   thorpej 	if (len & ERR_INCOMPLETE)
    847   1.1   thorpej 		return;
    848   1.1   thorpej 
    849   1.1   thorpej 	if (len & ERR_RX) {
    850   1.1   thorpej 		++ifp->if_ierrors;
    851   1.1   thorpej 		goto abort;
    852   1.1   thorpej 	}
    853   1.1   thorpej 
    854   1.1   thorpej 	len &= RX_BYTES_MASK;	/* Lower 11 bits = RX bytes. */
    855   1.1   thorpej 
    856   1.1   thorpej 	/* Pull packet off interface. */
    857   1.1   thorpej 	m = epget(sc, len);
    858   1.1   thorpej 	if (m == 0) {
    859   1.1   thorpej 		ifp->if_ierrors++;
    860   1.1   thorpej 		goto abort;
    861   1.1   thorpej 	}
    862   1.1   thorpej 
    863   1.1   thorpej 	++ifp->if_ipackets;
    864   1.1   thorpej 
    865   1.1   thorpej 	/* We assume the header fit entirely in one mbuf. */
    866   1.1   thorpej 	eh = mtod(m, struct ether_header *);
    867   1.1   thorpej 
    868   1.1   thorpej #if NBPFILTER > 0
    869   1.1   thorpej 	/*
    870   1.1   thorpej 	 * Check if there's a BPF listener on this interface.
    871   1.1   thorpej 	 * If so, hand off the raw packet to BPF.
    872   1.1   thorpej 	 */
    873   1.1   thorpej 	if (ifp->if_bpf) {
    874   1.1   thorpej 		bpf_mtap(ifp->if_bpf, m);
    875   1.1   thorpej 
    876   1.1   thorpej 		/*
    877   1.1   thorpej 		 * Note that the interface cannot be in promiscuous mode if
    878   1.1   thorpej 		 * there are no BPF listeners.  And if we are in promiscuous
    879   1.1   thorpej 		 * mode, we have to check if this packet is really ours.
    880   1.1   thorpej 		 */
    881   1.1   thorpej 		if ((ifp->if_flags & IFF_PROMISC) &&
    882   1.1   thorpej 		    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
    883   1.1   thorpej 		    bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
    884   1.1   thorpej 			    sizeof(eh->ether_dhost)) != 0) {
    885   1.1   thorpej 			m_freem(m);
    886   1.1   thorpej 			return;
    887   1.1   thorpej 		}
    888   1.1   thorpej 	}
    889   1.1   thorpej #endif
    890   1.1   thorpej 
    891   1.1   thorpej 	/* We assume the header fit entirely in one mbuf. */
    892   1.1   thorpej 	m_adj(m, sizeof(struct ether_header));
    893   1.1   thorpej 	ether_input(ifp, eh, m);
    894   1.1   thorpej 
    895   1.1   thorpej 	/*
    896   1.1   thorpej 	 * In periods of high traffic we can actually receive enough
    897   1.1   thorpej 	 * packets so that the fifo overrun bit will be set at this point,
    898   1.1   thorpej 	 * even though we just read a packet. In this case we
    899   1.1   thorpej 	 * are not going to receive any more interrupts. We check for
    900   1.1   thorpej 	 * this condition and read again until the fifo is not full.
    901   1.1   thorpej 	 * We could simplify this test by not using epstatus(), but
    902   1.1   thorpej 	 * rechecking the RX_STATUS register directly. This test could
    903   1.1   thorpej 	 * result in unnecessary looping in cases where there is a new
    904   1.1   thorpej 	 * packet but the fifo is not full, but it will not fix the
    905   1.1   thorpej 	 * stuck behavior.
    906   1.1   thorpej 	 *
    907   1.1   thorpej 	 * Even with this improvement, we still get packet overrun errors
    908   1.1   thorpej 	 * which are hurting performance. Maybe when I get some more time
    909   1.1   thorpej 	 * I'll modify epread() so that it can handle RX_EARLY interrupts.
    910   1.1   thorpej 	 */
    911   1.1   thorpej 	if (epstatus(sc)) {
    912  1.11   thorpej 		len = bus_space_read_2(iot, ioh, EP_W1_RX_STATUS);
    913   1.1   thorpej 		/* Check if we are stuck and reset [see XXX comment] */
    914   1.1   thorpej 		if (len & ERR_INCOMPLETE) {
    915   1.1   thorpej 			if (ifp->if_flags & IFF_DEBUG)
    916  1.10  christos 				printf("%s: adapter reset\n",
    917   1.9  christos 				    sc->sc_dev.dv_xname);
    918   1.1   thorpej 			epreset(sc);
    919   1.1   thorpej 			return;
    920   1.1   thorpej 		}
    921   1.1   thorpej 		goto again;
    922   1.1   thorpej 	}
    923   1.1   thorpej 
    924   1.1   thorpej 	return;
    925   1.1   thorpej 
    926   1.1   thorpej abort:
    927  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
    928  1.11   thorpej 	while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
    929   1.1   thorpej 		;
    930   1.1   thorpej }
    931   1.1   thorpej 
    932   1.1   thorpej struct mbuf *
    933   1.1   thorpej epget(sc, totlen)
    934   1.1   thorpej 	struct ep_softc *sc;
    935   1.1   thorpej 	int totlen;
    936   1.1   thorpej {
    937  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
    938  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
    939   1.1   thorpej 	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
    940   1.1   thorpej 	struct mbuf *top, **mp, *m;
    941  1.14       cjs 	int len, remaining;
    942   1.1   thorpej 	int sh;
    943   1.1   thorpej 
    944   1.1   thorpej 	m = sc->mb[sc->next_mb];
    945   1.1   thorpej 	sc->mb[sc->next_mb] = 0;
    946   1.1   thorpej 	if (m == 0) {
    947   1.1   thorpej 		MGETHDR(m, M_DONTWAIT, MT_DATA);
    948   1.1   thorpej 		if (m == 0)
    949   1.1   thorpej 			return 0;
    950   1.1   thorpej 	} else {
    951   1.1   thorpej 		/* If the queue is no longer full, refill. */
    952   1.1   thorpej 		if (sc->last_mb == sc->next_mb)
    953   1.1   thorpej 			timeout(epmbuffill, sc, 1);
    954   1.1   thorpej 		/* Convert one of our saved mbuf's. */
    955   1.1   thorpej 		sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
    956   1.1   thorpej 		m->m_data = m->m_pktdat;
    957   1.1   thorpej 		m->m_flags = M_PKTHDR;
    958   1.1   thorpej 	}
    959   1.1   thorpej 	m->m_pkthdr.rcvif = ifp;
    960   1.1   thorpej 	m->m_pkthdr.len = totlen;
    961   1.1   thorpej 	len = MHLEN;
    962   1.1   thorpej 	top = 0;
    963   1.1   thorpej 	mp = &top;
    964   1.1   thorpej 
    965   1.1   thorpej 	/*
    966   1.1   thorpej 	 * We read the packet at splhigh() so that an interrupt from another
    967   1.1   thorpej 	 * device doesn't cause the card's buffer to overflow while we're
    968   1.1   thorpej 	 * reading it.  We may still lose packets at other times.
    969   1.1   thorpej 	 */
    970   1.1   thorpej 	sh = splhigh();
    971   1.1   thorpej 
    972   1.1   thorpej 	while (totlen > 0) {
    973   1.1   thorpej 		if (top) {
    974   1.1   thorpej 			m = sc->mb[sc->next_mb];
    975   1.1   thorpej 			sc->mb[sc->next_mb] = 0;
    976   1.1   thorpej 			if (m == 0) {
    977   1.1   thorpej 				MGET(m, M_DONTWAIT, MT_DATA);
    978   1.1   thorpej 				if (m == 0) {
    979   1.1   thorpej 					splx(sh);
    980   1.1   thorpej 					m_freem(top);
    981   1.1   thorpej 					return 0;
    982   1.1   thorpej 				}
    983   1.1   thorpej 			} else {
    984   1.1   thorpej 				sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
    985   1.1   thorpej 			}
    986   1.1   thorpej 			len = MLEN;
    987   1.1   thorpej 		}
    988   1.1   thorpej 		if (totlen >= MINCLSIZE) {
    989   1.1   thorpej 			MCLGET(m, M_DONTWAIT);
    990   1.1   thorpej 			if (m->m_flags & M_EXT)
    991   1.1   thorpej 				len = MCLBYTES;
    992   1.1   thorpej 		}
    993  1.14       cjs 		if (EP_IS_BUS_32(sc->bustype) )  {
    994  1.14       cjs 			u_long pad;
    995  1.14       cjs 			if (top == 0)  {
    996  1.14       cjs 			    /* align the struct ip header */
    997  1.14       cjs 			    pad = ALIGN(sizeof(struct ether_header))
    998  1.14       cjs 				 - sizeof(struct ether_header);
    999  1.14       cjs 			} else {
   1000  1.14       cjs 			    /* XXX do we really need this? */
   1001  1.14       cjs 			    pad = ALIGN(m->m_data) - (u_long) m->m_data;
   1002  1.14       cjs 			}
   1003  1.14       cjs 			m->m_data += pad;
   1004  1.14       cjs 			len -= pad;
   1005  1.14       cjs 		}
   1006  1.14       cjs 		remaining = len = min(totlen, len);
   1007   1.1   thorpej 		if (EP_IS_BUS_32(sc->bustype)) {
   1008  1.14       cjs 			u_long offset = mtod(m, u_long);
   1009  1.14       cjs 			/*
   1010  1.14       cjs 			 * Read bytes up to the point where we are aligned.
   1011  1.14       cjs 			 * (We can align to 4 bytes, rather than ALIGNBYTES,
   1012  1.14       cjs 			 * here because we're later reading 4-byte chunks.)
   1013  1.14       cjs 			 */
   1014  1.14       cjs 			if ((remaining > 3) && (offset & 3))  {
   1015  1.14       cjs 				int count = (4 - (offset & 3));
   1016  1.14       cjs 				bus_space_read_multi_1(iot, ioh,
   1017  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1018  1.14       cjs 				    (u_int8_t *) offset, count);
   1019  1.14       cjs 				offset += count;
   1020  1.14       cjs 				remaining -= count;
   1021  1.14       cjs 			}
   1022  1.14       cjs 			if (remaining > 3) {
   1023  1.11   thorpej 				bus_space_read_multi_4(iot, ioh,
   1024  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1025  1.14       cjs 				    (u_int32_t *) offset, remaining >> 2);
   1026  1.14       cjs 				offset += remaining & ~3;
   1027  1.14       cjs 				remaining &= 3;
   1028  1.14       cjs 			}
   1029  1.14       cjs 			if (remaining)  {
   1030  1.11   thorpej 				bus_space_read_multi_1(iot, ioh,
   1031  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1032  1.14       cjs 				    (u_int8_t *) offset, remaining);
   1033  1.14       cjs 			}
   1034   1.1   thorpej 		} else {
   1035  1.14       cjs 			u_long offset = mtod(m, u_long);
   1036  1.14       cjs 			if ((remaining > 1) && (offset & 1))  {
   1037  1.14       cjs 				bus_space_read_multi_1(iot, ioh,
   1038  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1039  1.14       cjs 				    (u_int8_t *) offset, 1);
   1040  1.14       cjs 				remaining -= 1;
   1041  1.14       cjs 				offset += 1;
   1042  1.14       cjs 			}
   1043  1.14       cjs 			if (remaining > 1) {
   1044  1.11   thorpej 				bus_space_read_multi_2(iot, ioh,
   1045  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1046  1.14       cjs 				    (u_int16_t *) offset, remaining >> 1);
   1047  1.14       cjs 				offset += remaining & ~1;
   1048  1.14       cjs 			}
   1049  1.14       cjs 			if (remaining & 1)  {
   1050  1.14       cjs 				bus_space_read_multi_1(iot, ioh,
   1051  1.14       cjs 				    EP_W1_RX_PIO_RD_1,
   1052  1.14       cjs 				    (u_int8_t *) offset, remaining & 1);
   1053  1.14       cjs 			}
   1054   1.1   thorpej 		}
   1055   1.1   thorpej 		m->m_len = len;
   1056   1.1   thorpej 		totlen -= len;
   1057   1.1   thorpej 		*mp = m;
   1058   1.1   thorpej 		mp = &m->m_next;
   1059   1.1   thorpej 	}
   1060   1.1   thorpej 
   1061  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
   1062  1.11   thorpej 	while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
   1063   1.1   thorpej 		;
   1064   1.1   thorpej 
   1065   1.1   thorpej 	splx(sh);
   1066   1.1   thorpej 
   1067   1.1   thorpej 	return top;
   1068   1.1   thorpej }
   1069   1.1   thorpej 
   1070   1.1   thorpej int
   1071   1.1   thorpej epioctl(ifp, cmd, data)
   1072   1.1   thorpej 	register struct ifnet *ifp;
   1073   1.1   thorpej 	u_long cmd;
   1074   1.1   thorpej 	caddr_t data;
   1075   1.1   thorpej {
   1076   1.5   thorpej 	struct ep_softc *sc = ifp->if_softc;
   1077   1.1   thorpej 	struct ifaddr *ifa = (struct ifaddr *)data;
   1078   1.1   thorpej 	struct ifreq *ifr = (struct ifreq *)data;
   1079   1.1   thorpej 	int s, error = 0;
   1080   1.1   thorpej 
   1081   1.1   thorpej 	s = splnet();
   1082   1.1   thorpej 
   1083   1.1   thorpej 	switch (cmd) {
   1084   1.1   thorpej 
   1085   1.1   thorpej 	case SIOCSIFADDR:
   1086   1.1   thorpej 		ifp->if_flags |= IFF_UP;
   1087   1.1   thorpej 
   1088   1.1   thorpej 		switch (ifa->ifa_addr->sa_family) {
   1089   1.1   thorpej #ifdef INET
   1090   1.1   thorpej 		case AF_INET:
   1091   1.1   thorpej 			epinit(sc);
   1092   1.1   thorpej 			arp_ifinit(&sc->sc_arpcom, ifa);
   1093   1.1   thorpej 			break;
   1094   1.1   thorpej #endif
   1095   1.1   thorpej #ifdef NS
   1096   1.1   thorpej 		case AF_NS:
   1097   1.1   thorpej 		    {
   1098   1.1   thorpej 			register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
   1099   1.1   thorpej 
   1100   1.1   thorpej 			if (ns_nullhost(*ina))
   1101   1.1   thorpej 				ina->x_host =
   1102   1.1   thorpej 				    *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
   1103   1.1   thorpej 			else
   1104   1.1   thorpej 				bcopy(ina->x_host.c_host,
   1105   1.1   thorpej 				    sc->sc_arpcom.ac_enaddr,
   1106   1.1   thorpej 				    sizeof(sc->sc_arpcom.ac_enaddr));
   1107   1.1   thorpej 			/* Set new address. */
   1108   1.1   thorpej 			epinit(sc);
   1109   1.1   thorpej 			break;
   1110   1.1   thorpej 		    }
   1111   1.1   thorpej #endif
   1112   1.1   thorpej 		default:
   1113   1.1   thorpej 			epinit(sc);
   1114   1.1   thorpej 			break;
   1115   1.1   thorpej 		}
   1116   1.1   thorpej 		break;
   1117   1.1   thorpej 
   1118   1.1   thorpej 	case SIOCSIFFLAGS:
   1119   1.1   thorpej 		if ((ifp->if_flags & IFF_UP) == 0 &&
   1120   1.1   thorpej 		    (ifp->if_flags & IFF_RUNNING) != 0) {
   1121   1.1   thorpej 			/*
   1122   1.1   thorpej 			 * If interface is marked down and it is running, then
   1123   1.1   thorpej 			 * stop it.
   1124   1.1   thorpej 			 */
   1125   1.1   thorpej 			epstop(sc);
   1126   1.1   thorpej 			ifp->if_flags &= ~IFF_RUNNING;
   1127   1.1   thorpej 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
   1128   1.1   thorpej 			   (ifp->if_flags & IFF_RUNNING) == 0) {
   1129   1.1   thorpej 			/*
   1130   1.1   thorpej 			 * If interface is marked up and it is stopped, then
   1131   1.1   thorpej 			 * start it.
   1132   1.1   thorpej 			 */
   1133   1.1   thorpej 			epinit(sc);
   1134   1.1   thorpej 		} else {
   1135   1.1   thorpej 			/*
   1136   1.1   thorpej 			 * deal with flags changes:
   1137   1.1   thorpej 			 * IFF_MULTICAST, IFF_PROMISC,
   1138   1.1   thorpej 			 * IFF_LINK0, IFF_LINK1,
   1139   1.1   thorpej 			 */
   1140   1.1   thorpej 			epsetfilter(sc);
   1141   1.1   thorpej 			epsetlink(sc);
   1142   1.1   thorpej 		}
   1143   1.1   thorpej 		break;
   1144   1.1   thorpej 
   1145   1.1   thorpej 	case SIOCADDMULTI:
   1146   1.1   thorpej 	case SIOCDELMULTI:
   1147   1.1   thorpej 		error = (cmd == SIOCADDMULTI) ?
   1148   1.1   thorpej 		    ether_addmulti(ifr, &sc->sc_arpcom) :
   1149   1.1   thorpej 		    ether_delmulti(ifr, &sc->sc_arpcom);
   1150   1.1   thorpej 
   1151   1.1   thorpej 		if (error == ENETRESET) {
   1152   1.1   thorpej 			/*
   1153   1.1   thorpej 			 * Multicast list has changed; set the hardware filter
   1154   1.1   thorpej 			 * accordingly.
   1155   1.1   thorpej 			 */
   1156   1.1   thorpej 			epreset(sc);
   1157   1.1   thorpej 			error = 0;
   1158   1.1   thorpej 		}
   1159   1.1   thorpej 		break;
   1160   1.1   thorpej 
   1161   1.1   thorpej 	default:
   1162   1.1   thorpej 		error = EINVAL;
   1163   1.1   thorpej 		break;
   1164   1.1   thorpej 	}
   1165   1.1   thorpej 
   1166   1.1   thorpej 	splx(s);
   1167   1.1   thorpej 	return (error);
   1168   1.1   thorpej }
   1169   1.1   thorpej 
   1170   1.1   thorpej void
   1171   1.1   thorpej epreset(sc)
   1172   1.1   thorpej 	struct ep_softc *sc;
   1173   1.1   thorpej {
   1174   1.1   thorpej 	int s;
   1175   1.1   thorpej 
   1176   1.1   thorpej 	s = splnet();
   1177   1.1   thorpej 	epstop(sc);
   1178   1.1   thorpej 	epinit(sc);
   1179   1.1   thorpej 	splx(s);
   1180   1.1   thorpej }
   1181   1.1   thorpej 
   1182   1.1   thorpej void
   1183   1.5   thorpej epwatchdog(ifp)
   1184   1.5   thorpej 	struct ifnet *ifp;
   1185   1.1   thorpej {
   1186   1.5   thorpej 	struct ep_softc *sc = ifp->if_softc;
   1187   1.1   thorpej 
   1188   1.1   thorpej 	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
   1189   1.1   thorpej 	++sc->sc_arpcom.ac_if.if_oerrors;
   1190   1.1   thorpej 
   1191   1.1   thorpej 	epreset(sc);
   1192   1.1   thorpej }
   1193   1.1   thorpej 
   1194   1.1   thorpej void
   1195   1.1   thorpej epstop(sc)
   1196   1.1   thorpej 	register struct ep_softc *sc;
   1197   1.1   thorpej {
   1198  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
   1199  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
   1200   1.1   thorpej 
   1201  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
   1202  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
   1203  1.11   thorpej 	while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
   1204   1.1   thorpej 		;
   1205  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
   1206  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
   1207  1.18  jonathan 
   1208  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET);
   1209  1.18  jonathan 	DELAY(100000);	/* need at least 1 ms, but be generous. */
   1210  1.18  jonathan 
   1211  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET);
   1212  1.18  jonathan 	DELAY(100000);	/* need at least 1 ms, but be generous. */
   1213  1.18  jonathan 
   1214  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
   1215  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
   1216  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
   1217  1.11   thorpej 	bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
   1218   1.1   thorpej 
   1219   1.1   thorpej 	epmbufempty(sc);
   1220   1.1   thorpej }
   1221  1.16  jonathan 
   1222  1.16  jonathan 
   1223  1.16  jonathan /*
   1224  1.16  jonathan  * Before reboots, reset card completely.
   1225  1.16  jonathan  */
   1226  1.16  jonathan static void
   1227  1.16  jonathan epshutdown(arg)
   1228  1.16  jonathan 	void *arg;
   1229  1.16  jonathan {
   1230  1.16  jonathan 	register struct ep_softc *sc = arg;
   1231  1.16  jonathan 	bus_space_tag_t iot = sc->sc_iot;
   1232  1.16  jonathan 	bus_space_handle_t ioh = sc->sc_ioh;
   1233  1.16  jonathan 
   1234  1.16  jonathan 	epstop(sc);
   1235  1.16  jonathan 	bus_space_write_2(iot, ioh, EP_COMMAND, GLOBAL_RESET);
   1236  1.16  jonathan 	/*
   1237  1.16  jonathan 	 * should loop waiting for CMD_COMPLETE but some earlier cards
   1238  1.16  jonathan 	 * may not support that properly.
   1239  1.16  jonathan 	 */
   1240  1.16  jonathan 	DELAY(20000);	/* need at least 1 ms, but be generous. */
   1241  1.16  jonathan }
   1242  1.16  jonathan 
   1243   1.1   thorpej 
   1244   1.1   thorpej /*
   1245   1.1   thorpej  * We get eeprom data from the id_port given an offset into the
   1246   1.1   thorpej  * eeprom.  Basically; after the ID_sequence is sent to all of
   1247   1.1   thorpej  * the cards; they enter the ID_CMD state where they will accept
   1248   1.1   thorpej  * command requests. 0x80-0xbf loads the eeprom data.  We then
   1249   1.1   thorpej  * read the port 16 times and with every read; the cards check
   1250   1.1   thorpej  * for contention (ie: if one card writes a 0 bit and another
   1251   1.1   thorpej  * writes a 1 bit then the host sees a 0. At the end of the cycle;
   1252   1.1   thorpej  * each card compares the data on the bus; if there is a difference
   1253   1.1   thorpej  * then that card goes into ID_WAIT state again). In the meantime;
   1254   1.1   thorpej  * one bit of data is returned in the AX register which is conveniently
   1255  1.11   thorpej  * returned to us by bus_space_read_1().  Hence; we read 16 times getting one
   1256   1.1   thorpej  * bit of data with each read.
   1257   1.2   thorpej  *
   1258   1.2   thorpej  * NOTE: the caller must provide an i/o handle for ELINK_ID_PORT!
   1259   1.1   thorpej  */
   1260   1.2   thorpej u_int16_t
   1261  1.11   thorpej epreadeeprom(iot, ioh, offset)
   1262  1.11   thorpej 	bus_space_tag_t iot;
   1263  1.11   thorpej 	bus_space_handle_t ioh;
   1264   1.2   thorpej 	int offset;
   1265   1.1   thorpej {
   1266   1.2   thorpej 	u_int16_t data = 0;
   1267   1.2   thorpej 	int i;
   1268   1.1   thorpej 
   1269  1.11   thorpej 	bus_space_write_1(iot, ioh, 0, 0x80 + offset);
   1270   1.1   thorpej 	delay(1000);
   1271   1.1   thorpej 	for (i = 0; i < 16; i++)
   1272  1.11   thorpej 		data = (data << 1) | (bus_space_read_2(iot, ioh, 0) & 1);
   1273   1.1   thorpej 	return (data);
   1274   1.1   thorpej }
   1275   1.1   thorpej 
   1276   1.1   thorpej static int
   1277   1.1   thorpej epbusyeeprom(sc)
   1278   1.1   thorpej 	struct ep_softc *sc;
   1279   1.1   thorpej {
   1280  1.11   thorpej 	bus_space_tag_t iot = sc->sc_iot;
   1281  1.11   thorpej 	bus_space_handle_t ioh = sc->sc_ioh;
   1282   1.1   thorpej 	int i = 100, j;
   1283   1.1   thorpej 
   1284   1.1   thorpej 	if (sc->bustype == EP_BUS_PCMCIA) {
   1285   1.1   thorpej 		delay(1000);
   1286   1.1   thorpej 		return 0;
   1287   1.1   thorpej 	}
   1288   1.1   thorpej 
   1289   1.1   thorpej 	while (i--) {
   1290  1.11   thorpej 		j = bus_space_read_2(iot, ioh, EP_W0_EEPROM_COMMAND);
   1291   1.1   thorpej 		if (j & EEPROM_BUSY)
   1292   1.1   thorpej 			delay(100);
   1293   1.1   thorpej 		else
   1294   1.1   thorpej 			break;
   1295   1.1   thorpej 	}
   1296   1.1   thorpej 	if (!i) {
   1297  1.10  christos 		printf("\n%s: eeprom failed to come ready\n",
   1298   1.1   thorpej 		    sc->sc_dev.dv_xname);
   1299   1.1   thorpej 		return (1);
   1300   1.1   thorpej 	}
   1301   1.1   thorpej 	if (j & EEPROM_TST_MODE) {
   1302  1.10  christos 		printf("\n%s: erase pencil mark, or disable plug-n-play mode!\n",
   1303   1.1   thorpej 		    sc->sc_dev.dv_xname);
   1304   1.1   thorpej 		return (1);
   1305   1.1   thorpej 	}
   1306   1.1   thorpej 	return (0);
   1307   1.1   thorpej }
   1308   1.1   thorpej 
   1309   1.1   thorpej void
   1310   1.3  christos epmbuffill(v)
   1311   1.3  christos 	void *v;
   1312   1.1   thorpej {
   1313   1.3  christos 	struct ep_softc *sc = v;
   1314   1.1   thorpej 	int s, i;
   1315   1.1   thorpej 
   1316   1.1   thorpej 	s = splnet();
   1317   1.1   thorpej 	i = sc->last_mb;
   1318   1.1   thorpej 	do {
   1319   1.1   thorpej 		if (sc->mb[i] == NULL)
   1320   1.1   thorpej 			MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
   1321   1.1   thorpej 		if (sc->mb[i] == NULL)
   1322   1.1   thorpej 			break;
   1323   1.1   thorpej 		i = (i + 1) % MAX_MBS;
   1324   1.1   thorpej 	} while (i != sc->next_mb);
   1325   1.1   thorpej 	sc->last_mb = i;
   1326   1.1   thorpej 	/* If the queue was not filled, try again. */
   1327   1.1   thorpej 	if (sc->last_mb != sc->next_mb)
   1328   1.1   thorpej 		timeout(epmbuffill, sc, 1);
   1329   1.1   thorpej 	splx(s);
   1330   1.1   thorpej }
   1331   1.1   thorpej 
   1332   1.1   thorpej void
   1333   1.1   thorpej epmbufempty(sc)
   1334   1.1   thorpej 	struct ep_softc *sc;
   1335   1.1   thorpej {
   1336   1.1   thorpej 	int s, i;
   1337   1.1   thorpej 
   1338   1.1   thorpej 	s = splnet();
   1339   1.1   thorpej 	for (i = 0; i<MAX_MBS; i++) {
   1340   1.1   thorpej 		if (sc->mb[i]) {
   1341   1.1   thorpej 			m_freem(sc->mb[i]);
   1342   1.1   thorpej 			sc->mb[i] = NULL;
   1343   1.1   thorpej 		}
   1344   1.1   thorpej 	}
   1345   1.1   thorpej 	sc->last_mb = sc->next_mb = 0;
   1346   1.1   thorpej 	untimeout(epmbuffill, sc);
   1347   1.1   thorpej 	splx(s);
   1348   1.1   thorpej }
   1349