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