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