Home | History | Annotate | Line # | Download | only in ic
smc83c170.c revision 1.1
      1  1.1  thorpej /*	$NetBSD: smc83c170.c,v 1.1 1998/06/02 01:29:42 thorpej Exp $	*/
      2  1.1  thorpej 
      3  1.1  thorpej /*-
      4  1.1  thorpej  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  1.1  thorpej  * All rights reserved.
      6  1.1  thorpej  *
      7  1.1  thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  thorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  1.1  thorpej  * NASA Ames Research Center.
     10  1.1  thorpej  *
     11  1.1  thorpej  * Redistribution and use in source and binary forms, with or without
     12  1.1  thorpej  * modification, are permitted provided that the following conditions
     13  1.1  thorpej  * are met:
     14  1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     15  1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     16  1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     18  1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     19  1.1  thorpej  * 3. All advertising materials mentioning features or use of this software
     20  1.1  thorpej  *    must display the following acknowledgement:
     21  1.1  thorpej  *	This product includes software developed by the NetBSD
     22  1.1  thorpej  *	Foundation, Inc. and its contributors.
     23  1.1  thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  1.1  thorpej  *    contributors may be used to endorse or promote products derived
     25  1.1  thorpej  *    from this software without specific prior written permission.
     26  1.1  thorpej  *
     27  1.1  thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  1.1  thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  1.1  thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  1.1  thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  1.1  thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  1.1  thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  1.1  thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  1.1  thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  1.1  thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  1.1  thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  1.1  thorpej  * POSSIBILITY OF SUCH DAMAGE.
     38  1.1  thorpej  */
     39  1.1  thorpej 
     40  1.1  thorpej /*
     41  1.1  thorpej  * Device driver for the Standard Microsystems Corp. 83C170
     42  1.1  thorpej  * Ethernet PCI Integrated Controller (EPIC/100).
     43  1.1  thorpej  */
     44  1.1  thorpej 
     45  1.1  thorpej #include "bpfilter.h"
     46  1.1  thorpej 
     47  1.1  thorpej #include <sys/param.h>
     48  1.1  thorpej #include <sys/systm.h>
     49  1.1  thorpej #include <sys/mbuf.h>
     50  1.1  thorpej #include <sys/malloc.h>
     51  1.1  thorpej #include <sys/kernel.h>
     52  1.1  thorpej #include <sys/socket.h>
     53  1.1  thorpej #include <sys/ioctl.h>
     54  1.1  thorpej #include <sys/errno.h>
     55  1.1  thorpej #include <sys/device.h>
     56  1.1  thorpej 
     57  1.1  thorpej #include <net/if.h>
     58  1.1  thorpej #include <net/if_dl.h>
     59  1.1  thorpej #include <net/if_media.h>
     60  1.1  thorpej #include <net/if_ether.h>
     61  1.1  thorpej 
     62  1.1  thorpej #if NBPFILTER > 0
     63  1.1  thorpej #include <net/bpf.h>
     64  1.1  thorpej #endif
     65  1.1  thorpej 
     66  1.1  thorpej #ifdef INET
     67  1.1  thorpej #include <netinet/in.h>
     68  1.1  thorpej #include <netinet/if_inarp.h>
     69  1.1  thorpej #endif
     70  1.1  thorpej 
     71  1.1  thorpej #ifdef NS
     72  1.1  thorpej #include <netns/ns.h>
     73  1.1  thorpej #include <netns/ns_if.h>
     74  1.1  thorpej #endif
     75  1.1  thorpej 
     76  1.1  thorpej #include <machine/bus.h>
     77  1.1  thorpej #include <machine/intr.h>
     78  1.1  thorpej 
     79  1.1  thorpej #include <dev/ic/smc83c170reg.h>
     80  1.1  thorpej #include <dev/ic/smc83c170var.h>
     81  1.1  thorpej 
     82  1.1  thorpej void	epic_start __P((struct ifnet *));
     83  1.1  thorpej void	epic_watchdog __P((struct ifnet *));
     84  1.1  thorpej int	epic_ioctl __P((struct ifnet *, u_long, caddr_t));
     85  1.1  thorpej 
     86  1.1  thorpej void	epic_shutdown __P((void *));
     87  1.1  thorpej 
     88  1.1  thorpej void	epic_reset __P((struct epic_softc *));
     89  1.1  thorpej void	epic_init __P((struct epic_softc *));
     90  1.1  thorpej void	epic_stop __P((struct epic_softc *));
     91  1.1  thorpej int	epic_add_rxbuf __P((struct epic_softc *, int));
     92  1.1  thorpej void	epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
     93  1.1  thorpej void	epic_set_mchash __P((struct epic_softc *));
     94  1.1  thorpej 
     95  1.1  thorpej /*
     96  1.1  thorpej  * Fudge the incoming packets by this much, to ensure the data after
     97  1.1  thorpej  * the Ethernet header is aligned.
     98  1.1  thorpej  */
     99  1.1  thorpej #define	RX_ALIGNMENT_FUDGE	2
    100  1.1  thorpej 
    101  1.1  thorpej /* XXX Should be somewhere else. */
    102  1.1  thorpej #define	ETHER_MIN_LEN		60
    103  1.1  thorpej 
    104  1.1  thorpej #define	INTMASK	(INTSTAT_FATAL_INT | INTSTAT_TXU | \
    105  1.1  thorpej 	    INTSTAT_TXC | INTSTAT_RQE | INTSTAT_RCC)
    106  1.1  thorpej 
    107  1.1  thorpej /*
    108  1.1  thorpej  * Attach an EPIC interface to the system.
    109  1.1  thorpej  */
    110  1.1  thorpej void
    111  1.1  thorpej epic_attach(sc)
    112  1.1  thorpej 	struct epic_softc *sc;
    113  1.1  thorpej {
    114  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
    115  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
    116  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    117  1.1  thorpej 	int i, rseg, error, attach_stage;
    118  1.1  thorpej 	bus_dma_segment_t seg;
    119  1.1  thorpej 	u_int8_t enaddr[ETHER_ADDR_LEN], devname[12 + 1];
    120  1.1  thorpej 	u_int16_t myea[ETHER_ADDR_LEN / 2], mydevname[6];
    121  1.1  thorpej 
    122  1.1  thorpej 	attach_stage = 0;
    123  1.1  thorpej 
    124  1.1  thorpej 	/*
    125  1.1  thorpej 	 * Allocate the control data structures, and create and load the
    126  1.1  thorpej 	 * DMA map for it.
    127  1.1  thorpej 	 */
    128  1.1  thorpej 	if ((error = bus_dmamem_alloc(sc->sc_dmat,
    129  1.1  thorpej 	    sizeof(struct epic_control_data), NBPG, 0, &seg, 1, &rseg,
    130  1.1  thorpej 	    BUS_DMA_NOWAIT)) != 0) {
    131  1.1  thorpej 		printf("%s: unable to allocate control data, error = %d\n",
    132  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    133  1.1  thorpej 		goto fail;
    134  1.1  thorpej 	}
    135  1.1  thorpej 
    136  1.1  thorpej 	attach_stage = 1;
    137  1.1  thorpej 
    138  1.1  thorpej 	if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
    139  1.1  thorpej 	    sizeof(struct epic_control_data), (caddr_t *)&sc->sc_control_data,
    140  1.1  thorpej 	    BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
    141  1.1  thorpej 		printf("%s: unable to map control data, error = %d\n",
    142  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    143  1.1  thorpej 		goto fail;
    144  1.1  thorpej 	}
    145  1.1  thorpej 
    146  1.1  thorpej 	attach_stage = 2;
    147  1.1  thorpej 
    148  1.1  thorpej 	if ((error = bus_dmamap_create(sc->sc_dmat,
    149  1.1  thorpej 	    sizeof(struct epic_control_data), 1,
    150  1.1  thorpej 	    sizeof(struct epic_control_data), 0, BUS_DMA_NOWAIT,
    151  1.1  thorpej 	    &sc->sc_cddmamap)) != 0) {
    152  1.1  thorpej 		printf("%s: unable to create control data DMA map, "
    153  1.1  thorpej 		    "error = %d\n", sc->sc_dev.dv_xname, error);
    154  1.1  thorpej 		goto fail;
    155  1.1  thorpej 	}
    156  1.1  thorpej 
    157  1.1  thorpej 	attach_stage = 3;
    158  1.1  thorpej 
    159  1.1  thorpej 	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
    160  1.1  thorpej 	    sc->sc_control_data, sizeof(struct epic_control_data), NULL,
    161  1.1  thorpej 	    BUS_DMA_NOWAIT)) != 0) {
    162  1.1  thorpej 		printf("%s: unable to load control data DMA map, error = %d\n",
    163  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    164  1.1  thorpej 		goto fail;
    165  1.1  thorpej 	}
    166  1.1  thorpej 
    167  1.1  thorpej 	attach_stage = 4;
    168  1.1  thorpej 
    169  1.1  thorpej 	/*
    170  1.1  thorpej 	 * Create the transmit buffer DMA maps.
    171  1.1  thorpej 	 */
    172  1.1  thorpej 	for (i = 0; i < EPIC_NTXDESC; i++) {
    173  1.1  thorpej 		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
    174  1.1  thorpej 		    EPIC_NFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
    175  1.1  thorpej 		    &sc->sc_txsoft[i].ds_dmamap)) != 0) {
    176  1.1  thorpej 			printf("%s: unable to create tx DMA map %d, "
    177  1.1  thorpej 			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
    178  1.1  thorpej 			goto fail;
    179  1.1  thorpej 		}
    180  1.1  thorpej 	}
    181  1.1  thorpej 
    182  1.1  thorpej 	attach_stage = 5;
    183  1.1  thorpej 
    184  1.1  thorpej 	/*
    185  1.1  thorpej 	 * Create the recieve buffer DMA maps.
    186  1.1  thorpej 	 */
    187  1.1  thorpej 	for (i = 0; i < EPIC_NRXDESC; i++) {
    188  1.1  thorpej 		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
    189  1.1  thorpej 		    MCLBYTES, 0, BUS_DMA_NOWAIT,
    190  1.1  thorpej 		    &sc->sc_rxsoft[i].ds_dmamap)) != 0) {
    191  1.1  thorpej 			printf("%s: unable to create rx DMA map %d, "
    192  1.1  thorpej 			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
    193  1.1  thorpej 			goto fail;
    194  1.1  thorpej 		}
    195  1.1  thorpej 	}
    196  1.1  thorpej 
    197  1.1  thorpej 	attach_stage = 6;
    198  1.1  thorpej 
    199  1.1  thorpej 	/*
    200  1.1  thorpej 	 * Pre-allocate the receive buffers.
    201  1.1  thorpej 	 */
    202  1.1  thorpej 	for (i = 0; i < EPIC_NRXDESC; i++) {
    203  1.1  thorpej 		if ((error = epic_add_rxbuf(sc, i)) != 0) {
    204  1.1  thorpej 			printf("%s: unable to allocate or map rx buffer %d\n,"
    205  1.1  thorpej 			    " error = %d\n", sc->sc_dev.dv_xname, i, error);
    206  1.1  thorpej 			goto fail;
    207  1.1  thorpej 		}
    208  1.1  thorpej 	}
    209  1.1  thorpej 
    210  1.1  thorpej 	attach_stage = 7;
    211  1.1  thorpej 
    212  1.1  thorpej 	/*
    213  1.1  thorpej 	 * Bring the chip out of low-power mode and reset it to a known state.
    214  1.1  thorpej 	 */
    215  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_GENCTL, 0);
    216  1.1  thorpej 	epic_reset(sc);
    217  1.1  thorpej 
    218  1.1  thorpej 	/*
    219  1.1  thorpej 	 * Read the Ethernet address from the EEPROM.
    220  1.1  thorpej 	 */
    221  1.1  thorpej 	epic_read_eeprom(sc, 0, (sizeof(myea) / sizeof(myea[0])), myea);
    222  1.1  thorpej 	bcopy(myea, enaddr, sizeof(myea));
    223  1.1  thorpej 
    224  1.1  thorpej 	/*
    225  1.1  thorpej 	 * ...and the device name.
    226  1.1  thorpej 	 */
    227  1.1  thorpej 	epic_read_eeprom(sc, 0x2c, (sizeof(mydevname) / sizeof(mydevname[0])),
    228  1.1  thorpej 	    mydevname);
    229  1.1  thorpej 	bcopy(mydevname, devname, sizeof(mydevname));
    230  1.1  thorpej 	devname[sizeof(mydevname)] = '\0';
    231  1.1  thorpej 	for (i = sizeof(mydevname) - 1; i >= 0; i--) {
    232  1.1  thorpej 		if (devname[i] == ' ')
    233  1.1  thorpej 			devname[i] = '\0';
    234  1.1  thorpej 		else
    235  1.1  thorpej 			break;
    236  1.1  thorpej 	}
    237  1.1  thorpej 
    238  1.1  thorpej 	printf("%s: %s, Ethernet address %s\n", sc->sc_dev.dv_xname,
    239  1.1  thorpej 	    devname, ether_sprintf(enaddr));
    240  1.1  thorpej 
    241  1.1  thorpej 	ifp = &sc->sc_ethercom.ec_if;
    242  1.1  thorpej 	strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
    243  1.1  thorpej 	ifp->if_softc = sc;
    244  1.1  thorpej 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    245  1.1  thorpej 	ifp->if_ioctl = epic_ioctl;
    246  1.1  thorpej 	ifp->if_start = epic_start;
    247  1.1  thorpej 	ifp->if_watchdog = epic_watchdog;
    248  1.1  thorpej 
    249  1.1  thorpej 	/*
    250  1.1  thorpej 	 * Attach the interface.
    251  1.1  thorpej 	 */
    252  1.1  thorpej 	if_attach(ifp);
    253  1.1  thorpej 	ether_ifattach(ifp, enaddr);
    254  1.1  thorpej #if NBPFILTER > 0
    255  1.1  thorpej 	bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
    256  1.1  thorpej 	    sizeof(struct ether_header));
    257  1.1  thorpej #endif
    258  1.1  thorpej 
    259  1.1  thorpej 	/*
    260  1.1  thorpej 	 * Make sure the interface is shutdown during reboot.
    261  1.1  thorpej 	 */
    262  1.1  thorpej 	sc->sc_sdhook = shutdownhook_establish(epic_shutdown, sc);
    263  1.1  thorpej 	if (sc->sc_sdhook == NULL)
    264  1.1  thorpej 		printf("%s: WARNING: unable to establish shutdown hook\n",
    265  1.1  thorpej 		    sc->sc_dev.dv_xname);
    266  1.1  thorpej 	return;
    267  1.1  thorpej 
    268  1.1  thorpej  fail:
    269  1.1  thorpej 	/*
    270  1.1  thorpej 	 * Free any resources we've allocated during the failed attach
    271  1.1  thorpej 	 * attempt.  Do this in reverse order and fall through.
    272  1.1  thorpej 	 */
    273  1.1  thorpej 	switch (attach_stage) {
    274  1.1  thorpej 	case 7:
    275  1.1  thorpej 		for (i = 0; i < EPIC_NRXDESC; i++) {
    276  1.1  thorpej 			if (sc->sc_rxsoft[i].ds_mbuf != NULL) {
    277  1.1  thorpej 				bus_dmamap_unload(sc->sc_dmat,
    278  1.1  thorpej 				    sc->sc_rxsoft[i].ds_dmamap);
    279  1.1  thorpej 				m_freem(sc->sc_rxsoft[i].ds_mbuf);
    280  1.1  thorpej 			}
    281  1.1  thorpej 		}
    282  1.1  thorpej 		/* FALLTHROUGH */
    283  1.1  thorpej 
    284  1.1  thorpej 	case 6:
    285  1.1  thorpej 		for (i = 0; i < EPIC_NRXDESC; i++)
    286  1.1  thorpej 			bus_dmamap_destroy(sc->sc_dmat,
    287  1.1  thorpej 			    sc->sc_rxsoft[i].ds_dmamap);
    288  1.1  thorpej 		/* FALLTHROUGH */
    289  1.1  thorpej 
    290  1.1  thorpej 	case 5:
    291  1.1  thorpej 		for (i = 0; i < EPIC_NTXDESC; i++)
    292  1.1  thorpej 			bus_dmamap_destroy(sc->sc_dmat,
    293  1.1  thorpej 			    sc->sc_txsoft[i].ds_dmamap);
    294  1.1  thorpej 		/* FALLTHROUGH */
    295  1.1  thorpej 
    296  1.1  thorpej 	case 4:
    297  1.1  thorpej 		bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
    298  1.1  thorpej 		/* FALLTHROUGH */
    299  1.1  thorpej 
    300  1.1  thorpej 	case 3:
    301  1.1  thorpej 		bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
    302  1.1  thorpej 		/* FALLTHROUGH */
    303  1.1  thorpej 
    304  1.1  thorpej 	case 2:
    305  1.1  thorpej 		bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
    306  1.1  thorpej 		    sizeof(struct epic_control_data));
    307  1.1  thorpej 		/* FALLTHROUGH */
    308  1.1  thorpej 
    309  1.1  thorpej 	case 1:
    310  1.1  thorpej 		bus_dmamem_free(sc->sc_dmat, &seg, rseg);
    311  1.1  thorpej 		break;
    312  1.1  thorpej 	}
    313  1.1  thorpej }
    314  1.1  thorpej 
    315  1.1  thorpej /*
    316  1.1  thorpej  * Shutdown hook.  Make sure the interface is stopped at reboot.
    317  1.1  thorpej  */
    318  1.1  thorpej void
    319  1.1  thorpej epic_shutdown(arg)
    320  1.1  thorpej 	void *arg;
    321  1.1  thorpej {
    322  1.1  thorpej 	struct epic_softc *sc = arg;
    323  1.1  thorpej 
    324  1.1  thorpej 	epic_stop(sc);
    325  1.1  thorpej }
    326  1.1  thorpej 
    327  1.1  thorpej /*
    328  1.1  thorpej  * Start packet transmission on the interface.
    329  1.1  thorpej  * [ifnet interface function]
    330  1.1  thorpej  */
    331  1.1  thorpej void
    332  1.1  thorpej epic_start(ifp)
    333  1.1  thorpej 	struct ifnet *ifp;
    334  1.1  thorpej {
    335  1.1  thorpej 	struct epic_softc *sc = ifp->if_softc;
    336  1.1  thorpej 	struct epic_txdesc *txd;
    337  1.1  thorpej 	struct epic_descsoft *ds;
    338  1.1  thorpej 	struct epic_fraglist *fr;
    339  1.1  thorpej 	bus_dmamap_t dmamap;
    340  1.1  thorpej 	struct mbuf *m0;
    341  1.1  thorpej 	int nexttx, seg, error, txqueued;
    342  1.1  thorpej 
    343  1.1  thorpej 	txqueued = 0;
    344  1.1  thorpej 
    345  1.1  thorpej 	/*
    346  1.1  thorpej 	 * Loop through the send queue, setting up transmit descriptors
    347  1.1  thorpej 	 * until we drain the queue, or use up all available transmit
    348  1.1  thorpej 	 * descriptors.
    349  1.1  thorpej 	 */
    350  1.1  thorpej 	while (ifp->if_snd.ifq_head != NULL &&
    351  1.1  thorpej 	    sc->sc_txpending < EPIC_NTXDESC) {
    352  1.1  thorpej 		/*
    353  1.1  thorpej 		 * Grab a packet off the queue.
    354  1.1  thorpej 		 */
    355  1.1  thorpej 		IF_DEQUEUE(&ifp->if_snd, m0);
    356  1.1  thorpej 
    357  1.1  thorpej 		/*
    358  1.1  thorpej 		 * Get the last and next available transmit descriptor.
    359  1.1  thorpej 		 */
    360  1.1  thorpej 		nexttx = EPIC_NEXTTX(sc->sc_txlast);
    361  1.1  thorpej 		txd = &sc->sc_control_data->ecd_txdescs[nexttx];
    362  1.1  thorpej 		fr = &sc->sc_control_data->ecd_txfrags[nexttx];
    363  1.1  thorpej 		ds = &sc->sc_txsoft[nexttx];
    364  1.1  thorpej 		dmamap = ds->ds_dmamap;
    365  1.1  thorpej 
    366  1.1  thorpej  loadmap:
    367  1.1  thorpej 		/*
    368  1.1  thorpej 		 * Load the DMA map with the packet.
    369  1.1  thorpej 		 */
    370  1.1  thorpej 		error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
    371  1.1  thorpej 		    BUS_DMA_NOWAIT);
    372  1.1  thorpej 		switch (error) {
    373  1.1  thorpej 		case 0:
    374  1.1  thorpej 			/* Success. */
    375  1.1  thorpej 			break;
    376  1.1  thorpej 
    377  1.1  thorpej 		case EFBIG:
    378  1.1  thorpej 		    {
    379  1.1  thorpej 			struct mbuf *mn;
    380  1.1  thorpej 
    381  1.1  thorpej 			/*
    382  1.1  thorpej 			 * We ran out of segments.  We have to recopy this
    383  1.1  thorpej 			 * mbuf chain first.  Bail out if we can't get the
    384  1.1  thorpej 			 * new buffers.
    385  1.1  thorpej 			 */
    386  1.1  thorpej 			printf("%s: too many segments, ", sc->sc_dev.dv_xname);
    387  1.1  thorpej 
    388  1.1  thorpej 			MGETHDR(mn, M_DONTWAIT, MT_DATA);
    389  1.1  thorpej 			if (mn == NULL) {
    390  1.1  thorpej 				m_freem(m0);
    391  1.1  thorpej 				printf("aborting\n");
    392  1.1  thorpej 				goto out;
    393  1.1  thorpej 			}
    394  1.1  thorpej 			if (m0->m_pkthdr.len > MHLEN) {
    395  1.1  thorpej 				MCLGET(mn, M_DONTWAIT);
    396  1.1  thorpej 				if ((mn->m_flags & M_EXT) == 0) {
    397  1.1  thorpej 					m_freem(mn);
    398  1.1  thorpej 					m_freem(m0);
    399  1.1  thorpej 					printf("aborting\n");
    400  1.1  thorpej 					goto out;
    401  1.1  thorpej 				}
    402  1.1  thorpej 			}
    403  1.1  thorpej 			m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mn, caddr_t));
    404  1.1  thorpej 			mn->m_pkthdr.len = mn->m_len = m0->m_pkthdr.len;
    405  1.1  thorpej 			m_freem(m0);
    406  1.1  thorpej 			m0 = mn;
    407  1.1  thorpej 			printf("retrying\n");
    408  1.1  thorpej 			goto loadmap;
    409  1.1  thorpej 		    }
    410  1.1  thorpej 
    411  1.1  thorpej 		default:
    412  1.1  thorpej 			/*
    413  1.1  thorpej 			 * Some other problem; report it.
    414  1.1  thorpej 			 */
    415  1.1  thorpej 			printf("%s: can't load mbuf chain, error = %d\n",
    416  1.1  thorpej 			    sc->sc_dev.dv_xname, error);
    417  1.1  thorpej 			m_freem(m0);
    418  1.1  thorpej 			goto out;
    419  1.1  thorpej 		}
    420  1.1  thorpej 
    421  1.1  thorpej 		/*
    422  1.1  thorpej 		 * Initialize the fraglist.
    423  1.1  thorpej 		 */
    424  1.1  thorpej 		fr->ef_nfrags = dmamap->dm_nsegs;
    425  1.1  thorpej 		for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
    426  1.1  thorpej 			fr->ef_frags[seg].ef_addr =
    427  1.1  thorpej 			    dmamap->dm_segs[seg].ds_addr;
    428  1.1  thorpej 			fr->ef_frags[seg].ef_length =
    429  1.1  thorpej 			    dmamap->dm_segs[seg].ds_len;
    430  1.1  thorpej 		}
    431  1.1  thorpej 
    432  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
    433  1.1  thorpej 		    BUS_DMASYNC_PREWRITE);
    434  1.1  thorpej 
    435  1.1  thorpej 		/*
    436  1.1  thorpej 		 * Store a pointer to the packet so we can free it later.
    437  1.1  thorpej 		 */
    438  1.1  thorpej 		ds->ds_mbuf = m0;
    439  1.1  thorpej 
    440  1.1  thorpej 		/*
    441  1.1  thorpej 		 * Finish setting up the new transmit descriptor: set the
    442  1.1  thorpej 		 * packet length and give it to the EPIC.
    443  1.1  thorpej 		 */
    444  1.1  thorpej 		txd->et_txlength = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
    445  1.1  thorpej 		txd->et_txstatus = ET_TXSTAT_OWNER;
    446  1.1  thorpej 
    447  1.1  thorpej 		/*
    448  1.1  thorpej 		 * Committed; advance the lasttx pointer.  If nothing was
    449  1.1  thorpej 		 * previously queued, reset the dirty pointer.
    450  1.1  thorpej 		 */
    451  1.1  thorpej 		sc->sc_txlast = nexttx;
    452  1.1  thorpej 		if (sc->sc_txpending == 0)
    453  1.1  thorpej 			sc->sc_txdirty = nexttx;
    454  1.1  thorpej 
    455  1.1  thorpej 		sc->sc_txpending++;
    456  1.1  thorpej 
    457  1.1  thorpej 		txqueued = 1;
    458  1.1  thorpej 
    459  1.1  thorpej #if NBPFILTER > 0
    460  1.1  thorpej 		/*
    461  1.1  thorpej 		 * Pass the packet to any BPF listeners.
    462  1.1  thorpej 		 */
    463  1.1  thorpej 		if (ifp->if_bpf)
    464  1.1  thorpej 			bpf_mtap(ifp->if_bpf, m0);
    465  1.1  thorpej #endif
    466  1.1  thorpej 	}
    467  1.1  thorpej 
    468  1.1  thorpej  out:
    469  1.1  thorpej 	/*
    470  1.1  thorpej 	 * We're finished.  If we added more packets, make sure the
    471  1.1  thorpej 	 * transmit DMA engine is running.
    472  1.1  thorpej 	 */
    473  1.1  thorpej 	if (txqueued) {
    474  1.1  thorpej 		bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND,
    475  1.1  thorpej 		    COMMAND_TXQUEUED);
    476  1.1  thorpej 
    477  1.1  thorpej 		/*
    478  1.1  thorpej 		 * Set a 5 second watchdog timer.
    479  1.1  thorpej 		 */
    480  1.1  thorpej 		ifp->if_timer = 5;
    481  1.1  thorpej 	}
    482  1.1  thorpej }
    483  1.1  thorpej 
    484  1.1  thorpej /*
    485  1.1  thorpej  * Watchdog timer handler.
    486  1.1  thorpej  * [ifnet interface function]
    487  1.1  thorpej  */
    488  1.1  thorpej void
    489  1.1  thorpej epic_watchdog(ifp)
    490  1.1  thorpej 	struct ifnet *ifp;
    491  1.1  thorpej {
    492  1.1  thorpej 	struct epic_softc *sc = ifp->if_softc;
    493  1.1  thorpej 
    494  1.1  thorpej 	printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    495  1.1  thorpej 	ifp->if_oerrors++;
    496  1.1  thorpej 
    497  1.1  thorpej 	epic_init(sc);
    498  1.1  thorpej }
    499  1.1  thorpej 
    500  1.1  thorpej /*
    501  1.1  thorpej  * Handle control requests from the operator.
    502  1.1  thorpej  * [ifnet interface function]
    503  1.1  thorpej  */
    504  1.1  thorpej int
    505  1.1  thorpej epic_ioctl(ifp, cmd, data)
    506  1.1  thorpej 	struct ifnet *ifp;
    507  1.1  thorpej 	u_long cmd;
    508  1.1  thorpej 	caddr_t data;
    509  1.1  thorpej {
    510  1.1  thorpej 	struct epic_softc *sc = ifp->if_softc;
    511  1.1  thorpej 	struct ifreq *ifr = (struct ifreq *)data;
    512  1.1  thorpej 	struct ifaddr *ifa = (struct ifaddr *)data;
    513  1.1  thorpej 	int s, error = 0;
    514  1.1  thorpej 
    515  1.1  thorpej 	s = splimp();
    516  1.1  thorpej 
    517  1.1  thorpej 	switch (cmd) {
    518  1.1  thorpej 	case SIOCSIFADDR:
    519  1.1  thorpej 		ifp->if_flags |= IFF_UP;
    520  1.1  thorpej 
    521  1.1  thorpej 		switch (ifa->ifa_addr->sa_family) {
    522  1.1  thorpej #ifdef INET
    523  1.1  thorpej 		case AF_INET:
    524  1.1  thorpej 			epic_init(sc);
    525  1.1  thorpej 			arp_ifinit(ifp, ifa);
    526  1.1  thorpej 			break;
    527  1.1  thorpej #endif /* INET */
    528  1.1  thorpej #ifdef NS
    529  1.1  thorpej 		case AF_NS:
    530  1.1  thorpej 		    {
    531  1.1  thorpej 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
    532  1.1  thorpej 
    533  1.1  thorpej 			if (ns_nullhost(*ina))
    534  1.1  thorpej 				ina->x_host = *(union ns_host *)
    535  1.1  thorpej 				    LLADDR(ifp->if_sadl);
    536  1.1  thorpej 			else
    537  1.1  thorpej 				bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
    538  1.1  thorpej 				    ifp->if_addrlen);
    539  1.1  thorpej 			/* Set new address. */
    540  1.1  thorpej 			epic_init(sc);
    541  1.1  thorpej 			break;
    542  1.1  thorpej 		    }
    543  1.1  thorpej #endif /* NS */
    544  1.1  thorpej 		default:
    545  1.1  thorpej 			epic_init(sc);
    546  1.1  thorpej 			break;
    547  1.1  thorpej 		}
    548  1.1  thorpej 		break;
    549  1.1  thorpej 
    550  1.1  thorpej 	case SIOCSIFMTU:
    551  1.1  thorpej 		if (ifr->ifr_mtu > ETHERMTU)
    552  1.1  thorpej 			error = EINVAL;
    553  1.1  thorpej 		else
    554  1.1  thorpej 			ifp->if_mtu = ifr->ifr_mtu;
    555  1.1  thorpej 		break;
    556  1.1  thorpej 
    557  1.1  thorpej 	case SIOCSIFFLAGS:
    558  1.1  thorpej 		if ((ifp->if_flags & IFF_UP) == 0 &&
    559  1.1  thorpej 		    (ifp->if_flags & IFF_RUNNING) != 0) {
    560  1.1  thorpej 			/*
    561  1.1  thorpej 			 * If interface is marked down and it is running, then
    562  1.1  thorpej 			 * stop it.
    563  1.1  thorpej 			 */
    564  1.1  thorpej 			epic_stop(sc);
    565  1.1  thorpej 			ifp->if_flags &= ~IFF_RUNNING;
    566  1.1  thorpej 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
    567  1.1  thorpej 			   (ifp->if_flags & IFF_RUNNING) == 0) {
    568  1.1  thorpej 			/*
    569  1.1  thorpej 			 * If interfase it marked up and it is stopped, then
    570  1.1  thorpej 			 * start it.
    571  1.1  thorpej 			 */
    572  1.1  thorpej 			epic_init(sc);
    573  1.1  thorpej 		} else {
    574  1.1  thorpej 			/*
    575  1.1  thorpej 			 * Reset the interface to pick up changes in any other
    576  1.1  thorpej 			 * flags that affect the hardware state.
    577  1.1  thorpej 			 */
    578  1.1  thorpej 			epic_init(sc);
    579  1.1  thorpej 		}
    580  1.1  thorpej 		break;
    581  1.1  thorpej 
    582  1.1  thorpej 	case SIOCADDMULTI:
    583  1.1  thorpej 	case SIOCDELMULTI:
    584  1.1  thorpej 		error = (cmd == SIOCADDMULTI) ?
    585  1.1  thorpej 		    ether_addmulti(ifr, &sc->sc_ethercom) :
    586  1.1  thorpej 		    ether_delmulti(ifr, &sc->sc_ethercom);
    587  1.1  thorpej 
    588  1.1  thorpej 		if (error == ENETRESET) {
    589  1.1  thorpej 			/*
    590  1.1  thorpej 			 * Multicast list has changed; set the hardware filter
    591  1.1  thorpej 			 * accordingly.
    592  1.1  thorpej 			 */
    593  1.1  thorpej 			epic_init(sc);
    594  1.1  thorpej 			error = 0;
    595  1.1  thorpej 		}
    596  1.1  thorpej 		break;
    597  1.1  thorpej 
    598  1.1  thorpej 	default:
    599  1.1  thorpej 		error = EINVAL;
    600  1.1  thorpej 		break;
    601  1.1  thorpej 	}
    602  1.1  thorpej 
    603  1.1  thorpej 	splx(s);
    604  1.1  thorpej 	return (error);
    605  1.1  thorpej }
    606  1.1  thorpej 
    607  1.1  thorpej /*
    608  1.1  thorpej  * Interrupt handler.
    609  1.1  thorpej  */
    610  1.1  thorpej int
    611  1.1  thorpej epic_intr(arg)
    612  1.1  thorpej 	void *arg;
    613  1.1  thorpej {
    614  1.1  thorpej 	struct epic_softc *sc = arg;
    615  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    616  1.1  thorpej 	struct ether_header *eh;
    617  1.1  thorpej 	struct epic_rxdesc *rxd;
    618  1.1  thorpej 	struct epic_txdesc *txd;
    619  1.1  thorpej 	struct epic_descsoft *ds;
    620  1.1  thorpej 	struct mbuf *m;
    621  1.1  thorpej 	u_int32_t intstat;
    622  1.1  thorpej 	int i, len, claimed = 0, error;
    623  1.1  thorpej 
    624  1.1  thorpej  top:
    625  1.1  thorpej 	/*
    626  1.1  thorpej 	 * Get the interrupt status from the EPIC.
    627  1.1  thorpej 	 */
    628  1.1  thorpej 	intstat = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT);
    629  1.1  thorpej 	if ((intstat & INTSTAT_INT_ACTV) == 0)
    630  1.1  thorpej 		return (claimed);
    631  1.1  thorpej 
    632  1.1  thorpej 	claimed = 1;
    633  1.1  thorpej 
    634  1.1  thorpej 	/*
    635  1.1  thorpej 	 * Acknowledge the interrupt.
    636  1.1  thorpej 	 */
    637  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT,
    638  1.1  thorpej 	    intstat & INTMASK);
    639  1.1  thorpej 
    640  1.1  thorpej 	/*
    641  1.1  thorpej 	 * Check for receive interrupts.
    642  1.1  thorpej 	 */
    643  1.1  thorpej 	if (intstat & (INTSTAT_RCC | INTSTAT_RQE)) {
    644  1.1  thorpej 		for (i = sc->sc_rxptr;; i = EPIC_NEXTRX(i)) {
    645  1.1  thorpej 			rxd = &sc->sc_control_data->ecd_rxdescs[i];
    646  1.1  thorpej 			ds = &sc->sc_rxsoft[i];
    647  1.1  thorpej 			m = ds->ds_mbuf;
    648  1.1  thorpej 			error = 0;
    649  1.1  thorpej 
    650  1.1  thorpej 			if (rxd->er_rxstatus & ER_RXSTAT_OWNER) {
    651  1.1  thorpej 				/*
    652  1.1  thorpej 				 * We have processed all of the
    653  1.1  thorpej 				 * receive buffers.
    654  1.1  thorpej 				 */
    655  1.1  thorpej 				break;
    656  1.1  thorpej 			}
    657  1.1  thorpej 
    658  1.1  thorpej 			bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
    659  1.1  thorpej 			    ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
    660  1.1  thorpej 
    661  1.1  thorpej 			/*
    662  1.1  thorpej 			 * Make sure the packet arrived intact.
    663  1.1  thorpej 			 */
    664  1.1  thorpej 			if ((rxd->er_rxstatus & ER_RXSTAT_PKTINTACT) == 0) {
    665  1.1  thorpej #if 1
    666  1.1  thorpej 				if (rxd->er_rxstatus & ER_RXSTAT_CRCERROR)
    667  1.1  thorpej 					printf("%s: CRC error\n",
    668  1.1  thorpej 					    sc->sc_dev.dv_xname);
    669  1.1  thorpej 				if (rxd->er_rxstatus & ER_RXSTAT_ALIGNERROR)
    670  1.1  thorpej 					printf("%s: alignment error\n",
    671  1.1  thorpej 					    sc->sc_dev.dv_xname);
    672  1.1  thorpej #endif
    673  1.1  thorpej 				ifp->if_ierrors++;
    674  1.1  thorpej 				error = 1;
    675  1.1  thorpej 			}
    676  1.1  thorpej 
    677  1.1  thorpej 			/*
    678  1.1  thorpej 			 * Add a new buffer to the receive chain.  If this
    679  1.1  thorpej 			 * fails, the old buffer is recycled.
    680  1.1  thorpej 			 */
    681  1.1  thorpej 			if (epic_add_rxbuf(sc, i) == 0) {
    682  1.1  thorpej 				/*
    683  1.1  thorpej 				 * We wanted to reset the buffer, but
    684  1.1  thorpej 				 * didn't want to pass it on up.
    685  1.1  thorpej 				 */
    686  1.1  thorpej 				if (error) {
    687  1.1  thorpej 					m_freem(m);
    688  1.1  thorpej 					continue;
    689  1.1  thorpej 				}
    690  1.1  thorpej 
    691  1.1  thorpej 				len = rxd->er_buflength;
    692  1.1  thorpej 				if (len < sizeof(struct ether_header)) {
    693  1.1  thorpej 					m_freem(m);
    694  1.1  thorpej 					continue;
    695  1.1  thorpej 				}
    696  1.1  thorpej 
    697  1.1  thorpej 				m->m_pkthdr.rcvif = ifp;
    698  1.1  thorpej 				m->m_pkthdr.len = m->m_len = len;
    699  1.1  thorpej 				eh = mtod(m, struct ether_header *);
    700  1.1  thorpej #if NBPFILTER > 0
    701  1.1  thorpej 				/*
    702  1.1  thorpej 				 * Pass this up to any BPF listeners.
    703  1.1  thorpej 				 */
    704  1.1  thorpej 				if (ifp->if_bpf) {
    705  1.1  thorpej 					bpf_mtap(ifp->if_bpf, m);
    706  1.1  thorpej 
    707  1.1  thorpej 					/*
    708  1.1  thorpej 					 * Only pass this up the stack
    709  1.1  thorpej 					 * if it's for us.
    710  1.1  thorpej 					 */
    711  1.1  thorpej 					if ((ifp->if_flags & IFF_PROMISC) &&
    712  1.1  thorpej 					    bcmp(LLADDR(ifp->if_sadl),
    713  1.1  thorpej 						 eh->ether_dhost,
    714  1.1  thorpej 						 ETHER_ADDR_LEN) != 0 &&
    715  1.1  thorpej 					    (rxd->er_rxstatus &
    716  1.1  thorpej 					     (ER_RXSTAT_BCAST|ER_RXSTAT_MCAST))
    717  1.1  thorpej 					     == 0) {
    718  1.1  thorpej 						m_freem(m);
    719  1.1  thorpej 						continue;
    720  1.1  thorpej 					}
    721  1.1  thorpej 				}
    722  1.1  thorpej #endif /* NPBFILTER > 0 */
    723  1.1  thorpej 				m->m_data += sizeof(struct ether_header);
    724  1.1  thorpej 				m->m_len -= sizeof(struct ether_header);
    725  1.1  thorpej 				m->m_pkthdr.len = m->m_len;
    726  1.1  thorpej 				ether_input(ifp, eh, m);
    727  1.1  thorpej 			}
    728  1.1  thorpej 		}
    729  1.1  thorpej 
    730  1.1  thorpej 		/*
    731  1.1  thorpej 		 * Update the recieve pointer.
    732  1.1  thorpej 		 */
    733  1.1  thorpej 		sc->sc_rxptr = i;
    734  1.1  thorpej 
    735  1.1  thorpej 		/*
    736  1.1  thorpej 		 * Check for receive queue underflow.
    737  1.1  thorpej 		 */
    738  1.1  thorpej 		if (intstat & INTSTAT_RQE) {
    739  1.1  thorpej 			printf("%s: receiver queue empty\n",
    740  1.1  thorpej 			    sc->sc_dev.dv_xname);
    741  1.1  thorpej 			/*
    742  1.1  thorpej 			 * Ring is already built; just restart the
    743  1.1  thorpej 			 * receiver.
    744  1.1  thorpej 			 */
    745  1.1  thorpej 			bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_PRCDAR,
    746  1.1  thorpej 			    sc->sc_cddma + EPIC_CDOFF(ecd_rxdescs[0]));
    747  1.1  thorpej 			bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND,
    748  1.1  thorpej 			    COMMAND_RXQUEUED | COMMAND_START_RX);
    749  1.1  thorpej 		}
    750  1.1  thorpej 	}
    751  1.1  thorpej 
    752  1.1  thorpej 	/*
    753  1.1  thorpej 	 * Check for transmission complete interrupts.
    754  1.1  thorpej 	 */
    755  1.1  thorpej 	if (intstat & (INTSTAT_TXC | INTSTAT_TXU)) {
    756  1.1  thorpej 		for (i = sc->sc_txdirty;; i = EPIC_NEXTTX(i)) {
    757  1.1  thorpej 			txd = &sc->sc_control_data->ecd_txdescs[i];
    758  1.1  thorpej 			ds = &sc->sc_txsoft[i];
    759  1.1  thorpej 
    760  1.1  thorpej 			if (sc->sc_txpending == 0 ||
    761  1.1  thorpej 			    (txd->et_txstatus & ET_TXSTAT_OWNER) != 0)
    762  1.1  thorpej 				break;
    763  1.1  thorpej 
    764  1.1  thorpej 			if (ds->ds_mbuf != NULL) {
    765  1.1  thorpej 				bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap,
    766  1.1  thorpej 				    0, ds->ds_dmamap->dm_mapsize,
    767  1.1  thorpej 				    BUS_DMASYNC_POSTWRITE);
    768  1.1  thorpej 				bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
    769  1.1  thorpej 				m_freem(ds->ds_mbuf);
    770  1.1  thorpej 				ds->ds_mbuf = NULL;
    771  1.1  thorpej 			}
    772  1.1  thorpej 			sc->sc_txpending--;
    773  1.1  thorpej 
    774  1.1  thorpej 			/*
    775  1.1  thorpej 			 * Check for errors and collisions.
    776  1.1  thorpej 			 */
    777  1.1  thorpej 			if ((txd->et_txstatus & ET_TXSTAT_PACKETTX) == 0)
    778  1.1  thorpej 				ifp->if_oerrors++;
    779  1.1  thorpej 			ifp->if_collisions +=
    780  1.1  thorpej 			    TXSTAT_COLLISIONS(txd->et_txstatus);
    781  1.1  thorpej 			if (txd->et_txstatus & ET_TXSTAT_CARSENSELOST) {
    782  1.1  thorpej #if 1
    783  1.1  thorpej 				printf("%s: lost carrier\n",
    784  1.1  thorpej 				    sc->sc_dev.dv_xname);
    785  1.1  thorpej #endif
    786  1.1  thorpej 				/* XXX clear "active" but in media data */
    787  1.1  thorpej 			}
    788  1.1  thorpej 		}
    789  1.1  thorpej 
    790  1.1  thorpej 		/*
    791  1.1  thorpej 		 * Update the dirty transmit buffer pointer.
    792  1.1  thorpej 		 */
    793  1.1  thorpej 		sc->sc_txdirty = i;
    794  1.1  thorpej 
    795  1.1  thorpej 		/*
    796  1.1  thorpej 		 * Cancel the watchdog timer if there are no pending
    797  1.1  thorpej 		 * transmissions.
    798  1.1  thorpej 		 */
    799  1.1  thorpej 		if (sc->sc_txpending == 0)
    800  1.1  thorpej 			ifp->if_timer = 0;
    801  1.1  thorpej 
    802  1.1  thorpej 		/*
    803  1.1  thorpej 		 * Kick the transmitter after a DMA underrun.
    804  1.1  thorpej 		 */
    805  1.1  thorpej 		if (intstat & INTSTAT_TXU) {
    806  1.1  thorpej 			printf("%s: transmit underrun\n", sc->sc_dev.dv_xname);
    807  1.1  thorpej 			bus_space_write_4(sc->sc_st, sc->sc_sh,
    808  1.1  thorpej 			    EPIC_COMMAND, COMMAND_TXUGO);
    809  1.1  thorpej 			if (sc->sc_txpending)
    810  1.1  thorpej 				bus_space_write_4(sc->sc_st, sc->sc_sh,
    811  1.1  thorpej 				    EPIC_COMMAND, COMMAND_TXQUEUED);
    812  1.1  thorpej 		}
    813  1.1  thorpej 
    814  1.1  thorpej 		/*
    815  1.1  thorpej 		 * Try to get more packets going.
    816  1.1  thorpej 		 */
    817  1.1  thorpej 		epic_start(ifp);
    818  1.1  thorpej 	}
    819  1.1  thorpej 
    820  1.1  thorpej 	/*
    821  1.1  thorpej 	 * Check for fatal interrupts.
    822  1.1  thorpej 	 */
    823  1.1  thorpej 	if (intstat & INTSTAT_FATAL_INT) {
    824  1.1  thorpej 		printf("%s: fatal error, resetting\n", sc->sc_dev.dv_xname);
    825  1.1  thorpej 		epic_init(sc);
    826  1.1  thorpej 	}
    827  1.1  thorpej 
    828  1.1  thorpej 	/*
    829  1.1  thorpej 	 * Check for more interrupts.
    830  1.1  thorpej 	 */
    831  1.1  thorpej 	goto top;
    832  1.1  thorpej }
    833  1.1  thorpej 
    834  1.1  thorpej /*
    835  1.1  thorpej  * Perform a soft reset on the EPIC.
    836  1.1  thorpej  */
    837  1.1  thorpej void
    838  1.1  thorpej epic_reset(sc)
    839  1.1  thorpej 	struct epic_softc *sc;
    840  1.1  thorpej {
    841  1.1  thorpej 
    842  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, 0);
    843  1.1  thorpej 	delay(100);
    844  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, GENCTL_SOFTRESET);
    845  1.1  thorpej 	delay(100);
    846  1.1  thorpej }
    847  1.1  thorpej 
    848  1.1  thorpej /*
    849  1.1  thorpej  * Initialize the interface.  Must be called at splimp().
    850  1.1  thorpej  */
    851  1.1  thorpej void
    852  1.1  thorpej epic_init(sc)
    853  1.1  thorpej 	struct epic_softc *sc;
    854  1.1  thorpej {
    855  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
    856  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
    857  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    858  1.1  thorpej 	u_int8_t *enaddr = LLADDR(ifp->if_sadl);
    859  1.1  thorpej 	struct epic_txdesc *txd;
    860  1.1  thorpej 	struct epic_rxdesc *rxd;
    861  1.1  thorpej 	u_int32_t genctl, reg0;
    862  1.1  thorpej 	int i;
    863  1.1  thorpej 
    864  1.1  thorpej 	/*
    865  1.1  thorpej 	 * Cancel any pending I/O.
    866  1.1  thorpej 	 */
    867  1.1  thorpej 	epic_stop(sc);
    868  1.1  thorpej 
    869  1.1  thorpej 	/*
    870  1.1  thorpej 	 * Reset the EPIC to a known state.
    871  1.1  thorpej 	 */
    872  1.1  thorpej 	epic_reset(sc);
    873  1.1  thorpej 
    874  1.1  thorpej 	/*
    875  1.1  thorpej 	 * Magical mystery initialization.
    876  1.1  thorpej 	 */
    877  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_TEST, TEST_INIT);
    878  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_TXTEST, 0);
    879  1.1  thorpej 
    880  1.1  thorpej 	/*
    881  1.1  thorpej 	 * Initialize the EPIC genctl register:
    882  1.1  thorpej 	 *
    883  1.1  thorpej 	 *	- 64 byte receive FIFO threshold
    884  1.1  thorpej 	 *	- automatic advance to next receive frame
    885  1.1  thorpej 	 */
    886  1.1  thorpej 	genctl = GENCTL_RX_FIFO_THRESH0 | GENCTL_ONECOPY;
    887  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_GENCTL, genctl);
    888  1.1  thorpej 
    889  1.1  thorpej 	/*
    890  1.1  thorpej 	 * Reset the MII bus and PHY.
    891  1.1  thorpej 	 */
    892  1.1  thorpej 	reg0 = bus_space_read_4(st, sh, EPIC_NVCTL);
    893  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_NVCTL, reg0 | NVCTL_GPIO1 | NVCTL_GPOE1);
    894  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_MIICFG, MIICFG_ENASER);
    895  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_RESET_PHY);
    896  1.1  thorpej 	delay(100);
    897  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_GENCTL, genctl);
    898  1.1  thorpej 	delay(100);
    899  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_NVCTL, reg0);
    900  1.1  thorpej 
    901  1.1  thorpej 	/*
    902  1.1  thorpej 	 * Initialize Ethernet address.
    903  1.1  thorpej 	 */
    904  1.1  thorpej 	reg0 = enaddr[1] << 8 | enaddr[0];
    905  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_LAN0, reg0);
    906  1.1  thorpej 	reg0 = enaddr[3] << 8 | enaddr[2];
    907  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_LAN1, reg0);
    908  1.1  thorpej 	reg0 = enaddr[5] << 8 | enaddr[4];
    909  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_LAN2, reg0);
    910  1.1  thorpej 
    911  1.1  thorpej 	/*
    912  1.1  thorpej 	 * Set up the multicast hash table.
    913  1.1  thorpej 	 */
    914  1.1  thorpej 	epic_set_mchash(sc);
    915  1.1  thorpej 
    916  1.1  thorpej 	/*
    917  1.1  thorpej 	 * Initialize receive control.  Remember the external buffer
    918  1.1  thorpej 	 * size setting.
    919  1.1  thorpej 	 */
    920  1.1  thorpej 	reg0 = bus_space_read_4(st, sh, EPIC_RXCON) &
    921  1.1  thorpej 	    (RXCON_EXTBUFSIZESEL1 | RXCON_EXTBUFSIZESEL0);
    922  1.1  thorpej 	reg0 |= (RXCON_RXMULTICAST | RXCON_RXBROADCAST);
    923  1.1  thorpej 	if (ifp->if_flags & IFF_PROMISC)
    924  1.1  thorpej 		reg0 |= RXCON_PROMISCMODE;
    925  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_RXCON, reg0);
    926  1.1  thorpej 
    927  1.1  thorpej 	/*
    928  1.1  thorpej 	 * XXX Media (full-duplex in TXCON).
    929  1.1  thorpej 	 */
    930  1.1  thorpej 
    931  1.1  thorpej 	/*
    932  1.1  thorpej 	 * Initialize the transmit descriptors.
    933  1.1  thorpej 	 */
    934  1.1  thorpej 	txd = sc->sc_control_data->ecd_txdescs;
    935  1.1  thorpej 	bzero(txd, sizeof(sc->sc_control_data->ecd_txdescs));
    936  1.1  thorpej 	for (i = 0; i < EPIC_NTXDESC; i++) {
    937  1.1  thorpej 		txd[i].et_control = ET_TXCTL_LASTDESC | ET_TXCTL_IAF |
    938  1.1  thorpej 		    ET_TXCTL_FRAGLIST;
    939  1.1  thorpej 		txd[i].et_bufaddr = sc->sc_cddma + EPIC_CDOFF(ecd_txfrags[i]);
    940  1.1  thorpej 		txd[i].et_nextdesc = sc->sc_cddma +
    941  1.1  thorpej 		    EPIC_CDOFF(ecd_txdescs[(i + 1) & EPIC_NTXDESC_MASK]);
    942  1.1  thorpej 	}
    943  1.1  thorpej 
    944  1.1  thorpej 	/*
    945  1.1  thorpej 	 * Initialize the receive descriptors.  Note the buffers
    946  1.1  thorpej 	 * and control word have already been initialized; we only
    947  1.1  thorpej 	 * need to initialize the ring.
    948  1.1  thorpej 	 */
    949  1.1  thorpej 	rxd = sc->sc_control_data->ecd_rxdescs;
    950  1.1  thorpej 	for (i = 0; i < EPIC_NRXDESC; i++) {
    951  1.1  thorpej 		rxd[i].er_nextdesc = sc->sc_cddma +
    952  1.1  thorpej 		    EPIC_CDOFF(ecd_rxdescs[(i + 1) & EPIC_NRXDESC_MASK]);
    953  1.1  thorpej 	}
    954  1.1  thorpej 
    955  1.1  thorpej 	/*
    956  1.1  thorpej 	 * Initialize the interrupt mask and enable interrupts.
    957  1.1  thorpej 	 */
    958  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_INTMASK, INTMASK);
    959  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_INTENA);
    960  1.1  thorpej 
    961  1.1  thorpej 	/*
    962  1.1  thorpej 	 * Give the transmit and receive rings to the EPIC.
    963  1.1  thorpej 	 */
    964  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_PTCDAR,
    965  1.1  thorpej 	    sc->sc_cddma + EPIC_CDOFF(ecd_txdescs[0]));
    966  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_PRCDAR,
    967  1.1  thorpej 	    sc->sc_cddma + EPIC_CDOFF(ecd_rxdescs[0]));
    968  1.1  thorpej 
    969  1.1  thorpej 	/*
    970  1.1  thorpej 	 * Initialize our ring pointers.  txlast it initialized to
    971  1.1  thorpej 	 * the end of the list so that it will wrap around to the
    972  1.1  thorpej 	 * first descriptor when the first packet is transmitted.
    973  1.1  thorpej 	 */
    974  1.1  thorpej 	sc->sc_txpending = 0;
    975  1.1  thorpej 	sc->sc_txdirty = 0;
    976  1.1  thorpej 	sc->sc_txlast = EPIC_NTXDESC - 1;
    977  1.1  thorpej 
    978  1.1  thorpej 	sc->sc_rxptr = 0;
    979  1.1  thorpej 
    980  1.1  thorpej 	/*
    981  1.1  thorpej 	 * Set the EPIC in motion.
    982  1.1  thorpej 	 */
    983  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_COMMAND,
    984  1.1  thorpej 	    COMMAND_RXQUEUED | COMMAND_START_RX);
    985  1.1  thorpej 
    986  1.1  thorpej 	/*
    987  1.1  thorpej 	 * ...all done!
    988  1.1  thorpej 	 */
    989  1.1  thorpej 	ifp->if_flags |= IFF_RUNNING;
    990  1.1  thorpej 	ifp->if_flags &= ~IFF_OACTIVE;
    991  1.1  thorpej }
    992  1.1  thorpej 
    993  1.1  thorpej /*
    994  1.1  thorpej  * Stop transmission on the interface.
    995  1.1  thorpej  */
    996  1.1  thorpej void
    997  1.1  thorpej epic_stop(sc)
    998  1.1  thorpej 	struct epic_softc *sc;
    999  1.1  thorpej {
   1000  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
   1001  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
   1002  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1003  1.1  thorpej 	struct epic_descsoft *ds;
   1004  1.1  thorpej 	u_int32_t reg;
   1005  1.1  thorpej 	int i;
   1006  1.1  thorpej 
   1007  1.1  thorpej 	/*
   1008  1.1  thorpej 	 * Disable interrupts.
   1009  1.1  thorpej 	 */
   1010  1.1  thorpej 	reg = bus_space_read_4(st, sh, EPIC_GENCTL);
   1011  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_GENCTL, reg & ~GENCTL_INTENA);
   1012  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_INTMASK, 0);
   1013  1.1  thorpej 
   1014  1.1  thorpej 	/*
   1015  1.1  thorpej 	 * Stop the DMA engine and take the receiver off-line.
   1016  1.1  thorpej 	 */
   1017  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_COMMAND, COMMAND_STOP_RDMA |
   1018  1.1  thorpej 	    COMMAND_STOP_TDMA | COMMAND_STOP_RX);
   1019  1.1  thorpej 
   1020  1.1  thorpej 	/*
   1021  1.1  thorpej 	 * Release any queued transmit buffers.
   1022  1.1  thorpej 	 */
   1023  1.1  thorpej 	for (i = 0; i < EPIC_NTXDESC; i++) {
   1024  1.1  thorpej 		ds = &sc->sc_txsoft[i];
   1025  1.1  thorpej 		if (ds->ds_mbuf != NULL) {
   1026  1.1  thorpej 			bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
   1027  1.1  thorpej 			m_freem(ds->ds_mbuf);
   1028  1.1  thorpej 			ds->ds_mbuf = NULL;
   1029  1.1  thorpej 		}
   1030  1.1  thorpej 	}
   1031  1.1  thorpej 	sc->sc_txpending = 0;
   1032  1.1  thorpej 
   1033  1.1  thorpej 	/*
   1034  1.1  thorpej 	 * Release the receive buffers, then reallocate/reinitialize.
   1035  1.1  thorpej 	 */
   1036  1.1  thorpej 	for (i = 0; i < EPIC_NRXDESC; i++) {
   1037  1.1  thorpej 		ds = &sc->sc_rxsoft[i];
   1038  1.1  thorpej 		if (ds->ds_mbuf != NULL) {
   1039  1.1  thorpej 			bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
   1040  1.1  thorpej 			m_freem(ds->ds_mbuf);
   1041  1.1  thorpej 			ds->ds_mbuf = NULL;
   1042  1.1  thorpej 		}
   1043  1.1  thorpej 		if (epic_add_rxbuf(sc, i) != 0) {
   1044  1.1  thorpej 			/*
   1045  1.1  thorpej 			 * This "can't happen" - we're at splimp()
   1046  1.1  thorpej 			 * and we just freed the buffer we need
   1047  1.1  thorpej 			 * above.
   1048  1.1  thorpej 			 */
   1049  1.1  thorpej 			panic("epic_stop: no buffers!");
   1050  1.1  thorpej 		}
   1051  1.1  thorpej 	}
   1052  1.1  thorpej 
   1053  1.1  thorpej 	/*
   1054  1.1  thorpej 	 * Mark the interface down and cancel the watchdog timer.
   1055  1.1  thorpej 	 */
   1056  1.1  thorpej 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   1057  1.1  thorpej 	ifp->if_timer = 0;
   1058  1.1  thorpej }
   1059  1.1  thorpej 
   1060  1.1  thorpej /*
   1061  1.1  thorpej  * Read the EPIC Serial EEPROM.
   1062  1.1  thorpej  */
   1063  1.1  thorpej void
   1064  1.1  thorpej epic_read_eeprom(sc, word, wordcnt, data)
   1065  1.1  thorpej 	struct epic_softc *sc;
   1066  1.1  thorpej 	int word, wordcnt;
   1067  1.1  thorpej 	u_int16_t *data;
   1068  1.1  thorpej {
   1069  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
   1070  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
   1071  1.1  thorpej 	u_int16_t reg;
   1072  1.1  thorpej 	int i, x;
   1073  1.1  thorpej 
   1074  1.1  thorpej #define	EEPROM_WAIT_READY(st, sh) \
   1075  1.1  thorpej 	while ((bus_space_read_4((st), (sh), EPIC_EECTL) & EECTL_EERDY) == 0) \
   1076  1.1  thorpej 		/* nothing */
   1077  1.1  thorpej 
   1078  1.1  thorpej 	/*
   1079  1.1  thorpej 	 * Enable the EEPROM.
   1080  1.1  thorpej 	 */
   1081  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE);
   1082  1.1  thorpej 	EEPROM_WAIT_READY(st, sh);
   1083  1.1  thorpej 
   1084  1.1  thorpej 	for (i = 0; i < wordcnt; i++) {
   1085  1.1  thorpej 		/* Send CHIP SELECT for one clock tick. */
   1086  1.1  thorpej 		bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE|EECTL_EECS);
   1087  1.1  thorpej 		EEPROM_WAIT_READY(st, sh);
   1088  1.1  thorpej 
   1089  1.1  thorpej 		/* Shift in the READ opcode. */
   1090  1.1  thorpej 		for (x = 3; x > 0; x--) {
   1091  1.1  thorpej 			reg = EECTL_ENABLE|EECTL_EECS;
   1092  1.1  thorpej 			if (EPIC_EEPROM_OPC_READ & (1 << (x - 1)))
   1093  1.1  thorpej 				reg |= EECTL_EEDI;
   1094  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg);
   1095  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1096  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
   1097  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1098  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg);
   1099  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1100  1.1  thorpej 		}
   1101  1.1  thorpej 
   1102  1.1  thorpej 		/* Shift in address. */
   1103  1.1  thorpej 		for (x = 6; x > 0; x--) {
   1104  1.1  thorpej 			reg = EECTL_ENABLE|EECTL_EECS;
   1105  1.1  thorpej 			if ((word + i) & (1 << (x - 1)))
   1106  1.1  thorpej 				reg |= EECTL_EEDI;
   1107  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg);
   1108  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1109  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
   1110  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1111  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg);
   1112  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1113  1.1  thorpej 		}
   1114  1.1  thorpej 
   1115  1.1  thorpej 		/* Shift out data. */
   1116  1.1  thorpej 		reg = EECTL_ENABLE|EECTL_EECS;
   1117  1.1  thorpej 		data[i] = 0;
   1118  1.1  thorpej 		for (x = 16; x > 0; x--) {
   1119  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
   1120  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1121  1.1  thorpej 			if (bus_space_read_4(st, sh, EPIC_EECTL) & EECTL_EEDO)
   1122  1.1  thorpej 				data[i] |= (1 << (x - 1));
   1123  1.1  thorpej 			bus_space_write_4(st, sh, EPIC_EECTL, reg);
   1124  1.1  thorpej 			EEPROM_WAIT_READY(st, sh);
   1125  1.1  thorpej 		}
   1126  1.1  thorpej 
   1127  1.1  thorpej 		/* Clear CHIP SELECT. */
   1128  1.1  thorpej 		bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE);
   1129  1.1  thorpej 		EEPROM_WAIT_READY(st, sh);
   1130  1.1  thorpej 	}
   1131  1.1  thorpej 
   1132  1.1  thorpej 	/*
   1133  1.1  thorpej 	 * Disable the EEPROM.
   1134  1.1  thorpej 	 */
   1135  1.1  thorpej 	bus_space_write_4(st, sh, EPIC_EECTL, 0);
   1136  1.1  thorpej 
   1137  1.1  thorpej #undef EEPROM_WAIT_READY
   1138  1.1  thorpej }
   1139  1.1  thorpej 
   1140  1.1  thorpej /*
   1141  1.1  thorpej  * Add a receive buffer to the indicated descriptor.
   1142  1.1  thorpej  */
   1143  1.1  thorpej int
   1144  1.1  thorpej epic_add_rxbuf(sc, idx)
   1145  1.1  thorpej 	struct epic_softc *sc;
   1146  1.1  thorpej 	int idx;
   1147  1.1  thorpej {
   1148  1.1  thorpej 	struct epic_rxdesc *rxd = &sc->sc_control_data->ecd_rxdescs[idx];
   1149  1.1  thorpej 	struct epic_descsoft *ds = &sc->sc_rxsoft[idx];
   1150  1.1  thorpej 	struct mbuf *m, *oldm;
   1151  1.1  thorpej 	int error = 0;
   1152  1.1  thorpej 
   1153  1.1  thorpej 	oldm = ds->ds_mbuf;
   1154  1.1  thorpej 
   1155  1.1  thorpej 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1156  1.1  thorpej 	if (m != NULL) {
   1157  1.1  thorpej 		MCLGET(m, M_DONTWAIT);
   1158  1.1  thorpej 		if ((m->m_flags & M_EXT) == 0) {
   1159  1.1  thorpej 			error = ENOMEM;
   1160  1.1  thorpej 			m_freem(m);
   1161  1.1  thorpej 			if (oldm == NULL)
   1162  1.1  thorpej 				return (error);
   1163  1.1  thorpej 			m = oldm;
   1164  1.1  thorpej 			m->m_data = m->m_ext.ext_buf;
   1165  1.1  thorpej 		}
   1166  1.1  thorpej 	} else {
   1167  1.1  thorpej 		error = ENOMEM;
   1168  1.1  thorpej 		if (oldm == NULL)
   1169  1.1  thorpej 			return (error);
   1170  1.1  thorpej 		m = oldm;
   1171  1.1  thorpej 		m->m_data = m->m_ext.ext_buf;
   1172  1.1  thorpej 	}
   1173  1.1  thorpej 
   1174  1.1  thorpej 	ds->ds_mbuf = m;
   1175  1.1  thorpej 
   1176  1.1  thorpej 	/*
   1177  1.1  thorpej 	 * Set up the DMA map for this receive buffer.
   1178  1.1  thorpej 	 */
   1179  1.1  thorpej 	if (m != oldm) {
   1180  1.1  thorpej 		if (oldm != NULL)
   1181  1.1  thorpej 			bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
   1182  1.1  thorpej 		error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap,
   1183  1.1  thorpej 		    m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
   1184  1.1  thorpej 		if (error) {
   1185  1.1  thorpej 			printf("%s: can't load rx buffer, error = %d\n",
   1186  1.1  thorpej 			    sc->sc_dev.dv_xname, error);
   1187  1.1  thorpej 			panic("epic_add_rxbuf");	/* XXX */
   1188  1.1  thorpej 		}
   1189  1.1  thorpej 	}
   1190  1.1  thorpej 
   1191  1.1  thorpej 	bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
   1192  1.1  thorpej 	    ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
   1193  1.1  thorpej 
   1194  1.1  thorpej 	/*
   1195  1.1  thorpej 	 * Move the data pointer up so that the incoming packet
   1196  1.1  thorpej 	 * will be 32-bit aligned.
   1197  1.1  thorpej 	 */
   1198  1.1  thorpej 	m->m_data += RX_ALIGNMENT_FUDGE;
   1199  1.1  thorpej 
   1200  1.1  thorpej 	/*
   1201  1.1  thorpej 	 * Initialize the receive descriptor.
   1202  1.1  thorpej 	 */
   1203  1.1  thorpej 	rxd->er_bufaddr = ds->ds_dmamap->dm_segs[0].ds_addr +
   1204  1.1  thorpej 	    RX_ALIGNMENT_FUDGE;
   1205  1.1  thorpej 	rxd->er_buflength = m->m_ext.ext_size - RX_ALIGNMENT_FUDGE;
   1206  1.1  thorpej 	rxd->er_control = 0;
   1207  1.1  thorpej 	rxd->er_rxstatus = ER_RXSTAT_OWNER;
   1208  1.1  thorpej 
   1209  1.1  thorpej 	return (error);
   1210  1.1  thorpej }
   1211  1.1  thorpej 
   1212  1.1  thorpej /*
   1213  1.1  thorpej  * Set the EPIC multicast hash table.
   1214  1.1  thorpej  */
   1215  1.1  thorpej void
   1216  1.1  thorpej epic_set_mchash(sc)
   1217  1.1  thorpej 	struct epic_softc *sc;
   1218  1.1  thorpej {
   1219  1.1  thorpej 	struct ethercom *ec = &sc->sc_ethercom;
   1220  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1221  1.1  thorpej 	struct ether_multi *enm;
   1222  1.1  thorpej 	struct ether_multistep step;
   1223  1.1  thorpej 	u_int8_t *cp;
   1224  1.1  thorpej 	u_int32_t crc, mchash[4];
   1225  1.1  thorpej 	int len;
   1226  1.1  thorpej 	static const u_int32_t crctab[] = {
   1227  1.1  thorpej 		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
   1228  1.1  thorpej 		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
   1229  1.1  thorpej 		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
   1230  1.1  thorpej 		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
   1231  1.1  thorpej 	};
   1232  1.1  thorpej 
   1233  1.1  thorpej 	/*
   1234  1.1  thorpej 	 * Set up the multicast address filter by passing all multicast
   1235  1.1  thorpej 	 * addresses through a CRC generator, and then using the high-order
   1236  1.1  thorpej 	 * 6 bits as an index into the 64 bit multicast hash table (only
   1237  1.1  thorpej 	 * the lower 16 bits of each 32 bit multicast hash register are
   1238  1.1  thorpej 	 * valid).  The high order bit selects the register, while the
   1239  1.1  thorpej 	 * rest of the bits select the bit within the register.
   1240  1.1  thorpej 	 */
   1241  1.1  thorpej 
   1242  1.1  thorpej 	if (ifp->if_flags & IFF_PROMISC)
   1243  1.1  thorpej 		goto allmulti;
   1244  1.1  thorpej 
   1245  1.1  thorpej #if 1 /* XXX thorpej - hardware bug in 10Mb mode */
   1246  1.1  thorpej 	goto allmulti;
   1247  1.1  thorpej #endif
   1248  1.1  thorpej 
   1249  1.1  thorpej 	mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0;
   1250  1.1  thorpej 
   1251  1.1  thorpej 	ETHER_FIRST_MULTI(step, ec, enm);
   1252  1.1  thorpej 	while (enm != NULL) {
   1253  1.1  thorpej 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
   1254  1.1  thorpej 			/*
   1255  1.1  thorpej 			 * We must listen to a range of multicast addresses.
   1256  1.1  thorpej 			 * For now, just accept all multicasts, rather than
   1257  1.1  thorpej 			 * trying to set only those filter bits needed to match
   1258  1.1  thorpej 			 * the range.  (At this time, the only use of address
   1259  1.1  thorpej 			 * ranges is for IP multicast routing, for which the
   1260  1.1  thorpej 			 * range is big enough to require all bits set.)
   1261  1.1  thorpej 			 */
   1262  1.1  thorpej 			goto allmulti;
   1263  1.1  thorpej 		}
   1264  1.1  thorpej 
   1265  1.1  thorpej 		cp = enm->enm_addrlo;
   1266  1.1  thorpej 		crc = 0xffffffff;
   1267  1.1  thorpej 		for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
   1268  1.1  thorpej 			crc ^= *cp++;
   1269  1.1  thorpej 			crc = (crc >> 4) ^ crctab[crc & 0xf];
   1270  1.1  thorpej 			crc = (crc >> 4) ^ crctab[crc & 0xf];
   1271  1.1  thorpej 		}
   1272  1.1  thorpej 		/* Just want the 6 most significant bits. */
   1273  1.1  thorpej 		crc >>= 26;
   1274  1.1  thorpej 
   1275  1.1  thorpej 		/* Set the corresponding bit in the hash table. */
   1276  1.1  thorpej 		mchash[crc >> 4] |= 1 << (crc & 0xf);
   1277  1.1  thorpej 
   1278  1.1  thorpej 		ETHER_NEXT_MULTI(step, enm);
   1279  1.1  thorpej 	}
   1280  1.1  thorpej 
   1281  1.1  thorpej 	ifp->if_flags &= ~IFF_ALLMULTI;
   1282  1.1  thorpej 	goto sethash;
   1283  1.1  thorpej 
   1284  1.1  thorpej  allmulti:
   1285  1.1  thorpej 	ifp->if_flags |= IFF_ALLMULTI;
   1286  1.1  thorpej 	mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0xffff;
   1287  1.1  thorpej 
   1288  1.1  thorpej  sethash:
   1289  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC0, mchash[0]);
   1290  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC1, mchash[1]);
   1291  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC2, mchash[2]);
   1292  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC3, mchash[3]);
   1293  1.1  thorpej }
   1294