Home | History | Annotate | Line # | Download | only in pci
if_sip.c revision 1.3
      1  1.3  thorpej /*	$NetBSD: if_sip.c,v 1.3 1999/11/04 00:24:32 thorpej Exp $	*/
      2  1.1  thorpej 
      3  1.1  thorpej /*-
      4  1.1  thorpej  * Copyright (c) 1999 Network Computer, Inc.
      5  1.1  thorpej  * All rights reserved.
      6  1.1  thorpej  *
      7  1.1  thorpej  * Redistribution and use in source and binary forms, with or without
      8  1.1  thorpej  * modification, are permitted provided that the following conditions
      9  1.1  thorpej  * are met:
     10  1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     11  1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     12  1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     15  1.1  thorpej  * 3. Neither the name of Network Computer, Inc. nor the names of its
     16  1.1  thorpej  *    contributors may be used to endorse or promote products derived
     17  1.1  thorpej  *    from this software without specific prior written permission.
     18  1.1  thorpej  *
     19  1.1  thorpej  * THIS SOFTWARE IS PROVIDED BY NETWORK COMPUTER, INC. AND CONTRIBUTORS
     20  1.1  thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1  thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1  thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1  thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1  thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1  thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1  thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1  thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1  thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1  thorpej  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1  thorpej  */
     31  1.1  thorpej 
     32  1.1  thorpej /*
     33  1.1  thorpej  * Device driver for the Silicon Integrated Systems SiS900 10/100 PCI
     34  1.1  thorpej  * Ethernet controller.
     35  1.1  thorpej  *
     36  1.1  thorpej  * Written by Jason R. Thorpe for Network Computer, Inc.
     37  1.1  thorpej  */
     38  1.1  thorpej 
     39  1.1  thorpej #include "opt_inet.h"
     40  1.1  thorpej #include "opt_ns.h"
     41  1.1  thorpej #include "bpfilter.h"
     42  1.1  thorpej 
     43  1.1  thorpej #include <sys/param.h>
     44  1.1  thorpej #include <sys/systm.h>
     45  1.1  thorpej #include <sys/mbuf.h>
     46  1.1  thorpej #include <sys/malloc.h>
     47  1.1  thorpej #include <sys/kernel.h>
     48  1.1  thorpej #include <sys/socket.h>
     49  1.1  thorpej #include <sys/ioctl.h>
     50  1.1  thorpej #include <sys/errno.h>
     51  1.1  thorpej #include <sys/device.h>
     52  1.1  thorpej #include <sys/queue.h>
     53  1.1  thorpej 
     54  1.1  thorpej #include <vm/vm.h>		/* for PAGE_SIZE */
     55  1.1  thorpej 
     56  1.1  thorpej #include <net/if.h>
     57  1.1  thorpej #include <net/if_dl.h>
     58  1.1  thorpej #include <net/if_media.h>
     59  1.1  thorpej #include <net/if_ether.h>
     60  1.1  thorpej 
     61  1.1  thorpej #if NBPFILTER > 0
     62  1.1  thorpej #include <net/bpf.h>
     63  1.1  thorpej #endif
     64  1.1  thorpej 
     65  1.1  thorpej #ifdef INET
     66  1.1  thorpej #include <netinet/in.h>
     67  1.1  thorpej #include <netinet/if_inarp.h>
     68  1.1  thorpej #endif
     69  1.1  thorpej 
     70  1.1  thorpej #ifdef NS
     71  1.1  thorpej #include <netns/ns.h>
     72  1.1  thorpej #include <netns/ns_if.h>
     73  1.1  thorpej #endif
     74  1.1  thorpej 
     75  1.1  thorpej #include <machine/bus.h>
     76  1.1  thorpej #include <machine/intr.h>
     77  1.1  thorpej 
     78  1.1  thorpej #include <dev/mii/miivar.h>
     79  1.1  thorpej 
     80  1.1  thorpej #include <dev/pci/pcireg.h>
     81  1.1  thorpej #include <dev/pci/pcivar.h>
     82  1.1  thorpej #include <dev/pci/pcidevs.h>
     83  1.1  thorpej 
     84  1.1  thorpej #include <dev/pci/if_sipreg.h>
     85  1.1  thorpej 
     86  1.1  thorpej /*
     87  1.1  thorpej  * Devices supported by this driver.
     88  1.1  thorpej  */
     89  1.1  thorpej const struct sip_product {
     90  1.1  thorpej 	pci_vendor_id_t		sip_vendor;
     91  1.1  thorpej 	pci_product_id_t	sip_product;
     92  1.1  thorpej 	const char		*sip_name;
     93  1.1  thorpej } sip_products[] = {
     94  1.1  thorpej 	{ PCI_VENDOR_SIS,	PCI_PRODUCT_SIS_900,
     95  1.1  thorpej 	  "SiS 900 10/100 Ethernet" },
     96  1.1  thorpej 
     97  1.1  thorpej 	{ 0,			0,
     98  1.1  thorpej 	  NULL },
     99  1.1  thorpej };
    100  1.1  thorpej 
    101  1.1  thorpej /*
    102  1.1  thorpej  * Transmit descriptor list size.  This is arbitrary, but allocate
    103  1.1  thorpej  * enough descriptors for 64 pending transmissions, and 16 segments
    104  1.1  thorpej  * per packet.  This MUST work out to a power of 2.
    105  1.1  thorpej  */
    106  1.1  thorpej #define	SIP_NTXSEGS		16
    107  1.1  thorpej 
    108  1.1  thorpej #define	SIP_TXQUEUELEN		64
    109  1.1  thorpej #define	SIP_NTXDESC		(SIP_TXQUEUELEN * SIP_NTXSEGS)
    110  1.1  thorpej #define	SIP_NTXDESC_MASK	(SIP_NTXDESC - 1)
    111  1.1  thorpej #define	SIP_NEXTTX(x)		(((x) + 1) & SIP_NTXDESC_MASK)
    112  1.1  thorpej 
    113  1.1  thorpej /*
    114  1.1  thorpej  * Receive descriptor list size.  We have one Rx buffer per incoming
    115  1.1  thorpej  * packet, so this logic is a little simpler.
    116  1.1  thorpej  */
    117  1.1  thorpej #define	SIP_NRXDESC		64
    118  1.1  thorpej #define	SIP_NRXDESC_MASK	(SIP_NRXDESC - 1)
    119  1.1  thorpej #define	SIP_NEXTRX(x)		(((x) + 1) & SIP_NRXDESC_MASK)
    120  1.1  thorpej 
    121  1.1  thorpej /*
    122  1.1  thorpej  * Control structures are DMA'd to the SiS900 chip.  We allocate them in
    123  1.1  thorpej  * a single clump that maps to a single DMA segment to make several things
    124  1.1  thorpej  * easier.
    125  1.1  thorpej  */
    126  1.1  thorpej struct sip_control_data {
    127  1.1  thorpej 	/*
    128  1.1  thorpej 	 * The transmit descriptors.
    129  1.1  thorpej 	 */
    130  1.1  thorpej 	struct sip_desc scd_txdescs[SIP_NTXDESC];
    131  1.1  thorpej 
    132  1.1  thorpej 	/*
    133  1.1  thorpej 	 * The receive descriptors.
    134  1.1  thorpej 	 */
    135  1.1  thorpej 	struct sip_desc scd_rxdescs[SIP_NRXDESC];
    136  1.1  thorpej };
    137  1.1  thorpej 
    138  1.1  thorpej #define	SIP_CDOFF(x)	offsetof(struct sip_control_data, x)
    139  1.1  thorpej #define	SIP_CDTXOFF(x)	SIP_CDOFF(scd_txdescs[(x)])
    140  1.1  thorpej #define	SIP_CDRXOFF(x)	SIP_CDOFF(scd_rxdescs[(x)])
    141  1.1  thorpej 
    142  1.1  thorpej /*
    143  1.1  thorpej  * Software state for transmit jobs.
    144  1.1  thorpej  */
    145  1.1  thorpej struct sip_txsoft {
    146  1.1  thorpej 	struct mbuf *txs_mbuf;		/* head of our mbuf chain */
    147  1.1  thorpej 	bus_dmamap_t txs_dmamap;	/* our DMA map */
    148  1.1  thorpej 	int txs_firstdesc;		/* first descriptor in packet */
    149  1.1  thorpej 	int txs_lastdesc;		/* last descriptor in packet */
    150  1.1  thorpej 	SIMPLEQ_ENTRY(sip_txsoft) txs_q;
    151  1.1  thorpej };
    152  1.1  thorpej 
    153  1.1  thorpej SIMPLEQ_HEAD(sip_txsq, sip_txsoft);
    154  1.1  thorpej 
    155  1.1  thorpej /*
    156  1.1  thorpej  * Software state for receive jobs.
    157  1.1  thorpej  */
    158  1.1  thorpej struct sip_rxsoft {
    159  1.1  thorpej 	struct mbuf *rxs_mbuf;		/* head of our mbuf chain */
    160  1.1  thorpej 	bus_dmamap_t rxs_dmamap;	/* our DMA map */
    161  1.1  thorpej };
    162  1.1  thorpej 
    163  1.1  thorpej /*
    164  1.1  thorpej  * Software state per device.
    165  1.1  thorpej  */
    166  1.1  thorpej struct sip_softc {
    167  1.1  thorpej 	struct device sc_dev;		/* generic device information */
    168  1.1  thorpej 	bus_space_tag_t sc_st;		/* bus space tag */
    169  1.1  thorpej 	bus_space_handle_t sc_sh;	/* bus space handle */
    170  1.1  thorpej 	bus_dma_tag_t sc_dmat;		/* bus DMA tag */
    171  1.1  thorpej 	struct ethercom sc_ethercom;	/* ethernet common data */
    172  1.1  thorpej 	void *sc_sdhook;		/* shutdown hook */
    173  1.1  thorpej 
    174  1.1  thorpej 	void *sc_ih;			/* interrupt cookie */
    175  1.1  thorpej 
    176  1.1  thorpej 	struct mii_data sc_mii;		/* MII/media information */
    177  1.1  thorpej 
    178  1.1  thorpej 	bus_dmamap_t sc_cddmamap;	/* control data DMA map */
    179  1.1  thorpej #define	sc_cddma	sc_cddmamap->dm_segs[0].ds_addr
    180  1.1  thorpej 
    181  1.1  thorpej 	/*
    182  1.1  thorpej 	 * Software state for transmit and receive descriptors.
    183  1.1  thorpej 	 */
    184  1.1  thorpej 	struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN];
    185  1.1  thorpej 	struct sip_rxsoft sc_rxsoft[SIP_NRXDESC];
    186  1.1  thorpej 
    187  1.1  thorpej 	/*
    188  1.1  thorpej 	 * Control data structures.
    189  1.1  thorpej 	 */
    190  1.1  thorpej 	struct sip_control_data *sc_control_data;
    191  1.1  thorpej #define	sc_txdescs	sc_control_data->scd_txdescs
    192  1.1  thorpej #define	sc_rxdescs	sc_control_data->scd_rxdescs
    193  1.1  thorpej 
    194  1.1  thorpej 	u_int32_t sc_txcfg;		/* prototype TXCFG register */
    195  1.1  thorpej 	u_int32_t sc_rxcfg;		/* prototype RXCFG register */
    196  1.1  thorpej 	u_int32_t sc_imr;		/* prototype IMR register */
    197  1.1  thorpej 	u_int32_t sc_rfcr;		/* prototype RFCR register */
    198  1.1  thorpej 
    199  1.1  thorpej 	u_int32_t sc_tx_fill_thresh;	/* transmit fill threshold */
    200  1.1  thorpej 	u_int32_t sc_tx_drain_thresh;	/* transmit drain threshold */
    201  1.1  thorpej 
    202  1.1  thorpej 	u_int32_t sc_rx_drain_thresh;	/* receive drain threshold */
    203  1.1  thorpej 
    204  1.1  thorpej 	int	sc_flags;		/* misc. flags; see below */
    205  1.1  thorpej 
    206  1.1  thorpej 	int	sc_txfree;		/* number of free Tx descriptors */
    207  1.1  thorpej 	int	sc_txnext;		/* next ready Tx descriptor */
    208  1.1  thorpej 
    209  1.1  thorpej 	struct sip_txsq sc_txfreeq;	/* free Tx descsofts */
    210  1.1  thorpej 	struct sip_txsq sc_txdirtyq;	/* dirty Tx descsofts */
    211  1.1  thorpej 
    212  1.1  thorpej 	int	sc_rxptr;		/* next ready Rx descriptor/descsoft */
    213  1.1  thorpej };
    214  1.1  thorpej 
    215  1.1  thorpej /* sc_flags */
    216  1.1  thorpej #define	SIPF_PAUSED	0x00000001	/* paused (802.3x flow control) */
    217  1.1  thorpej 
    218  1.1  thorpej #define	SIP_CDTXADDR(sc, x)	((sc)->sc_cddma + SIP_CDTXOFF((x)))
    219  1.1  thorpej #define	SIP_CDRXADDR(sc, x)	((sc)->sc_cddma + SIP_CDRXOFF((x)))
    220  1.1  thorpej 
    221  1.1  thorpej #define	SIP_CDTXSYNC(sc, x, n, ops)					\
    222  1.1  thorpej do {									\
    223  1.1  thorpej 	int __x, __n;							\
    224  1.1  thorpej 									\
    225  1.1  thorpej 	__x = (x);							\
    226  1.1  thorpej 	__n = (n);							\
    227  1.1  thorpej 									\
    228  1.1  thorpej 	/* If it will wrap around, sync to the end of the ring. */	\
    229  1.1  thorpej 	if ((__x + __n) > SIP_NTXDESC) {				\
    230  1.1  thorpej 		bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,	\
    231  1.1  thorpej 		    SIP_CDTXOFF(__x), sizeof(struct sip_desc) *		\
    232  1.1  thorpej 		    (SIP_NTXDESC - __x), (ops));			\
    233  1.1  thorpej 		__n -= (SIP_NTXDESC - __x);				\
    234  1.1  thorpej 		__x = 0;						\
    235  1.1  thorpej 	}								\
    236  1.1  thorpej 									\
    237  1.1  thorpej 	/* Now sync whatever is left. */				\
    238  1.1  thorpej 	bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,		\
    239  1.1  thorpej 	    SIP_CDTXOFF(__x), sizeof(struct sip_desc) * __n, (ops));	\
    240  1.1  thorpej } while (0)
    241  1.1  thorpej 
    242  1.1  thorpej #define	SIP_CDRXSYNC(sc, x, ops)					\
    243  1.1  thorpej 	bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,		\
    244  1.1  thorpej 	    SIP_CDRXOFF((x)), sizeof(struct sip_desc), (ops))
    245  1.1  thorpej 
    246  1.1  thorpej /*
    247  1.1  thorpej  * Note we rely on MCLBYTES being a power of two below.
    248  1.1  thorpej  */
    249  1.1  thorpej #define	SIP_INIT_RXDESC(sc, x)						\
    250  1.1  thorpej do {									\
    251  1.1  thorpej 	struct sip_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)];		\
    252  1.1  thorpej 	struct sip_desc *__sipd = &(sc)->sc_rxdescs[(x)];		\
    253  1.1  thorpej 									\
    254  1.1  thorpej 	__sipd->sipd_link = SIP_CDRXADDR((sc), SIP_NEXTRX((x)));	\
    255  1.1  thorpej 	__sipd->sipd_bufptr = __rxs->rxs_dmamap->dm_segs[0].ds_addr;	\
    256  1.1  thorpej 	__sipd->sipd_cmdsts = CMDSTS_INTR |				\
    257  1.1  thorpej 	    ((MCLBYTES - 1) & CMDSTS_SIZE_MASK);			\
    258  1.1  thorpej 	SIP_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
    259  1.1  thorpej } while (0)
    260  1.1  thorpej 
    261  1.1  thorpej void	sip_start __P((struct ifnet *));
    262  1.1  thorpej void	sip_watchdog __P((struct ifnet *));
    263  1.1  thorpej int	sip_ioctl __P((struct ifnet *, u_long, caddr_t));
    264  1.1  thorpej 
    265  1.1  thorpej void	sip_shutdown __P((void *));
    266  1.1  thorpej 
    267  1.1  thorpej void	sip_reset __P((struct sip_softc *));
    268  1.2  thorpej int	sip_init __P((struct sip_softc *));
    269  1.2  thorpej void	sip_stop __P((struct sip_softc *, int));
    270  1.2  thorpej void	sip_rxdrain __P((struct sip_softc *));
    271  1.1  thorpej int	sip_add_rxbuf __P((struct sip_softc *, int));
    272  1.1  thorpej void	sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
    273  1.1  thorpej void	sip_set_filter __P((struct sip_softc *));
    274  1.1  thorpej void	sip_tick __P((void *));
    275  1.1  thorpej 
    276  1.1  thorpej int	sip_intr __P((void *));
    277  1.1  thorpej void	sip_txintr __P((struct sip_softc *));
    278  1.1  thorpej void	sip_rxintr __P((struct sip_softc *));
    279  1.1  thorpej 
    280  1.1  thorpej int	sip_mii_readreg __P((struct device *, int, int));
    281  1.1  thorpej void	sip_mii_writereg __P((struct device *, int, int, int));
    282  1.1  thorpej void	sip_mii_statchg __P((struct device *));
    283  1.1  thorpej 
    284  1.1  thorpej int	sip_mediachange __P((struct ifnet *));
    285  1.1  thorpej void	sip_mediastatus __P((struct ifnet *, struct ifmediareq *));
    286  1.1  thorpej 
    287  1.1  thorpej int	sip_match __P((struct device *, struct cfdata *, void *));
    288  1.1  thorpej void	sip_attach __P((struct device *, struct device *, void *));
    289  1.1  thorpej 
    290  1.2  thorpej int	sip_copy_small = 0;
    291  1.2  thorpej 
    292  1.1  thorpej struct cfattach sip_ca = {
    293  1.1  thorpej 	sizeof(struct sip_softc), sip_match, sip_attach,
    294  1.1  thorpej };
    295  1.1  thorpej 
    296  1.1  thorpej const struct sip_product *sip_lookup __P((const struct pci_attach_args *));
    297  1.1  thorpej 
    298  1.1  thorpej const struct sip_product *
    299  1.1  thorpej sip_lookup(pa)
    300  1.1  thorpej 	const struct pci_attach_args *pa;
    301  1.1  thorpej {
    302  1.1  thorpej 	const struct sip_product *sip;
    303  1.1  thorpej 
    304  1.1  thorpej 	for (sip = sip_products; sip->sip_name != NULL; sip++) {
    305  1.1  thorpej 		if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor &&
    306  1.1  thorpej 		    PCI_PRODUCT(pa->pa_id) == sip->sip_product)
    307  1.1  thorpej 			return (sip);
    308  1.1  thorpej 	}
    309  1.1  thorpej 	return (NULL);
    310  1.1  thorpej }
    311  1.1  thorpej 
    312  1.1  thorpej int
    313  1.1  thorpej sip_match(parent, cf, aux)
    314  1.1  thorpej 	struct device *parent;
    315  1.1  thorpej 	struct cfdata *cf;
    316  1.1  thorpej 	void *aux;
    317  1.1  thorpej {
    318  1.1  thorpej 	struct pci_attach_args *pa = aux;
    319  1.1  thorpej 
    320  1.1  thorpej 	if (sip_lookup(pa) != NULL)
    321  1.1  thorpej 		return (1);
    322  1.1  thorpej 
    323  1.1  thorpej 	return (0);
    324  1.1  thorpej }
    325  1.1  thorpej 
    326  1.1  thorpej void
    327  1.1  thorpej sip_attach(parent, self, aux)
    328  1.1  thorpej 	struct device *parent, *self;
    329  1.1  thorpej 	void *aux;
    330  1.1  thorpej {
    331  1.1  thorpej 	struct sip_softc *sc = (struct sip_softc *) self;
    332  1.1  thorpej 	struct pci_attach_args *pa = aux;
    333  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    334  1.1  thorpej 	pci_chipset_tag_t pc = pa->pa_pc;
    335  1.1  thorpej 	pci_intr_handle_t ih;
    336  1.1  thorpej 	const char *intrstr = NULL;
    337  1.1  thorpej 	bus_space_tag_t iot, memt;
    338  1.1  thorpej 	bus_space_handle_t ioh, memh;
    339  1.1  thorpej 	bus_dma_segment_t seg;
    340  1.1  thorpej 	int ioh_valid, memh_valid;
    341  1.1  thorpej 	int i, rseg, error;
    342  1.1  thorpej 	const struct sip_product *sip;
    343  1.1  thorpej 	pcireg_t pmode;
    344  1.1  thorpej 	u_int16_t enaddr[ETHER_ADDR_LEN / 2];
    345  1.1  thorpej 
    346  1.1  thorpej 	sip = sip_lookup(pa);
    347  1.1  thorpej 	if (sip == NULL) {
    348  1.1  thorpej 		printf("\n");
    349  1.1  thorpej 		panic("sip_attach: impossible");
    350  1.1  thorpej 	}
    351  1.1  thorpej 
    352  1.1  thorpej 	printf(": %s\n", sip->sip_name);
    353  1.1  thorpej 
    354  1.1  thorpej 	/*
    355  1.1  thorpej 	 * Map the device.
    356  1.1  thorpej 	 */
    357  1.1  thorpej 	ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA,
    358  1.1  thorpej 	    PCI_MAPREG_TYPE_IO, 0,
    359  1.1  thorpej 	    &iot, &ioh, NULL, NULL) == 0);
    360  1.1  thorpej 	memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA,
    361  1.1  thorpej 	    PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0,
    362  1.1  thorpej 	    &memt, &memh, NULL, NULL) == 0);
    363  1.1  thorpej 
    364  1.1  thorpej 	if (memh_valid) {
    365  1.1  thorpej 		sc->sc_st = memt;
    366  1.1  thorpej 		sc->sc_sh = memh;
    367  1.1  thorpej 	} else if (ioh_valid) {
    368  1.1  thorpej 		sc->sc_st = iot;
    369  1.1  thorpej 		sc->sc_sh = ioh;
    370  1.1  thorpej 	} else {
    371  1.1  thorpej 		printf("%s: unable to map device registers\n",
    372  1.1  thorpej 		    sc->sc_dev.dv_xname);
    373  1.1  thorpej 		return;
    374  1.1  thorpej 	}
    375  1.1  thorpej 
    376  1.1  thorpej 	sc->sc_dmat = pa->pa_dmat;
    377  1.1  thorpej 
    378  1.1  thorpej 	/* Enable bus mastering. */
    379  1.1  thorpej 	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
    380  1.1  thorpej 	    pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
    381  1.1  thorpej 	    PCI_COMMAND_MASTER_ENABLE);
    382  1.1  thorpej 
    383  1.1  thorpej 	/* Get it out of power save mode if needed. */
    384  1.1  thorpej 	if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, 0, 0)) {
    385  1.1  thorpej 		pmode = pci_conf_read(pc, pa->pa_tag, SIP_PCI_CFGPMCSR) & 0x3;
    386  1.1  thorpej 		if (pmode == 3) {
    387  1.1  thorpej 			/*
    388  1.1  thorpej 			 * The card has lost all configuration data in
    389  1.1  thorpej 			 * this state, so punt.
    390  1.1  thorpej 			 */
    391  1.1  thorpej 			printf("%s: unable to wake up from power state D3\n",
    392  1.1  thorpej 			    sc->sc_dev.dv_xname);
    393  1.1  thorpej 			return;
    394  1.1  thorpej 		}
    395  1.1  thorpej 		if (pmode != 0) {
    396  1.1  thorpej 			printf("%s: waking up from power state D%d\n",
    397  1.1  thorpej 			    sc->sc_dev.dv_xname, pmode);
    398  1.1  thorpej 			pci_conf_write(pc, pa->pa_tag, SIP_PCI_CFGPMCSR, 0);
    399  1.1  thorpej 		}
    400  1.1  thorpej 	}
    401  1.1  thorpej 
    402  1.1  thorpej 	/*
    403  1.1  thorpej 	 * Map and establish our interrupt.
    404  1.1  thorpej 	 */
    405  1.1  thorpej 	if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
    406  1.1  thorpej 	    pa->pa_intrline, &ih)) {
    407  1.1  thorpej 		printf("%s: unable to map interrupt\n", sc->sc_dev.dv_xname);
    408  1.1  thorpej 		return;
    409  1.1  thorpej 	}
    410  1.1  thorpej 	intrstr = pci_intr_string(pc, ih);
    411  1.1  thorpej 	sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sip_intr, sc);
    412  1.1  thorpej 	if (sc->sc_ih == NULL) {
    413  1.1  thorpej 		printf("%s: unable to establish interrupt",
    414  1.1  thorpej 		    sc->sc_dev.dv_xname);
    415  1.1  thorpej 		if (intrstr != NULL)
    416  1.1  thorpej 			printf(" at %s", intrstr);
    417  1.1  thorpej 		printf("\n");
    418  1.1  thorpej 		return;
    419  1.1  thorpej 	}
    420  1.1  thorpej 	printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
    421  1.1  thorpej 
    422  1.1  thorpej 	SIMPLEQ_INIT(&sc->sc_txfreeq);
    423  1.1  thorpej 	SIMPLEQ_INIT(&sc->sc_txdirtyq);
    424  1.1  thorpej 
    425  1.1  thorpej 	/*
    426  1.1  thorpej 	 * Allocate the control data structures, and create and load the
    427  1.1  thorpej 	 * DMA map for it.
    428  1.1  thorpej 	 */
    429  1.1  thorpej 	if ((error = bus_dmamem_alloc(sc->sc_dmat,
    430  1.1  thorpej 	    sizeof(struct sip_control_data), PAGE_SIZE, 0, &seg, 1, &rseg,
    431  1.1  thorpej 	    0)) != 0) {
    432  1.1  thorpej 		printf("%s: unable to allocate control data, error = %d\n",
    433  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    434  1.1  thorpej 		goto fail_0;
    435  1.1  thorpej 	}
    436  1.1  thorpej 
    437  1.1  thorpej 	if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
    438  1.1  thorpej 	    sizeof(struct sip_control_data), (caddr_t *)&sc->sc_control_data,
    439  1.1  thorpej 	    BUS_DMA_COHERENT)) != 0) {
    440  1.1  thorpej 		printf("%s: unable to map control data, error = %d\n",
    441  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    442  1.1  thorpej 		goto fail_1;
    443  1.1  thorpej 	}
    444  1.1  thorpej 
    445  1.1  thorpej 	if ((error = bus_dmamap_create(sc->sc_dmat,
    446  1.1  thorpej 	    sizeof(struct sip_control_data), 1,
    447  1.1  thorpej 	    sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
    448  1.1  thorpej 		printf("%s: unable to create control data DMA map, "
    449  1.1  thorpej 		    "error = %d\n", sc->sc_dev.dv_xname, error);
    450  1.1  thorpej 		goto fail_2;
    451  1.1  thorpej 	}
    452  1.1  thorpej 
    453  1.1  thorpej 	if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
    454  1.1  thorpej 	    sc->sc_control_data, sizeof(struct sip_control_data), NULL,
    455  1.1  thorpej 	    0)) != 0) {
    456  1.1  thorpej 		printf("%s: unable to load control data DMA map, error = %d\n",
    457  1.1  thorpej 		    sc->sc_dev.dv_xname, error);
    458  1.1  thorpej 		goto fail_3;
    459  1.1  thorpej 	}
    460  1.1  thorpej 
    461  1.1  thorpej 	/*
    462  1.1  thorpej 	 * Create the transmit buffer DMA maps.
    463  1.1  thorpej 	 */
    464  1.1  thorpej 	for (i = 0; i < SIP_TXQUEUELEN; i++) {
    465  1.1  thorpej 		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
    466  1.1  thorpej 		    SIP_NTXSEGS, MCLBYTES, 0, 0,
    467  1.1  thorpej 		    &sc->sc_txsoft[i].txs_dmamap)) != 0) {
    468  1.1  thorpej 			printf("%s: unable to create tx DMA map %d, "
    469  1.1  thorpej 			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
    470  1.1  thorpej 			goto fail_4;
    471  1.1  thorpej 		}
    472  1.1  thorpej 	}
    473  1.1  thorpej 
    474  1.1  thorpej 	/*
    475  1.1  thorpej 	 * Create the receive buffer DMA maps.
    476  1.1  thorpej 	 */
    477  1.1  thorpej 	for (i = 0; i < SIP_NRXDESC; i++) {
    478  1.1  thorpej 		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
    479  1.1  thorpej 		    MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
    480  1.1  thorpej 			printf("%s: unable to create rx DMA map %d, "
    481  1.1  thorpej 			    "error = %d\n", sc->sc_dev.dv_xname, i, error);
    482  1.1  thorpej 			goto fail_5;
    483  1.1  thorpej 		}
    484  1.2  thorpej 		sc->sc_rxsoft[i].rxs_mbuf = NULL;
    485  1.1  thorpej 	}
    486  1.1  thorpej 
    487  1.1  thorpej 	/*
    488  1.1  thorpej 	 * Reset the chip to a known state.
    489  1.1  thorpej 	 */
    490  1.1  thorpej 	sip_reset(sc);
    491  1.1  thorpej 
    492  1.1  thorpej 	/*
    493  1.1  thorpej 	 * Read the Ethernet address from the EEPROM.
    494  1.1  thorpej 	 */
    495  1.1  thorpej 	sip_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
    496  1.1  thorpej 	    sizeof(enaddr) / sizeof(enaddr[0]), enaddr);
    497  1.1  thorpej 
    498  1.1  thorpej 	printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
    499  1.1  thorpej 	    ether_sprintf((u_int8_t *)enaddr));
    500  1.1  thorpej 
    501  1.1  thorpej 	/*
    502  1.1  thorpej 	 * Initialize our media structures and probe the MII.
    503  1.1  thorpej 	 */
    504  1.1  thorpej 	sc->sc_mii.mii_ifp = ifp;
    505  1.1  thorpej 	sc->sc_mii.mii_readreg = sip_mii_readreg;
    506  1.1  thorpej 	sc->sc_mii.mii_writereg = sip_mii_writereg;
    507  1.1  thorpej 	sc->sc_mii.mii_statchg = sip_mii_statchg;
    508  1.1  thorpej 	ifmedia_init(&sc->sc_mii.mii_media, 0, sip_mediachange,
    509  1.1  thorpej 	    sip_mediastatus);
    510  1.3  thorpej 	mii_phy_probe(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
    511  1.3  thorpej 	    MII_OFFSET_ANY);
    512  1.1  thorpej 	if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
    513  1.1  thorpej 		ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
    514  1.1  thorpej 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
    515  1.1  thorpej 	} else
    516  1.1  thorpej 		ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
    517  1.1  thorpej 
    518  1.1  thorpej 	ifp = &sc->sc_ethercom.ec_if;
    519  1.1  thorpej 	strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
    520  1.1  thorpej 	ifp->if_softc = sc;
    521  1.1  thorpej 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    522  1.1  thorpej 	ifp->if_ioctl = sip_ioctl;
    523  1.1  thorpej 	ifp->if_start = sip_start;
    524  1.1  thorpej 	ifp->if_watchdog = sip_watchdog;
    525  1.1  thorpej 
    526  1.1  thorpej 	/*
    527  1.1  thorpej 	 * Attach the interface.
    528  1.1  thorpej 	 */
    529  1.1  thorpej 	if_attach(ifp);
    530  1.1  thorpej 	ether_ifattach(ifp, (u_int8_t *)enaddr);
    531  1.1  thorpej #if NBPFILTER > 0
    532  1.1  thorpej 	bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
    533  1.1  thorpej 	    sizeof(struct ether_header));
    534  1.1  thorpej #endif
    535  1.1  thorpej 
    536  1.1  thorpej 	/*
    537  1.1  thorpej 	 * Make sure the interface is shutdown during reboot.
    538  1.1  thorpej 	 */
    539  1.1  thorpej 	sc->sc_sdhook = shutdownhook_establish(sip_shutdown, sc);
    540  1.1  thorpej 	if (sc->sc_sdhook == NULL)
    541  1.1  thorpej 		printf("%s: WARNING: unable to establish shutdown hook\n",
    542  1.1  thorpej 		    sc->sc_dev.dv_xname);
    543  1.1  thorpej 	return;
    544  1.1  thorpej 
    545  1.1  thorpej 	/*
    546  1.1  thorpej 	 * Free any resources we've allocated during the failed attach
    547  1.1  thorpej 	 * attempt.  Do this in reverse order and fall through.
    548  1.1  thorpej 	 */
    549  1.1  thorpej  fail_5:
    550  1.1  thorpej 	for (i = 0; i < SIP_NRXDESC; i++) {
    551  1.1  thorpej 		if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
    552  1.1  thorpej 			bus_dmamap_destroy(sc->sc_dmat,
    553  1.1  thorpej 			    sc->sc_rxsoft[i].rxs_dmamap);
    554  1.1  thorpej 	}
    555  1.1  thorpej  fail_4:
    556  1.1  thorpej 	for (i = 0; i < SIP_TXQUEUELEN; i++) {
    557  1.1  thorpej 		if (sc->sc_txsoft[i].txs_dmamap != NULL)
    558  1.1  thorpej 			bus_dmamap_destroy(sc->sc_dmat,
    559  1.1  thorpej 			    sc->sc_txsoft[i].txs_dmamap);
    560  1.1  thorpej 	}
    561  1.1  thorpej 	bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
    562  1.1  thorpej  fail_3:
    563  1.1  thorpej 	bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
    564  1.1  thorpej  fail_2:
    565  1.1  thorpej 	bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
    566  1.1  thorpej 	    sizeof(struct sip_control_data));
    567  1.1  thorpej  fail_1:
    568  1.1  thorpej 	bus_dmamem_free(sc->sc_dmat, &seg, rseg);
    569  1.1  thorpej  fail_0:
    570  1.1  thorpej 	return;
    571  1.1  thorpej }
    572  1.1  thorpej 
    573  1.1  thorpej /*
    574  1.1  thorpej  * sip_shutdown:
    575  1.1  thorpej  *
    576  1.1  thorpej  *	Make sure the interface is stopped at reboot time.
    577  1.1  thorpej  */
    578  1.1  thorpej void
    579  1.1  thorpej sip_shutdown(arg)
    580  1.1  thorpej 	void *arg;
    581  1.1  thorpej {
    582  1.1  thorpej 	struct sip_softc *sc = arg;
    583  1.1  thorpej 
    584  1.2  thorpej 	sip_stop(sc, 1);
    585  1.1  thorpej }
    586  1.1  thorpej 
    587  1.1  thorpej /*
    588  1.1  thorpej  * sip_start:		[ifnet interface function]
    589  1.1  thorpej  *
    590  1.1  thorpej  *	Start packet transmission on the interface.
    591  1.1  thorpej  */
    592  1.1  thorpej void
    593  1.1  thorpej sip_start(ifp)
    594  1.1  thorpej 	struct ifnet *ifp;
    595  1.1  thorpej {
    596  1.1  thorpej 	struct sip_softc *sc = ifp->if_softc;
    597  1.1  thorpej 	struct mbuf *m0, *m;
    598  1.1  thorpej 	struct sip_txsoft *txs;
    599  1.1  thorpej 	bus_dmamap_t dmamap;
    600  1.1  thorpej 	int error, firsttx, nexttx, lasttx, ofree, seg;
    601  1.1  thorpej 
    602  1.1  thorpej 	/*
    603  1.1  thorpej 	 * If we've been told to pause, don't transmit any more packets.
    604  1.1  thorpej 	 */
    605  1.1  thorpej 	if (sc->sc_flags & SIPF_PAUSED)
    606  1.1  thorpej 		ifp->if_flags |= IFF_OACTIVE;
    607  1.1  thorpej 
    608  1.1  thorpej 	if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
    609  1.1  thorpej 		return;
    610  1.1  thorpej 
    611  1.1  thorpej 	/*
    612  1.1  thorpej 	 * Remember the previous number of free descriptors and
    613  1.1  thorpej 	 * the first descriptor we'll use.
    614  1.1  thorpej 	 */
    615  1.1  thorpej 	ofree = sc->sc_txfree;
    616  1.1  thorpej 	firsttx = sc->sc_txnext;
    617  1.1  thorpej 
    618  1.1  thorpej 	/*
    619  1.1  thorpej 	 * Loop through the send queue, setting up transmit descriptors
    620  1.1  thorpej 	 * until we drain the queue, or use up all available transmit
    621  1.1  thorpej 	 * descriptors.
    622  1.1  thorpej 	 */
    623  1.1  thorpej 	while ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) != NULL &&
    624  1.1  thorpej 	       sc->sc_txfree != 0) {
    625  1.1  thorpej 		/*
    626  1.1  thorpej 		 * Grab a packet off the queue.
    627  1.1  thorpej 		 */
    628  1.1  thorpej 		IF_DEQUEUE(&ifp->if_snd, m0);
    629  1.1  thorpej 		if (m0 == NULL)
    630  1.1  thorpej 			break;
    631  1.1  thorpej 
    632  1.1  thorpej 		dmamap = txs->txs_dmamap;
    633  1.1  thorpej 
    634  1.1  thorpej 		/*
    635  1.1  thorpej 		 * Load the DMA map.  If this fails, the packet either
    636  1.1  thorpej 		 * didn't fit in the alloted number of segments, or we
    637  1.1  thorpej 		 * were short on resources.  In this case, we'll copy
    638  1.1  thorpej 		 * and try again.
    639  1.1  thorpej 		 */
    640  1.1  thorpej 		if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
    641  1.1  thorpej 		    BUS_DMA_NOWAIT) != 0) {
    642  1.1  thorpej 			MGETHDR(m, M_DONTWAIT, MT_DATA);
    643  1.1  thorpej 			if (m == NULL) {
    644  1.1  thorpej 				printf("%s: unable to allocate Tx mbuf\n",
    645  1.1  thorpej 				    sc->sc_dev.dv_xname);
    646  1.1  thorpej 				IF_PREPEND(&ifp->if_snd, m0);
    647  1.1  thorpej 				break;
    648  1.1  thorpej 			}
    649  1.1  thorpej 			if (m0->m_pkthdr.len > MHLEN) {
    650  1.1  thorpej 				MCLGET(m, M_DONTWAIT);
    651  1.1  thorpej 				if ((m->m_flags & M_EXT) == 0) {
    652  1.1  thorpej 					printf("%s: unable to allocate Tx "
    653  1.1  thorpej 					    "cluster\n", sc->sc_dev.dv_xname);
    654  1.1  thorpej 					m_freem(m);
    655  1.1  thorpej 					IF_PREPEND(&ifp->if_snd, m0);
    656  1.1  thorpej 					break;
    657  1.1  thorpej 				}
    658  1.1  thorpej 			}
    659  1.1  thorpej 			m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
    660  1.1  thorpej 			m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
    661  1.1  thorpej 			m_freem(m0);
    662  1.1  thorpej 			m0 = m;
    663  1.1  thorpej 			error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
    664  1.1  thorpej 			    m0, BUS_DMA_NOWAIT);
    665  1.1  thorpej 			if (error) {
    666  1.1  thorpej 				printf("%s: unable to load Tx buffer, "
    667  1.1  thorpej 				    "error = %d\n", sc->sc_dev.dv_xname, error);
    668  1.1  thorpej 				IF_PREPEND(&ifp->if_snd, m0);
    669  1.1  thorpej 				break;
    670  1.1  thorpej 			}
    671  1.1  thorpej 		}
    672  1.1  thorpej 
    673  1.1  thorpej 		/*
    674  1.1  thorpej 		 * Ensure we have enough descriptors free to describe
    675  1.1  thorpej 		 * the packet.
    676  1.1  thorpej 		 */
    677  1.1  thorpej 		if (dmamap->dm_nsegs > sc->sc_txfree) {
    678  1.1  thorpej 			/*
    679  1.1  thorpej 			 * Not enough free descriptors to transmit this
    680  1.1  thorpej 			 * packet.  We haven't committed anything yet,
    681  1.1  thorpej 			 * so just unload the DMA map, put the packet
    682  1.1  thorpej 			 * back on the queue, and punt.  Notify the upper
    683  1.1  thorpej 			 * layer that there are not more slots left.
    684  1.1  thorpej 			 *
    685  1.1  thorpej 			 * XXX We could allocate an mbuf and copy, but
    686  1.1  thorpej 			 * XXX is it worth it?
    687  1.1  thorpej 			 */
    688  1.1  thorpej 			ifp->if_flags |= IFF_OACTIVE;
    689  1.1  thorpej 			bus_dmamap_unload(sc->sc_dmat, dmamap);
    690  1.1  thorpej 			IF_PREPEND(&ifp->if_snd, m0);
    691  1.1  thorpej 			break;
    692  1.1  thorpej 		}
    693  1.1  thorpej 
    694  1.1  thorpej 		/*
    695  1.1  thorpej 		 * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
    696  1.1  thorpej 		 */
    697  1.1  thorpej 
    698  1.1  thorpej 		/* Sync the DMA map. */
    699  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
    700  1.1  thorpej 		    BUS_DMASYNC_PREWRITE);
    701  1.1  thorpej 
    702  1.1  thorpej 		/*
    703  1.1  thorpej 		 * Initialize the transmit descriptors.
    704  1.1  thorpej 		 */
    705  1.1  thorpej 		for (nexttx = sc->sc_txnext, seg = 0;
    706  1.1  thorpej 		     seg < dmamap->dm_nsegs;
    707  1.1  thorpej 		     seg++, nexttx = SIP_NEXTTX(nexttx)) {
    708  1.1  thorpej 			/*
    709  1.1  thorpej 			 * If this is the first descriptor we're
    710  1.1  thorpej 			 * enqueueing, don't set the OWN bit just
    711  1.1  thorpej 			 * yet.  That could cause a race condition.
    712  1.1  thorpej 			 * We'll do it below.
    713  1.1  thorpej 			 */
    714  1.1  thorpej 			sc->sc_txdescs[nexttx].sipd_bufptr =
    715  1.1  thorpej 			    dmamap->dm_segs[seg].ds_addr;
    716  1.1  thorpej 			sc->sc_txdescs[nexttx].sipd_cmdsts =
    717  1.1  thorpej 			    (nexttx == firsttx ? 0 : CMDSTS_OWN) |
    718  1.1  thorpej 			    CMDSTS_MORE | dmamap->dm_segs[seg].ds_len;
    719  1.1  thorpej 			lasttx = nexttx;
    720  1.1  thorpej 		}
    721  1.1  thorpej 
    722  1.1  thorpej 		/* Clear the MORE bit on the last segment. */
    723  1.1  thorpej 		sc->sc_txdescs[lasttx].sipd_cmdsts &= ~CMDSTS_MORE;
    724  1.1  thorpej 
    725  1.1  thorpej 		/* Sync the descriptors we're using. */
    726  1.1  thorpej 		SIP_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs,
    727  1.1  thorpej 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    728  1.1  thorpej 
    729  1.1  thorpej 		/*
    730  1.1  thorpej 		 * Store a pointer to the packet so we can free it later,
    731  1.1  thorpej 		 * and remember what txdirty will be once the packet is
    732  1.1  thorpej 		 * done.
    733  1.1  thorpej 		 */
    734  1.1  thorpej 		txs->txs_mbuf = m0;
    735  1.1  thorpej 		txs->txs_firstdesc = sc->sc_txnext;
    736  1.1  thorpej 		txs->txs_lastdesc = lasttx;
    737  1.1  thorpej 
    738  1.1  thorpej 		/* Advance the tx pointer. */
    739  1.1  thorpej 		sc->sc_txfree -= dmamap->dm_nsegs;
    740  1.1  thorpej 		sc->sc_txnext = nexttx;
    741  1.1  thorpej 
    742  1.1  thorpej 		SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs, txs_q);
    743  1.1  thorpej 		SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
    744  1.1  thorpej 
    745  1.1  thorpej #if NBPFILTER > 0
    746  1.1  thorpej 		/*
    747  1.1  thorpej 		 * Pass the packet to any BPF listeners.
    748  1.1  thorpej 		 */
    749  1.1  thorpej 		if (ifp->if_bpf)
    750  1.1  thorpej 			bpf_mtap(ifp->if_bpf, m0);
    751  1.1  thorpej #endif /* NBPFILTER > 0 */
    752  1.1  thorpej 	}
    753  1.1  thorpej 
    754  1.1  thorpej 	if (txs == NULL || sc->sc_txfree == 0) {
    755  1.1  thorpej 		/* No more slots left; notify upper layer. */
    756  1.1  thorpej 		ifp->if_flags |= IFF_OACTIVE;
    757  1.1  thorpej 	}
    758  1.1  thorpej 
    759  1.1  thorpej 	if (sc->sc_txfree != ofree) {
    760  1.1  thorpej 		/*
    761  1.1  thorpej 		 * Cause a descriptor interrupt to happen on the
    762  1.1  thorpej 		 * last packet we enqueued.
    763  1.1  thorpej 		 */
    764  1.1  thorpej 		sc->sc_txdescs[lasttx].sipd_cmdsts |= CMDSTS_INTR;
    765  1.1  thorpej 		SIP_CDTXSYNC(sc, lasttx, 1,
    766  1.1  thorpej 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    767  1.1  thorpej 
    768  1.1  thorpej 		/*
    769  1.1  thorpej 		 * The entire packet chain is set up.  Give the
    770  1.1  thorpej 		 * first descrptor to the chip now.
    771  1.1  thorpej 		 */
    772  1.1  thorpej 		sc->sc_txdescs[firsttx].sipd_cmdsts |= CMDSTS_OWN;
    773  1.1  thorpej 		SIP_CDTXSYNC(sc, firsttx, 1,
    774  1.1  thorpej 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    775  1.1  thorpej 
    776  1.1  thorpej 		/* Start the transmit process. */
    777  1.1  thorpej 		if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR) &
    778  1.1  thorpej 		     CR_TXE) == 0) {
    779  1.1  thorpej 			bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP,
    780  1.1  thorpej 			    SIP_CDTXADDR(sc, firsttx));
    781  1.1  thorpej 			bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE);
    782  1.1  thorpej 		}
    783  1.1  thorpej 
    784  1.1  thorpej 		/* Set a watchdog timer in case the chip flakes out. */
    785  1.1  thorpej 		ifp->if_timer = 5;
    786  1.1  thorpej 	}
    787  1.1  thorpej }
    788  1.1  thorpej 
    789  1.1  thorpej /*
    790  1.1  thorpej  * sip_watchdog:	[ifnet interface function]
    791  1.1  thorpej  *
    792  1.1  thorpej  *	Watchdog timer handler.
    793  1.1  thorpej  */
    794  1.1  thorpej void
    795  1.1  thorpej sip_watchdog(ifp)
    796  1.1  thorpej 	struct ifnet *ifp;
    797  1.1  thorpej {
    798  1.1  thorpej 	struct sip_softc *sc = ifp->if_softc;
    799  1.1  thorpej 
    800  1.1  thorpej 	/*
    801  1.1  thorpej 	 * The chip seems to ignore the CMDSTS_INTR bit sometimes!
    802  1.1  thorpej 	 * If we get a timeout, try and sweep up transmit descriptors.
    803  1.1  thorpej 	 * If we manage to sweep them all up, ignore the lack of
    804  1.1  thorpej 	 * interrupt.
    805  1.1  thorpej 	 */
    806  1.1  thorpej 	sip_txintr(sc);
    807  1.1  thorpej 
    808  1.1  thorpej 	if (sc->sc_txfree != SIP_NTXDESC) {
    809  1.1  thorpej 		printf("%s: device timeout\n", sc->sc_dev.dv_xname);
    810  1.1  thorpej 		ifp->if_oerrors++;
    811  1.1  thorpej 
    812  1.1  thorpej 		/* Reset the interface. */
    813  1.2  thorpej 		(void) sip_init(sc);
    814  1.1  thorpej 	} else if (ifp->if_flags & IFF_DEBUG)
    815  1.1  thorpej 		printf("%s: recovered from device timeout\n",
    816  1.1  thorpej 		    sc->sc_dev.dv_xname);
    817  1.1  thorpej 
    818  1.1  thorpej 	/* Try to get more packets going. */
    819  1.1  thorpej 	sip_start(ifp);
    820  1.1  thorpej }
    821  1.1  thorpej 
    822  1.1  thorpej /*
    823  1.1  thorpej  * sip_ioctl:		[ifnet interface function]
    824  1.1  thorpej  *
    825  1.1  thorpej  *	Handle control requests from the operator.
    826  1.1  thorpej  */
    827  1.1  thorpej int
    828  1.1  thorpej sip_ioctl(ifp, cmd, data)
    829  1.1  thorpej 	struct ifnet *ifp;
    830  1.1  thorpej 	u_long cmd;
    831  1.1  thorpej 	caddr_t data;
    832  1.1  thorpej {
    833  1.1  thorpej 	struct sip_softc *sc = ifp->if_softc;
    834  1.1  thorpej 	struct ifreq *ifr = (struct ifreq *)data;
    835  1.1  thorpej 	struct ifaddr *ifa = (struct ifaddr *)data;
    836  1.1  thorpej 	int s, error = 0;
    837  1.1  thorpej 
    838  1.1  thorpej 	s = splnet();
    839  1.1  thorpej 
    840  1.1  thorpej 	switch (cmd) {
    841  1.1  thorpej 	case SIOCSIFADDR:
    842  1.1  thorpej 		ifp->if_flags |= IFF_UP;
    843  1.1  thorpej 
    844  1.1  thorpej 		switch (ifa->ifa_addr->sa_family) {
    845  1.1  thorpej #ifdef INET
    846  1.1  thorpej 		case AF_INET:
    847  1.2  thorpej 			if ((error = sip_init(sc)) != 0)
    848  1.2  thorpej 				break;
    849  1.1  thorpej 			arp_ifinit(ifp, ifa);
    850  1.1  thorpej 			break;
    851  1.1  thorpej #endif /* INET */
    852  1.1  thorpej #ifdef NS
    853  1.1  thorpej 		case AF_NS:
    854  1.1  thorpej 		    {
    855  1.1  thorpej 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
    856  1.1  thorpej 
    857  1.1  thorpej 			if (ns_nullhost(*ina))
    858  1.1  thorpej 				ina->x_host = *(union ns_host *)
    859  1.1  thorpej 				    LLADDR(ifp->if_sadl);
    860  1.1  thorpej 			else
    861  1.1  thorpej 				memcpy(LLADDR(ifp->if_sadl),
    862  1.1  thorpej 				    ina->x_host.c_host, ifp->if_addrlen);
    863  1.2  thorpej 			error = sip_init(sc);
    864  1.1  thorpej 			break;
    865  1.1  thorpej 		    }
    866  1.1  thorpej #endif /* NS */
    867  1.1  thorpej 		default:
    868  1.2  thorpej 			error = sip_init(sc);
    869  1.1  thorpej 			break;
    870  1.1  thorpej 		}
    871  1.1  thorpej 		break;
    872  1.1  thorpej 
    873  1.1  thorpej 	case SIOCSIFMTU:
    874  1.1  thorpej 		if (ifr->ifr_mtu > ETHERMTU)
    875  1.1  thorpej 			error = EINVAL;
    876  1.1  thorpej 		else
    877  1.1  thorpej 			ifp->if_mtu = ifr->ifr_mtu;
    878  1.1  thorpej 		break;
    879  1.1  thorpej 
    880  1.1  thorpej 	case SIOCSIFFLAGS:
    881  1.1  thorpej 		if ((ifp->if_flags & IFF_UP) == 0 &&
    882  1.1  thorpej 		    (ifp->if_flags & IFF_RUNNING) != 0) {
    883  1.1  thorpej 			/*
    884  1.1  thorpej 			 * If interface is marked down and it is running, then
    885  1.1  thorpej 			 * stop it.
    886  1.1  thorpej 			 */
    887  1.2  thorpej 			sip_stop(sc, 1);
    888  1.1  thorpej 		} else if ((ifp->if_flags & IFF_UP) != 0 &&
    889  1.1  thorpej 			   (ifp->if_flags & IFF_RUNNING) == 0) {
    890  1.1  thorpej 			/*
    891  1.1  thorpej 			 * If interfase it marked up and it is stopped, then
    892  1.1  thorpej 			 * start it.
    893  1.1  thorpej 			 */
    894  1.2  thorpej 			error = sip_init(sc);
    895  1.1  thorpej 		} else if ((ifp->if_flags & IFF_UP) != 0) {
    896  1.1  thorpej 			/*
    897  1.1  thorpej 			 * Reset the interface to pick up changes in any other
    898  1.1  thorpej 			 * flags that affect the hardware state.
    899  1.1  thorpej 			 */
    900  1.2  thorpej 			error = sip_init(sc);
    901  1.1  thorpej 		}
    902  1.1  thorpej 		break;
    903  1.1  thorpej 
    904  1.1  thorpej 	case SIOCADDMULTI:
    905  1.1  thorpej 	case SIOCDELMULTI:
    906  1.1  thorpej 		error = (cmd == SIOCADDMULTI) ?
    907  1.1  thorpej 		    ether_addmulti(ifr, &sc->sc_ethercom) :
    908  1.1  thorpej 		    ether_delmulti(ifr, &sc->sc_ethercom);
    909  1.1  thorpej 
    910  1.1  thorpej 		if (error == ENETRESET) {
    911  1.1  thorpej 			/*
    912  1.1  thorpej 			 * Multicast list has changed; set the hardware filter
    913  1.1  thorpej 			 * accordingly.
    914  1.1  thorpej 			 */
    915  1.1  thorpej 			sip_set_filter(sc);
    916  1.1  thorpej 			error = 0;
    917  1.1  thorpej 		}
    918  1.1  thorpej 		break;
    919  1.1  thorpej 
    920  1.1  thorpej 	case SIOCSIFMEDIA:
    921  1.1  thorpej 	case SIOCGIFMEDIA:
    922  1.1  thorpej 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
    923  1.1  thorpej 		break;
    924  1.1  thorpej 
    925  1.1  thorpej 	default:
    926  1.1  thorpej 		error = EINVAL;
    927  1.1  thorpej 		break;
    928  1.1  thorpej 	}
    929  1.1  thorpej 
    930  1.1  thorpej 	/* Try to get more packets going. */
    931  1.1  thorpej 	sip_start(ifp);
    932  1.1  thorpej 
    933  1.1  thorpej 	splx(s);
    934  1.1  thorpej 	return (error);
    935  1.1  thorpej }
    936  1.1  thorpej 
    937  1.1  thorpej /*
    938  1.1  thorpej  * sip_intr:
    939  1.1  thorpej  *
    940  1.1  thorpej  *	Interrupt service routine.
    941  1.1  thorpej  */
    942  1.1  thorpej int
    943  1.1  thorpej sip_intr(arg)
    944  1.1  thorpej 	void *arg;
    945  1.1  thorpej {
    946  1.1  thorpej 	struct sip_softc *sc = arg;
    947  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
    948  1.1  thorpej 	u_int32_t isr;
    949  1.1  thorpej 	int handled = 0;
    950  1.1  thorpej 
    951  1.1  thorpej 	for (;;) {
    952  1.1  thorpej 		/* Reading clears interrupt. */
    953  1.1  thorpej 		isr = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ISR);
    954  1.1  thorpej 		if ((isr & sc->sc_imr) == 0)
    955  1.1  thorpej 			break;
    956  1.1  thorpej 
    957  1.1  thorpej 		handled = 1;
    958  1.1  thorpej 
    959  1.1  thorpej 		if (isr & (ISR_RXORN|ISR_RXIDLE|ISR_RXDESC)) {
    960  1.1  thorpej 			/* Grab any new packets. */
    961  1.1  thorpej 			sip_rxintr(sc);
    962  1.1  thorpej 
    963  1.1  thorpej 			if (isr & ISR_RXORN) {
    964  1.1  thorpej 				printf("%s: receive FIFO overrun\n",
    965  1.1  thorpej 				    sc->sc_dev.dv_xname);
    966  1.1  thorpej 
    967  1.1  thorpej 				/* XXX adjust rx_drain_thresh? */
    968  1.1  thorpej 			}
    969  1.1  thorpej 
    970  1.1  thorpej 			if (isr & ISR_RXIDLE) {
    971  1.1  thorpej 				printf("%s: receive ring overrun\n",
    972  1.1  thorpej 				    sc->sc_dev.dv_xname);
    973  1.1  thorpej 
    974  1.1  thorpej 				/* Get the receive process going again. */
    975  1.1  thorpej 				bus_space_write_4(sc->sc_st, sc->sc_sh,
    976  1.1  thorpej 				    SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
    977  1.1  thorpej 				bus_space_write_4(sc->sc_st, sc->sc_sh,
    978  1.1  thorpej 				    SIP_CR, CR_RXE);
    979  1.1  thorpej 			}
    980  1.1  thorpej 		}
    981  1.1  thorpej 
    982  1.1  thorpej 		if (isr & (ISR_TXURN|ISR_TXDESC)) {
    983  1.1  thorpej 			/* Sweep up transmit descriptors. */
    984  1.1  thorpej 			sip_txintr(sc);
    985  1.1  thorpej 
    986  1.1  thorpej 			if (isr & ISR_TXURN) {
    987  1.1  thorpej 				u_int32_t thresh;
    988  1.1  thorpej 
    989  1.1  thorpej 				printf("%s: transmit FIFO underrun",
    990  1.1  thorpej 				    sc->sc_dev.dv_xname);
    991  1.1  thorpej 
    992  1.1  thorpej 				thresh = sc->sc_tx_drain_thresh + 1;
    993  1.1  thorpej 				if (thresh <= TXCFG_DRTH &&
    994  1.1  thorpej 				    (thresh * 32) <= (SIP_TXFIFO_SIZE -
    995  1.1  thorpej 				     (sc->sc_tx_fill_thresh * 32))) {
    996  1.1  thorpej 					printf("; increasing Tx drain "
    997  1.1  thorpej 					    "threshold to %u bytes\n",
    998  1.1  thorpej 					    thresh * 32);
    999  1.1  thorpej 					sc->sc_tx_drain_thresh = thresh;
   1000  1.2  thorpej 					(void) sip_init(sc);
   1001  1.1  thorpej 				} else {
   1002  1.2  thorpej 					(void) sip_init(sc);
   1003  1.1  thorpej 					printf("\n");
   1004  1.1  thorpej 				}
   1005  1.1  thorpej 			}
   1006  1.1  thorpej 		}
   1007  1.1  thorpej 
   1008  1.1  thorpej 		if (sc->sc_imr & (ISR_PAUSE_END|ISR_PAUSE_ST)) {
   1009  1.1  thorpej 			if (isr & ISR_PAUSE_ST) {
   1010  1.1  thorpej 				sc->sc_flags |= SIPF_PAUSED;
   1011  1.1  thorpej 				ifp->if_flags |= IFF_OACTIVE;
   1012  1.1  thorpej 			}
   1013  1.1  thorpej 			if (isr & ISR_PAUSE_END) {
   1014  1.1  thorpej 				sc->sc_flags &= ~SIPF_PAUSED;
   1015  1.1  thorpej 				ifp->if_flags &= ~IFF_OACTIVE;
   1016  1.1  thorpej 			}
   1017  1.1  thorpej 		}
   1018  1.1  thorpej 
   1019  1.1  thorpej 		if (isr & ISR_HIBERR) {
   1020  1.1  thorpej #define	PRINTERR(bit, str)						\
   1021  1.1  thorpej 			if (isr & (bit))				\
   1022  1.1  thorpej 				printf("%s: %s\n", sc->sc_dev.dv_xname, str)
   1023  1.1  thorpej 			PRINTERR(ISR_DPERR, "parity error");
   1024  1.1  thorpej 			PRINTERR(ISR_SSERR, "system error");
   1025  1.1  thorpej 			PRINTERR(ISR_RMABT, "master abort");
   1026  1.1  thorpej 			PRINTERR(ISR_RTABT, "target abort");
   1027  1.1  thorpej 			PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
   1028  1.2  thorpej 			(void) sip_init(sc);
   1029  1.1  thorpej #undef PRINTERR
   1030  1.1  thorpej 		}
   1031  1.1  thorpej 	}
   1032  1.1  thorpej 
   1033  1.1  thorpej 	/* Try to get more packets going. */
   1034  1.1  thorpej 	sip_start(ifp);
   1035  1.1  thorpej 
   1036  1.1  thorpej 	return (handled);
   1037  1.1  thorpej }
   1038  1.1  thorpej 
   1039  1.1  thorpej /*
   1040  1.1  thorpej  * sip_txintr:
   1041  1.1  thorpej  *
   1042  1.1  thorpej  *	Helper; handle transmit interrupts.
   1043  1.1  thorpej  */
   1044  1.1  thorpej void
   1045  1.1  thorpej sip_txintr(sc)
   1046  1.1  thorpej 	struct sip_softc *sc;
   1047  1.1  thorpej {
   1048  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1049  1.1  thorpej 	struct sip_txsoft *txs;
   1050  1.1  thorpej 	u_int32_t cmdsts;
   1051  1.1  thorpej 
   1052  1.1  thorpej 	if ((sc->sc_flags & SIPF_PAUSED) == 0)
   1053  1.1  thorpej 		ifp->if_flags &= ~IFF_OACTIVE;
   1054  1.1  thorpej 
   1055  1.1  thorpej 	/*
   1056  1.1  thorpej 	 * Go through our Tx list and free mbufs for those
   1057  1.1  thorpej 	 * frames which have been transmitted.
   1058  1.1  thorpej 	 */
   1059  1.1  thorpej 	while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
   1060  1.1  thorpej 		SIP_CDTXSYNC(sc, txs->txs_firstdesc, txs->txs_dmamap->dm_nsegs,
   1061  1.1  thorpej 		    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   1062  1.1  thorpej 
   1063  1.1  thorpej 		cmdsts = sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts;
   1064  1.1  thorpej 		if (cmdsts & CMDSTS_OWN)
   1065  1.1  thorpej 			break;
   1066  1.1  thorpej 
   1067  1.1  thorpej 		SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs, txs_q);
   1068  1.1  thorpej 
   1069  1.1  thorpej 		sc->sc_txfree += txs->txs_dmamap->dm_nsegs;
   1070  1.1  thorpej 
   1071  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
   1072  1.1  thorpej 		    0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
   1073  1.1  thorpej 		bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
   1074  1.1  thorpej 		m_freem(txs->txs_mbuf);
   1075  1.1  thorpej 		txs->txs_mbuf = NULL;
   1076  1.1  thorpej 
   1077  1.1  thorpej 		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
   1078  1.1  thorpej 
   1079  1.1  thorpej 		/*
   1080  1.1  thorpej 		 * Check for errors and collisions.
   1081  1.1  thorpej 		 */
   1082  1.1  thorpej 		if (cmdsts &
   1083  1.1  thorpej 		    (CMDSTS_Tx_TXA|CMDSTS_Tx_TFU|CMDSTS_Tx_ED|CMDSTS_Tx_EC)) {
   1084  1.1  thorpej 			if (ifp->if_flags & IFF_DEBUG) {
   1085  1.1  thorpej 				if (CMDSTS_Tx_ED)
   1086  1.1  thorpej 					printf("%s: excessive deferral\n",
   1087  1.1  thorpej 					    sc->sc_dev.dv_xname);
   1088  1.1  thorpej 				if (CMDSTS_Tx_EC) {
   1089  1.1  thorpej 					printf("%s: excessive collisions\n",
   1090  1.1  thorpej 					    sc->sc_dev.dv_xname);
   1091  1.1  thorpej 					ifp->if_collisions += 16;
   1092  1.1  thorpej 				}
   1093  1.1  thorpej 			}
   1094  1.1  thorpej 		} else {
   1095  1.1  thorpej 			/* Packet was transmitted successfully. */
   1096  1.1  thorpej 			ifp->if_opackets++;
   1097  1.1  thorpej 			ifp->if_collisions += CMDSTS_COLLISIONS(cmdsts);
   1098  1.1  thorpej 		}
   1099  1.1  thorpej 	}
   1100  1.1  thorpej 
   1101  1.1  thorpej 	/*
   1102  1.1  thorpej 	 * If there are no more pending transmissions, cancel the watchdog
   1103  1.1  thorpej 	 * timer.
   1104  1.1  thorpej 	 */
   1105  1.1  thorpej 	if (txs == NULL)
   1106  1.1  thorpej 		ifp->if_timer = 0;
   1107  1.1  thorpej }
   1108  1.1  thorpej 
   1109  1.1  thorpej /*
   1110  1.1  thorpej  * sip_rxintr:
   1111  1.1  thorpej  *
   1112  1.1  thorpej  *	Helper; handle receive interrupts.
   1113  1.1  thorpej  */
   1114  1.1  thorpej void
   1115  1.1  thorpej sip_rxintr(sc)
   1116  1.1  thorpej 	struct sip_softc *sc;
   1117  1.1  thorpej {
   1118  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1119  1.1  thorpej 	struct ether_header *eh;
   1120  1.1  thorpej 	struct sip_rxsoft *rxs;
   1121  1.1  thorpej 	struct mbuf *m;
   1122  1.1  thorpej 	u_int32_t cmdsts;
   1123  1.1  thorpej 	int i, len;
   1124  1.1  thorpej 
   1125  1.1  thorpej 	for (i = sc->sc_rxptr;; i = SIP_NEXTRX(i)) {
   1126  1.1  thorpej 		rxs = &sc->sc_rxsoft[i];
   1127  1.1  thorpej 
   1128  1.1  thorpej 		SIP_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   1129  1.1  thorpej 
   1130  1.1  thorpej 		cmdsts = sc->sc_rxdescs[i].sipd_cmdsts;
   1131  1.1  thorpej 
   1132  1.1  thorpej 		/*
   1133  1.1  thorpej 		 * NOTE: OWN is set if owned by _consumer_.  We're the
   1134  1.1  thorpej 		 * consumer of the receive ring, so if the bit is clear,
   1135  1.1  thorpej 		 * we have processed all of the packets.
   1136  1.1  thorpej 		 */
   1137  1.1  thorpej 		if ((cmdsts & CMDSTS_OWN) == 0) {
   1138  1.1  thorpej 			/*
   1139  1.1  thorpej 			 * We have processed all of the receive buffers.
   1140  1.1  thorpej 			 */
   1141  1.1  thorpej 			break;
   1142  1.1  thorpej 		}
   1143  1.1  thorpej 
   1144  1.1  thorpej 		/*
   1145  1.1  thorpej 		 * If any collisions were seen on the wire, count one.
   1146  1.1  thorpej 		 */
   1147  1.1  thorpej 		if (cmdsts & CMDSTS_Rx_COL)
   1148  1.1  thorpej 			ifp->if_collisions++;
   1149  1.1  thorpej 
   1150  1.1  thorpej 		/*
   1151  1.1  thorpej 		 * If an error occurred, update stats, clear the status
   1152  1.1  thorpej 		 * word, and leave the packet buffer in place.  It will
   1153  1.1  thorpej 		 * simply be reused the next time the ring comes around.
   1154  1.1  thorpej 		 */
   1155  1.1  thorpej 		if (cmdsts & (CMDSTS_Rx_RXA|CMDSTS_Rx_LONG|CMDSTS_Rx_RUNT|
   1156  1.1  thorpej 		    CMDSTS_Rx_ISE|CMDSTS_Rx_CRCE|CMDSTS_Rx_FAE)) {
   1157  1.1  thorpej 			ifp->if_ierrors++;
   1158  1.1  thorpej 			if ((cmdsts & CMDSTS_Rx_RXA) != 0 &&
   1159  1.1  thorpej 			    (cmdsts & CMDSTS_Rx_RXO) == 0) {
   1160  1.1  thorpej 				/* Receive overrun handled elsewhere. */
   1161  1.1  thorpej 				printf("%s: receive descriptor error\n",
   1162  1.1  thorpej 				    sc->sc_dev.dv_xname);
   1163  1.1  thorpej 			}
   1164  1.1  thorpej #define	PRINTERR(bit, str)						\
   1165  1.1  thorpej 			if (cmdsts & (bit))				\
   1166  1.1  thorpej 				printf("%s: %s\n", sc->sc_dev.dv_xname, str)
   1167  1.1  thorpej 			PRINTERR(CMDSTS_Rx_LONG, "packet too long");
   1168  1.1  thorpej 			PRINTERR(CMDSTS_Rx_RUNT, "runt packet");
   1169  1.1  thorpej 			PRINTERR(CMDSTS_Rx_ISE, "invalid symbol error");
   1170  1.1  thorpej 			PRINTERR(CMDSTS_Rx_CRCE, "CRC error");
   1171  1.1  thorpej 			PRINTERR(CMDSTS_Rx_FAE, "frame alignment error");
   1172  1.1  thorpej #undef PRINTERR
   1173  1.1  thorpej 			SIP_INIT_RXDESC(sc, i);
   1174  1.1  thorpej 			continue;
   1175  1.1  thorpej 		}
   1176  1.1  thorpej 
   1177  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   1178  1.1  thorpej 		    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
   1179  1.1  thorpej 
   1180  1.1  thorpej 		/*
   1181  1.1  thorpej 		 * No errors; receive the packet.  Note, the SiS 900
   1182  1.1  thorpej 		 * includes the CRC with every packet; trim it.
   1183  1.1  thorpej 		 */
   1184  1.1  thorpej 		len = CMDSTS_SIZE(cmdsts) - ETHER_CRC_LEN;
   1185  1.1  thorpej 
   1186  1.1  thorpej #ifdef __NO_STRICT_ALIGNMENT
   1187  1.1  thorpej 		/*
   1188  1.2  thorpej 		 * If the packet is small enough to fit in a
   1189  1.2  thorpej 		 * single header mbuf, allocate one and copy
   1190  1.2  thorpej 		 * the data into it.  This greatly reduces
   1191  1.2  thorpej 		 * memory consumption when we receive lots
   1192  1.2  thorpej 		 * of small packets.
   1193  1.2  thorpej 		 *
   1194  1.2  thorpej 		 * Otherwise, we add a new buffer to the receive
   1195  1.2  thorpej 		 * chain.  If this fails, we drop the packet and
   1196  1.2  thorpej 		 * recycle the old buffer.
   1197  1.1  thorpej 		 */
   1198  1.2  thorpej 		if (sip_copy_small != 0 && len <= MHLEN) {
   1199  1.2  thorpej 			MGETHDR(m, M_DONTWAIT, MT_DATA);
   1200  1.2  thorpej 			if (m == NULL)
   1201  1.2  thorpej 				goto dropit;
   1202  1.2  thorpej 			memcpy(mtod(m, caddr_t),
   1203  1.2  thorpej 			    mtod(rxs->rxs_mbuf, caddr_t), len);
   1204  1.1  thorpej 			SIP_INIT_RXDESC(sc, i);
   1205  1.1  thorpej 			bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   1206  1.2  thorpej 			    rxs->rxs_dmamap->dm_mapsize,
   1207  1.2  thorpej 			    BUS_DMASYNC_PREREAD);
   1208  1.2  thorpej 		} else {
   1209  1.2  thorpej 			m = rxs->rxs_mbuf;
   1210  1.2  thorpej 			if (sip_add_rxbuf(sc, i) != 0) {
   1211  1.2  thorpej  dropit:
   1212  1.2  thorpej 				ifp->if_ierrors++;
   1213  1.2  thorpej 				SIP_INIT_RXDESC(sc, i);
   1214  1.2  thorpej 				bus_dmamap_sync(sc->sc_dmat,
   1215  1.2  thorpej 				    rxs->rxs_dmamap, 0,
   1216  1.2  thorpej 				    rxs->rxs_dmamap->dm_mapsize,
   1217  1.2  thorpej 				    BUS_DMASYNC_PREREAD);
   1218  1.2  thorpej 				continue;
   1219  1.2  thorpej 			}
   1220  1.1  thorpej 		}
   1221  1.1  thorpej #else
   1222  1.1  thorpej 		/*
   1223  1.1  thorpej 		 * The SiS 900's receive buffers must be 4-byte aligned.
   1224  1.1  thorpej 		 * But this means that the data after the Ethernet header
   1225  1.1  thorpej 		 * is misaligned.  We must allocate a new buffer and
   1226  1.1  thorpej 		 * copy the data, shifted forward 2 bytes.
   1227  1.1  thorpej 		 */
   1228  1.1  thorpej 		MGETHDR(m, M_DONTWAIT, MT_DATA);
   1229  1.1  thorpej 		if (m == NULL) {
   1230  1.1  thorpej  dropit:
   1231  1.1  thorpej 			ifp->if_ierrors++;
   1232  1.1  thorpej 			SIP_INIT_RXDESC(sc, i);
   1233  1.1  thorpej 			bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   1234  1.1  thorpej 			    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
   1235  1.1  thorpej 			continue;
   1236  1.1  thorpej 		}
   1237  1.1  thorpej 		if (len > (MHLEN - 2)) {
   1238  1.1  thorpej 			MCLGET(m, M_DONTWAIT);
   1239  1.1  thorpej 			if ((m->m_flags & M_EXT) == 0) {
   1240  1.1  thorpej 				m_freem(m);
   1241  1.1  thorpej 				goto dropit;
   1242  1.1  thorpej 			}
   1243  1.1  thorpej 		}
   1244  1.1  thorpej 		m->m_data += 2;
   1245  1.1  thorpej 
   1246  1.1  thorpej 		/*
   1247  1.1  thorpej 		 * Note that we use clusters for incoming frames, so the
   1248  1.1  thorpej 		 * buffer is virtually contiguous.
   1249  1.1  thorpej 		 */
   1250  1.1  thorpej 		memcpy(mtod(m, caddr_t), mtod(rxs->rxs_mbuf, caddr_t), len);
   1251  1.1  thorpej 
   1252  1.1  thorpej 		/* Allow the receive descriptor to continue using its mbuf. */
   1253  1.1  thorpej 		SIP_INIT_RXDESC(sc, i);
   1254  1.1  thorpej 		bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   1255  1.1  thorpej 		    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
   1256  1.1  thorpej #endif /* __NO_STRICT_ALIGNMENT */
   1257  1.1  thorpej 
   1258  1.1  thorpej 		ifp->if_ipackets++;
   1259  1.1  thorpej 		eh = mtod(m, struct ether_header *);
   1260  1.1  thorpej 		m->m_pkthdr.rcvif = ifp;
   1261  1.1  thorpej 		m->m_pkthdr.len = m->m_len = len;
   1262  1.1  thorpej 
   1263  1.1  thorpej #if NBPFILTER > 0
   1264  1.1  thorpej 		/*
   1265  1.1  thorpej 		 * Pass this up to any BPF listeners, but only
   1266  1.1  thorpej 		 * pass if up the stack if it's for us.
   1267  1.1  thorpej 		 */
   1268  1.1  thorpej 		if (ifp->if_bpf) {
   1269  1.1  thorpej 			bpf_mtap(ifp->if_bpf, m);
   1270  1.1  thorpej 			if ((ifp->if_flags & IFF_PROMISC) != 0 &&
   1271  1.1  thorpej 			    (cmdsts & CMDSTS_Rx_DEST) == CMDSTS_Rx_DEST_REJ) {
   1272  1.1  thorpej 				m_freem(m);
   1273  1.1  thorpej 				continue;
   1274  1.1  thorpej 			}
   1275  1.1  thorpej 		}
   1276  1.1  thorpej #endif /* NBPFILTER > 0 */
   1277  1.1  thorpej 
   1278  1.1  thorpej 		/* Pass it on. */
   1279  1.1  thorpej 		(*ifp->if_input)(ifp, m);
   1280  1.1  thorpej 	}
   1281  1.1  thorpej 
   1282  1.1  thorpej 	/* Update the receive pointer. */
   1283  1.1  thorpej 	sc->sc_rxptr = i;
   1284  1.1  thorpej }
   1285  1.1  thorpej 
   1286  1.1  thorpej /*
   1287  1.1  thorpej  * sip_tick:
   1288  1.1  thorpej  *
   1289  1.1  thorpej  *	One second timer, used to tick the MII.
   1290  1.1  thorpej  */
   1291  1.1  thorpej void
   1292  1.1  thorpej sip_tick(arg)
   1293  1.1  thorpej 	void *arg;
   1294  1.1  thorpej {
   1295  1.1  thorpej 	struct sip_softc *sc = arg;
   1296  1.1  thorpej 	int s;
   1297  1.1  thorpej 
   1298  1.1  thorpej 	s = splnet();
   1299  1.1  thorpej 	mii_tick(&sc->sc_mii);
   1300  1.1  thorpej 	splx(s);
   1301  1.1  thorpej 
   1302  1.1  thorpej 	timeout(sip_tick, sc, hz);
   1303  1.1  thorpej }
   1304  1.1  thorpej 
   1305  1.1  thorpej /*
   1306  1.1  thorpej  * sip_reset:
   1307  1.1  thorpej  *
   1308  1.1  thorpej  *	Perform a soft reset on the SiS 900.
   1309  1.1  thorpej  */
   1310  1.1  thorpej void
   1311  1.1  thorpej sip_reset(sc)
   1312  1.1  thorpej 	struct sip_softc *sc;
   1313  1.1  thorpej {
   1314  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
   1315  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
   1316  1.1  thorpej 	int i;
   1317  1.1  thorpej 
   1318  1.1  thorpej 	bus_space_write_4(st, sh, SIP_CR, CR_RST);
   1319  1.1  thorpej 
   1320  1.1  thorpej 	for (i = 0; i < 1000; i++) {
   1321  1.1  thorpej 		if ((bus_space_read_4(st, sh, SIP_ISR) &
   1322  1.1  thorpej 		     (ISR_TXRCMP|ISR_RXRCMP)) == (ISR_TXRCMP|ISR_RXRCMP))
   1323  1.1  thorpej 			return;
   1324  1.1  thorpej 		delay(2);
   1325  1.1  thorpej 	}
   1326  1.1  thorpej 
   1327  1.1  thorpej 	printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
   1328  1.1  thorpej }
   1329  1.1  thorpej 
   1330  1.1  thorpej /*
   1331  1.1  thorpej  * sip_init:
   1332  1.1  thorpej  *
   1333  1.1  thorpej  *	Initialize the interface.  Must be called at splnet().
   1334  1.1  thorpej  */
   1335  1.2  thorpej int
   1336  1.1  thorpej sip_init(sc)
   1337  1.1  thorpej 	struct sip_softc *sc;
   1338  1.1  thorpej {
   1339  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
   1340  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
   1341  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1342  1.1  thorpej 	struct sip_txsoft *txs;
   1343  1.2  thorpej 	struct sip_rxsoft *rxs;
   1344  1.1  thorpej 	struct sip_desc *sipd;
   1345  1.1  thorpej 	u_int32_t cfg;
   1346  1.2  thorpej 	int i, error = 0;
   1347  1.1  thorpej 
   1348  1.1  thorpej 	/*
   1349  1.1  thorpej 	 * Cancel any pending I/O.
   1350  1.1  thorpej 	 */
   1351  1.2  thorpej 	sip_stop(sc, 0);
   1352  1.1  thorpej 
   1353  1.1  thorpej 	/*
   1354  1.1  thorpej 	 * Reset the chip to a known state.
   1355  1.1  thorpej 	 */
   1356  1.1  thorpej 	sip_reset(sc);
   1357  1.1  thorpej 
   1358  1.1  thorpej 	/*
   1359  1.1  thorpej 	 * Initialize the transmit descriptor ring.
   1360  1.1  thorpej 	 */
   1361  1.1  thorpej 	for (i = 0; i < SIP_NTXDESC; i++) {
   1362  1.1  thorpej 		sipd = &sc->sc_txdescs[i];
   1363  1.1  thorpej 		memset(sipd, 0, sizeof(struct sip_desc));
   1364  1.1  thorpej 		sipd->sipd_link = SIP_CDTXADDR(sc, SIP_NEXTTX(i));
   1365  1.1  thorpej 	}
   1366  1.1  thorpej 	SIP_CDTXSYNC(sc, 0, SIP_NTXDESC,
   1367  1.1  thorpej 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   1368  1.1  thorpej 	sc->sc_txfree = SIP_NTXDESC;
   1369  1.1  thorpej 	sc->sc_txnext = 0;
   1370  1.1  thorpej 
   1371  1.1  thorpej 	/*
   1372  1.1  thorpej 	 * Initialize the transmit job descriptors.
   1373  1.1  thorpej 	 */
   1374  1.1  thorpej 	SIMPLEQ_INIT(&sc->sc_txfreeq);
   1375  1.1  thorpej 	SIMPLEQ_INIT(&sc->sc_txdirtyq);
   1376  1.1  thorpej 	for (i = 0; i < SIP_TXQUEUELEN; i++) {
   1377  1.1  thorpej 		txs = &sc->sc_txsoft[i];
   1378  1.1  thorpej 		txs->txs_mbuf = NULL;
   1379  1.1  thorpej 		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
   1380  1.1  thorpej 	}
   1381  1.1  thorpej 
   1382  1.1  thorpej 	/*
   1383  1.1  thorpej 	 * Initialize the receive descriptor and receive job
   1384  1.2  thorpej 	 * descriptor rings.
   1385  1.1  thorpej 	 */
   1386  1.2  thorpej 	for (i = 0; i < SIP_NRXDESC; i++) {
   1387  1.2  thorpej 		rxs = &sc->sc_rxsoft[i];
   1388  1.2  thorpej 		if (rxs->rxs_mbuf == NULL) {
   1389  1.2  thorpej 			if ((error = sip_add_rxbuf(sc, i)) != 0) {
   1390  1.2  thorpej 				printf("%s: unable to allocate or map rx "
   1391  1.2  thorpej 				    "buffer %d, error = %d\n",
   1392  1.2  thorpej 				    sc->sc_dev.dv_xname, i, error);
   1393  1.2  thorpej 				/*
   1394  1.2  thorpej 				 * XXX Should attempt to run with fewer receive
   1395  1.2  thorpej 				 * XXX buffers instead of just failing.
   1396  1.2  thorpej 				 */
   1397  1.2  thorpej 				sip_rxdrain(sc);
   1398  1.2  thorpej 				goto out;
   1399  1.2  thorpej 			}
   1400  1.2  thorpej 		}
   1401  1.2  thorpej 	}
   1402  1.1  thorpej 	sc->sc_rxptr = 0;
   1403  1.1  thorpej 
   1404  1.1  thorpej 	/*
   1405  1.1  thorpej 	 * Initialize the configuration register: aggressive PCI
   1406  1.1  thorpej 	 * bus request algorithm, default backoff, default OW timer,
   1407  1.1  thorpej 	 * default parity error detection.
   1408  1.1  thorpej 	 */
   1409  1.1  thorpej 	cfg = 0;
   1410  1.1  thorpej #if BYTE_ORDER == BIG_ENDIAN
   1411  1.1  thorpej 	/*
   1412  1.1  thorpej 	 * ...descriptors in big-endian mode.
   1413  1.1  thorpej 	 */
   1414  1.1  thorpej 	cfg |= CFG_BEM;
   1415  1.1  thorpej #endif
   1416  1.1  thorpej 	bus_space_write_4(st, sh, SIP_CFG, cfg);
   1417  1.1  thorpej 
   1418  1.1  thorpej 	/*
   1419  1.1  thorpej 	 * Initialize the transmit fill and drain thresholds if
   1420  1.1  thorpej 	 * we have never done so.
   1421  1.1  thorpej 	 */
   1422  1.1  thorpej 	if (sc->sc_tx_fill_thresh == 0) {
   1423  1.1  thorpej 		/*
   1424  1.1  thorpej 		 * XXX This value should be tuned.  This is the
   1425  1.1  thorpej 		 * minimum (32 bytes), and we may be able to
   1426  1.1  thorpej 		 * improve performance by increasing it.
   1427  1.1  thorpej 		 */
   1428  1.1  thorpej 		sc->sc_tx_fill_thresh = 1;
   1429  1.1  thorpej 	}
   1430  1.1  thorpej 	if (sc->sc_tx_drain_thresh == 0) {
   1431  1.1  thorpej 		/*
   1432  1.1  thorpej 		 * Start at a drain threshold of 128 bytes.  We will
   1433  1.1  thorpej 		 * increase it if a DMA underrun occurs.
   1434  1.1  thorpej 		 *
   1435  1.1  thorpej 		 * XXX The minimum value of this variable should be
   1436  1.1  thorpej 		 * tuned.  We may be able to improve performance
   1437  1.1  thorpej 		 * by starting with a lower value.  That, however,
   1438  1.1  thorpej 		 * may trash the first few outgoing packets if the
   1439  1.1  thorpej 		 * PCI bus is saturated.
   1440  1.1  thorpej 		 */
   1441  1.1  thorpej 		sc->sc_tx_drain_thresh = 4;
   1442  1.1  thorpej 	}
   1443  1.1  thorpej 
   1444  1.1  thorpej 	/*
   1445  1.1  thorpej 	 * Initialize the prototype TXCFG register.
   1446  1.1  thorpej 	 */
   1447  1.1  thorpej 	sc->sc_txcfg = TXCFG_ATP | TXCFG_MXDMA_512 |
   1448  1.1  thorpej 	    (sc->sc_tx_fill_thresh << TXCFG_FLTH_SHIFT) |
   1449  1.1  thorpej 	    sc->sc_tx_drain_thresh;
   1450  1.1  thorpej 	bus_space_write_4(st, sh, SIP_TXCFG, sc->sc_txcfg);
   1451  1.1  thorpej 
   1452  1.1  thorpej 	/*
   1453  1.1  thorpej 	 * Initialize the receive drain threshold if we have never
   1454  1.1  thorpej 	 * done so.
   1455  1.1  thorpej 	 */
   1456  1.1  thorpej 	if (sc->sc_rx_drain_thresh == 0) {
   1457  1.1  thorpej 		/*
   1458  1.1  thorpej 		 * XXX This value should be tuned.  This is set to the
   1459  1.1  thorpej 		 * maximum of 248 bytes, and we may be able to improve
   1460  1.1  thorpej 		 * performance by decreasing it (although we should never
   1461  1.1  thorpej 		 * set this value lower than 2; 14 bytes are required to
   1462  1.1  thorpej 		 * filter the packet).
   1463  1.1  thorpej 		 */
   1464  1.1  thorpej 		sc->sc_rx_drain_thresh = RXCFG_DRTH >> RXCFG_DRTH_SHIFT;
   1465  1.1  thorpej 	}
   1466  1.1  thorpej 
   1467  1.1  thorpej 	/*
   1468  1.1  thorpej 	 * Initialize the prototype RXCFG register.
   1469  1.1  thorpej 	 */
   1470  1.1  thorpej 	sc->sc_rxcfg = RXCFG_MXDMA_512 |
   1471  1.1  thorpej 	    (sc->sc_rx_drain_thresh << RXCFG_DRTH_SHIFT);
   1472  1.1  thorpej 	bus_space_write_4(st, sh, SIP_RXCFG, sc->sc_rxcfg);
   1473  1.1  thorpej 
   1474  1.1  thorpej 	/* Set up the receive filter. */
   1475  1.1  thorpej 	sip_set_filter(sc);
   1476  1.1  thorpej 
   1477  1.1  thorpej 	/*
   1478  1.1  thorpej 	 * Give the transmit and receive rings to the chip.
   1479  1.1  thorpej 	 */
   1480  1.1  thorpej 	bus_space_write_4(st, sh, SIP_TXDP, SIP_CDTXADDR(sc, sc->sc_txnext));
   1481  1.1  thorpej 	bus_space_write_4(st, sh, SIP_RXDP, SIP_CDRXADDR(sc, sc->sc_rxptr));
   1482  1.1  thorpej 
   1483  1.1  thorpej 	/*
   1484  1.1  thorpej 	 * Initialize the interrupt mask.
   1485  1.1  thorpej 	 */
   1486  1.1  thorpej 	sc->sc_imr = ISR_DPERR|ISR_SSERR|ISR_RMABT|ISR_RTABT|ISR_RXSOVR|
   1487  1.1  thorpej 	    ISR_TXURN|ISR_TXDESC|ISR_RXORN|ISR_RXIDLE|ISR_RXDESC;
   1488  1.1  thorpej 	bus_space_write_4(st, sh, SIP_IMR, sc->sc_imr);
   1489  1.1  thorpej 
   1490  1.1  thorpej 	/*
   1491  1.1  thorpej 	 * Set the current media.  Do this after initializing the prototype
   1492  1.1  thorpej 	 * IMR, since sip_mii_statchg() modifies the IMR for 802.3x flow
   1493  1.1  thorpej 	 * control.
   1494  1.1  thorpej 	 */
   1495  1.1  thorpej 	mii_mediachg(&sc->sc_mii);
   1496  1.1  thorpej 
   1497  1.1  thorpej 	/*
   1498  1.1  thorpej 	 * Enable interrupts.
   1499  1.1  thorpej 	 */
   1500  1.1  thorpej 	bus_space_write_4(st, sh, SIP_IER, IER_IE);
   1501  1.1  thorpej 
   1502  1.1  thorpej 	/*
   1503  1.1  thorpej 	 * Start the transmit and receive processes.
   1504  1.1  thorpej 	 */
   1505  1.1  thorpej 	bus_space_write_4(st, sh, SIP_CR, CR_RXE | CR_TXE);
   1506  1.1  thorpej 
   1507  1.1  thorpej 	/*
   1508  1.1  thorpej 	 * Start the one second MII clock.
   1509  1.1  thorpej 	 */
   1510  1.1  thorpej 	timeout(sip_tick, sc, hz);
   1511  1.1  thorpej 
   1512  1.1  thorpej 	/*
   1513  1.1  thorpej 	 * ...all done!
   1514  1.1  thorpej 	 */
   1515  1.1  thorpej 	ifp->if_flags |= IFF_RUNNING;
   1516  1.1  thorpej 	ifp->if_flags &= ~IFF_OACTIVE;
   1517  1.2  thorpej 
   1518  1.2  thorpej  out:
   1519  1.2  thorpej 	if (error)
   1520  1.2  thorpej 		printf("%s: interface not running\n", sc->sc_dev.dv_xname);
   1521  1.2  thorpej 	return (error);
   1522  1.2  thorpej }
   1523  1.2  thorpej 
   1524  1.2  thorpej /*
   1525  1.2  thorpej  * sip_drain:
   1526  1.2  thorpej  *
   1527  1.2  thorpej  *	Drain the receive queue.
   1528  1.2  thorpej  */
   1529  1.2  thorpej void
   1530  1.2  thorpej sip_rxdrain(sc)
   1531  1.2  thorpej 	struct sip_softc *sc;
   1532  1.2  thorpej {
   1533  1.2  thorpej 	struct sip_rxsoft *rxs;
   1534  1.2  thorpej 	int i;
   1535  1.2  thorpej 
   1536  1.2  thorpej 	for (i = 0; i < SIP_NRXDESC; i++) {
   1537  1.2  thorpej 		rxs = &sc->sc_rxsoft[i];
   1538  1.2  thorpej 		if (rxs->rxs_mbuf != NULL) {
   1539  1.2  thorpej 			bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
   1540  1.2  thorpej 			m_freem(rxs->rxs_mbuf);
   1541  1.2  thorpej 			rxs->rxs_mbuf = NULL;
   1542  1.2  thorpej 		}
   1543  1.2  thorpej 	}
   1544  1.1  thorpej }
   1545  1.1  thorpej 
   1546  1.1  thorpej /*
   1547  1.1  thorpej  * sip_stop:
   1548  1.1  thorpej  *
   1549  1.1  thorpej  *	Stop transmission on the interface.
   1550  1.1  thorpej  */
   1551  1.1  thorpej void
   1552  1.2  thorpej sip_stop(sc, drain)
   1553  1.1  thorpej 	struct sip_softc *sc;
   1554  1.1  thorpej {
   1555  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
   1556  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
   1557  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1558  1.1  thorpej 	struct sip_txsoft *txs;
   1559  1.1  thorpej 	u_int32_t cmdsts = 0;		/* DEBUG */
   1560  1.1  thorpej 
   1561  1.1  thorpej 	/*
   1562  1.1  thorpej 	 * Stop the one second clock.
   1563  1.1  thorpej 	 */
   1564  1.1  thorpej 	untimeout(sip_tick, sc);
   1565  1.1  thorpej 
   1566  1.1  thorpej 	/*
   1567  1.1  thorpej 	 * Disable interrupts.
   1568  1.1  thorpej 	 */
   1569  1.1  thorpej 	bus_space_write_4(st, sh, SIP_IER, 0);
   1570  1.1  thorpej 
   1571  1.1  thorpej 	/*
   1572  1.1  thorpej 	 * Stop receiver and transmitter.
   1573  1.1  thorpej 	 */
   1574  1.1  thorpej 	bus_space_write_4(st, sh, SIP_CR, CR_RXD | CR_TXD);
   1575  1.1  thorpej 
   1576  1.1  thorpej 	/*
   1577  1.1  thorpej 	 * Release any queued transmit buffers.
   1578  1.1  thorpej 	 */
   1579  1.1  thorpej 	while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
   1580  1.1  thorpej 		if ((ifp->if_flags & IFF_DEBUG) != 0 &&
   1581  1.1  thorpej 		    SIMPLEQ_NEXT(txs, txs_q) == NULL &&
   1582  1.1  thorpej 		    (sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts &
   1583  1.1  thorpej 		     CMDSTS_INTR) == 0)
   1584  1.1  thorpej 			printf("%s: sip_stop: last descriptor does not "
   1585  1.1  thorpej 			    "have INTR bit set\n", sc->sc_dev.dv_xname);
   1586  1.1  thorpej 		SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs, txs_q);
   1587  1.1  thorpej #ifdef DIAGNOSTIC
   1588  1.1  thorpej 		if (txs->txs_mbuf == NULL) {
   1589  1.1  thorpej 			printf("%s: dirty txsoft with no mbuf chain\n",
   1590  1.1  thorpej 			    sc->sc_dev.dv_xname);
   1591  1.1  thorpej 			panic("sip_stop");
   1592  1.1  thorpej 		}
   1593  1.1  thorpej #endif
   1594  1.1  thorpej 		cmdsts |=		/* DEBUG */
   1595  1.1  thorpej 		    sc->sc_txdescs[txs->txs_lastdesc].sipd_cmdsts;
   1596  1.1  thorpej 		bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
   1597  1.1  thorpej 		m_freem(txs->txs_mbuf);
   1598  1.1  thorpej 		txs->txs_mbuf = NULL;
   1599  1.1  thorpej 		SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
   1600  1.2  thorpej 	}
   1601  1.2  thorpej 
   1602  1.2  thorpej 	if (drain) {
   1603  1.2  thorpej 		/*
   1604  1.2  thorpej 		 * Release the receive buffers.
   1605  1.2  thorpej 		 */
   1606  1.2  thorpej 		sip_rxdrain(sc);
   1607  1.1  thorpej 	}
   1608  1.1  thorpej 
   1609  1.1  thorpej 	/*
   1610  1.1  thorpej 	 * Mark the interface down and cancel the watchdog timer.
   1611  1.1  thorpej 	 */
   1612  1.1  thorpej 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   1613  1.1  thorpej 	ifp->if_timer = 0;
   1614  1.1  thorpej 
   1615  1.1  thorpej 	if ((ifp->if_flags & IFF_DEBUG) != 0 &&
   1616  1.1  thorpej 	    (cmdsts & CMDSTS_INTR) == 0 && sc->sc_txfree != SIP_NTXDESC)
   1617  1.1  thorpej 		printf("%s: sip_stop: no INTR bits set in dirty tx "
   1618  1.1  thorpej 		    "descriptors\n", sc->sc_dev.dv_xname);
   1619  1.1  thorpej }
   1620  1.1  thorpej 
   1621  1.1  thorpej /*
   1622  1.1  thorpej  * sip_read_eeprom:
   1623  1.1  thorpej  *
   1624  1.1  thorpej  *	Read data from the serial EEPROM.
   1625  1.1  thorpej  */
   1626  1.1  thorpej void
   1627  1.1  thorpej sip_read_eeprom(sc, word, wordcnt, data)
   1628  1.1  thorpej 	struct sip_softc *sc;
   1629  1.1  thorpej 	int word, wordcnt;
   1630  1.1  thorpej 	u_int16_t *data;
   1631  1.1  thorpej {
   1632  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
   1633  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
   1634  1.1  thorpej 	u_int16_t reg;
   1635  1.1  thorpej 	int i, x;
   1636  1.1  thorpej 
   1637  1.1  thorpej 	for (i = 0; i < wordcnt; i++) {
   1638  1.1  thorpej 		/* Send CHIP SELECT. */
   1639  1.1  thorpej 		reg = EROMAR_EECS;
   1640  1.1  thorpej 		bus_space_write_4(st, sh, SIP_EROMAR, reg);
   1641  1.1  thorpej 
   1642  1.1  thorpej 		/* Shift in the READ opcode. */
   1643  1.1  thorpej 		for (x = 3; x > 0; x--) {
   1644  1.1  thorpej 			if (SIP_EEPROM_OPC_READ & (1 << (x - 1)))
   1645  1.1  thorpej 				reg |= EROMAR_EEDI;
   1646  1.1  thorpej 			else
   1647  1.1  thorpej 				reg &= ~EROMAR_EEDI;
   1648  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR, reg);
   1649  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR,
   1650  1.1  thorpej 			    reg | EROMAR_EESK);
   1651  1.1  thorpej 			delay(4);
   1652  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR, reg);
   1653  1.1  thorpej 			delay(4);
   1654  1.1  thorpej 		}
   1655  1.1  thorpej 
   1656  1.1  thorpej 		/* Shift in address. */
   1657  1.1  thorpej 		for (x = 6; x > 0; x--) {
   1658  1.1  thorpej 			if ((word + i) & (1 << (x - 1)))
   1659  1.1  thorpej 				reg |= EROMAR_EEDI;
   1660  1.1  thorpej 			else
   1661  1.1  thorpej 				reg &= ~EROMAR_EEDI;
   1662  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR, reg);
   1663  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR,
   1664  1.1  thorpej 			    reg | EROMAR_EESK);
   1665  1.1  thorpej 			delay(4);
   1666  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR, reg);
   1667  1.1  thorpej 			delay(4);
   1668  1.1  thorpej 		}
   1669  1.1  thorpej 
   1670  1.1  thorpej 		/* Shift out data. */
   1671  1.1  thorpej 		reg = EROMAR_EECS;
   1672  1.1  thorpej 		data[i] = 0;
   1673  1.1  thorpej 		for (x = 16; x > 0; x--) {
   1674  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR,
   1675  1.1  thorpej 			    reg | EROMAR_EESK);
   1676  1.1  thorpej 			delay(4);
   1677  1.1  thorpej 			if (bus_space_read_4(st, sh, SIP_EROMAR) & EROMAR_EEDO)
   1678  1.1  thorpej 				data[i] |= (1 << (x - 1));
   1679  1.1  thorpej 			bus_space_write_4(st, sh, SIP_EROMAR, reg);
   1680  1.1  thorpej 		}
   1681  1.1  thorpej 
   1682  1.1  thorpej 		/* Clear CHIP SELECT. */
   1683  1.1  thorpej 		bus_space_write_4(st, sh, SIP_EROMAR, 0);
   1684  1.1  thorpej 		delay(4);
   1685  1.1  thorpej 	}
   1686  1.1  thorpej }
   1687  1.1  thorpej 
   1688  1.1  thorpej /*
   1689  1.1  thorpej  * sip_add_rxbuf:
   1690  1.1  thorpej  *
   1691  1.1  thorpej  *	Add a receive buffer to the indicated descriptor.
   1692  1.1  thorpej  */
   1693  1.1  thorpej int
   1694  1.1  thorpej sip_add_rxbuf(sc, idx)
   1695  1.1  thorpej 	struct sip_softc *sc;
   1696  1.1  thorpej 	int idx;
   1697  1.1  thorpej {
   1698  1.1  thorpej 	struct sip_rxsoft *rxs = &sc->sc_rxsoft[idx];
   1699  1.1  thorpej 	struct mbuf *m;
   1700  1.1  thorpej 	int error;
   1701  1.1  thorpej 
   1702  1.1  thorpej 	MGETHDR(m, M_DONTWAIT, MT_DATA);
   1703  1.1  thorpej 	if (m == NULL)
   1704  1.1  thorpej 		return (ENOBUFS);
   1705  1.1  thorpej 
   1706  1.1  thorpej 	MCLGET(m, M_DONTWAIT);
   1707  1.1  thorpej 	if ((m->m_flags & M_EXT) == 0) {
   1708  1.1  thorpej 		m_freem(m);
   1709  1.1  thorpej 		return (ENOBUFS);
   1710  1.1  thorpej 	}
   1711  1.1  thorpej 
   1712  1.1  thorpej 	if (rxs->rxs_mbuf != NULL)
   1713  1.1  thorpej 		bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
   1714  1.1  thorpej 
   1715  1.1  thorpej 	rxs->rxs_mbuf = m;
   1716  1.1  thorpej 
   1717  1.1  thorpej 	error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
   1718  1.1  thorpej 	    m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
   1719  1.1  thorpej 	if (error) {
   1720  1.1  thorpej 		printf("%s: can't load rx DMA map %d, error = %d\n",
   1721  1.1  thorpej 		    sc->sc_dev.dv_xname, idx, error);
   1722  1.1  thorpej 		panic("sip_add_rxbuf");		/* XXX */
   1723  1.1  thorpej 	}
   1724  1.1  thorpej 
   1725  1.1  thorpej 	bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
   1726  1.1  thorpej 	    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
   1727  1.1  thorpej 
   1728  1.1  thorpej 	SIP_INIT_RXDESC(sc, idx);
   1729  1.1  thorpej 
   1730  1.1  thorpej 	return (0);
   1731  1.1  thorpej }
   1732  1.1  thorpej 
   1733  1.1  thorpej /*
   1734  1.1  thorpej  * sip_set_filter:
   1735  1.1  thorpej  *
   1736  1.1  thorpej  *	Set up the receive filter.
   1737  1.1  thorpej  */
   1738  1.1  thorpej void
   1739  1.1  thorpej sip_set_filter(sc)
   1740  1.1  thorpej 	struct sip_softc *sc;
   1741  1.1  thorpej {
   1742  1.1  thorpej 	bus_space_tag_t st = sc->sc_st;
   1743  1.1  thorpej 	bus_space_handle_t sh = sc->sc_sh;
   1744  1.1  thorpej 	struct ethercom *ec = &sc->sc_ethercom;
   1745  1.1  thorpej 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
   1746  1.1  thorpej 	struct ether_multi *enm;
   1747  1.1  thorpej 	struct ether_multistep step;
   1748  1.1  thorpej 	u_int8_t *cp;
   1749  1.1  thorpej 	u_int32_t crc, mchash[8];
   1750  1.1  thorpej 	int len;
   1751  1.1  thorpej 	static const u_int32_t crctab[] = {
   1752  1.1  thorpej 		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
   1753  1.1  thorpej 		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
   1754  1.1  thorpej 		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
   1755  1.1  thorpej 		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
   1756  1.1  thorpej 	};
   1757  1.1  thorpej 
   1758  1.1  thorpej 	/*
   1759  1.1  thorpej 	 * Initialize the prototype RFCR.
   1760  1.1  thorpej 	 */
   1761  1.1  thorpej 	sc->sc_rfcr = RFCR_RFEN;
   1762  1.1  thorpej 	if (ifp->if_flags & IFF_BROADCAST)
   1763  1.1  thorpej 		sc->sc_rfcr |= RFCR_AAB;
   1764  1.1  thorpej 	if (ifp->if_flags & IFF_PROMISC) {
   1765  1.1  thorpej 		sc->sc_rfcr |= RFCR_AAP;
   1766  1.1  thorpej 		goto allmulti;
   1767  1.1  thorpej 	}
   1768  1.1  thorpej 
   1769  1.1  thorpej 	/*
   1770  1.1  thorpej 	 * Set up the multicast address filter by passing all multicast
   1771  1.1  thorpej 	 * addresses through a CRC generator, and then using the high-order
   1772  1.1  thorpej 	 * 6 bits as an index into the 128 bit multicast hash table (only
   1773  1.1  thorpej 	 * the lower 16 bits of each 32 bit multicast hash register are
   1774  1.1  thorpej 	 * valid).  The high order bits select the register, while the
   1775  1.1  thorpej 	 * rest of the bits select the bit within the register.
   1776  1.1  thorpej 	 */
   1777  1.1  thorpej 
   1778  1.1  thorpej 	memset(mchash, 0, sizeof(mchash));
   1779  1.1  thorpej 
   1780  1.1  thorpej 	ETHER_FIRST_MULTI(step, ec, enm);
   1781  1.1  thorpej 	while (enm != NULL) {
   1782  1.1  thorpej 		if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
   1783  1.1  thorpej 			/*
   1784  1.1  thorpej 			 * We must listen to a range of multicast addresses.
   1785  1.1  thorpej 			 * For now, just accept all multicasts, rather than
   1786  1.1  thorpej 			 * trying to set only those filter bits needed to match
   1787  1.1  thorpej 			 * the range.  (At this time, the only use of address
   1788  1.1  thorpej 			 * ranges is for IP multicast routing, for which the
   1789  1.1  thorpej 			 * range is big enough to require all bits set.)
   1790  1.1  thorpej 			 */
   1791  1.1  thorpej 			goto allmulti;
   1792  1.1  thorpej 		}
   1793  1.1  thorpej 
   1794  1.1  thorpej 		cp = enm->enm_addrlo;
   1795  1.1  thorpej 		crc = 0xffffffff;
   1796  1.1  thorpej 		for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
   1797  1.1  thorpej 			crc ^= *cp++;
   1798  1.1  thorpej 			crc = (crc >> 4) ^ crctab[crc & 0xf];
   1799  1.1  thorpej 			crc = (crc >> 4) ^ crctab[crc & 0xf];
   1800  1.1  thorpej 		}
   1801  1.1  thorpej 		/* Just want the 7 most significant bits. */
   1802  1.1  thorpej 		crc >>= 25;
   1803  1.1  thorpej 
   1804  1.1  thorpej 		/* Set the corresponding bit in the hash table. */
   1805  1.1  thorpej 		mchash[crc >> 4] |= 1 << (crc & 0xf);
   1806  1.1  thorpej 
   1807  1.1  thorpej 		ETHER_NEXT_MULTI(step, enm);
   1808  1.1  thorpej 	}
   1809  1.1  thorpej 
   1810  1.1  thorpej 	ifp->if_flags &= ~IFF_ALLMULTI;
   1811  1.1  thorpej 	goto setit;
   1812  1.1  thorpej 
   1813  1.1  thorpej  allmulti:
   1814  1.1  thorpej 	ifp->if_flags |= IFF_ALLMULTI;
   1815  1.1  thorpej 	sc->sc_rfcr |= RFCR_AAM;
   1816  1.1  thorpej 
   1817  1.1  thorpej  setit:
   1818  1.1  thorpej #define	FILTER_EMIT(addr, data)						\
   1819  1.1  thorpej 	bus_space_write_4(st, sh, SIP_RFCR, (addr));			\
   1820  1.1  thorpej 	bus_space_write_4(st, sh, SIP_RFDR, (data))
   1821  1.1  thorpej 
   1822  1.1  thorpej 	/*
   1823  1.1  thorpej 	 * Disable receive filter, and program the node address.
   1824  1.1  thorpej 	 */
   1825  1.1  thorpej 	cp = LLADDR(ifp->if_sadl);
   1826  1.1  thorpej 	FILTER_EMIT(RFCR_RFADDR_NODE0, (cp[1] << 8) | cp[0]);
   1827  1.1  thorpej 	FILTER_EMIT(RFCR_RFADDR_NODE2, (cp[3] << 8) | cp[2]);
   1828  1.1  thorpej 	FILTER_EMIT(RFCR_RFADDR_NODE4, (cp[5] << 8) | cp[4]);
   1829  1.1  thorpej 
   1830  1.1  thorpej 	if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
   1831  1.1  thorpej 		/*
   1832  1.1  thorpej 		 * Program the multicast hash table.
   1833  1.1  thorpej 		 */
   1834  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC0, mchash[0]);
   1835  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC1, mchash[1]);
   1836  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC2, mchash[2]);
   1837  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC3, mchash[3]);
   1838  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC4, mchash[4]);
   1839  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC5, mchash[5]);
   1840  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC6, mchash[6]);
   1841  1.1  thorpej 		FILTER_EMIT(RFCR_RFADDR_MC7, mchash[7]);
   1842  1.1  thorpej 	}
   1843  1.1  thorpej #undef FILTER_EMIT
   1844  1.1  thorpej 
   1845  1.1  thorpej 	/*
   1846  1.1  thorpej 	 * Re-enable the receiver filter.
   1847  1.1  thorpej 	 */
   1848  1.1  thorpej 	bus_space_write_4(st, sh, SIP_RFCR, sc->sc_rfcr);
   1849  1.1  thorpej }
   1850  1.1  thorpej 
   1851  1.1  thorpej /*
   1852  1.1  thorpej  * sip_mii_readreg:	[mii interface function]
   1853  1.1  thorpej  *
   1854  1.1  thorpej  *	Read a PHY register on the MII.
   1855  1.1  thorpej  */
   1856  1.1  thorpej int
   1857  1.1  thorpej sip_mii_readreg(self, phy, reg)
   1858  1.1  thorpej 	struct device *self;
   1859  1.1  thorpej 	int phy, reg;
   1860  1.1  thorpej {
   1861  1.1  thorpej 	struct sip_softc *sc = (struct sip_softc *) self;
   1862  1.1  thorpej 	u_int32_t enphy;
   1863  1.1  thorpej 
   1864  1.1  thorpej 	/*
   1865  1.1  thorpej 	 * The SiS 900 has only an internal PHY on the MII.  Only allow
   1866  1.1  thorpej 	 * MII address 0.
   1867  1.1  thorpej 	 */
   1868  1.1  thorpej 	if (phy != 0)
   1869  1.1  thorpej 		return (0);
   1870  1.1  thorpej 
   1871  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
   1872  1.1  thorpej 	    (reg << ENPHY_REGADDR_SHIFT) | ENPHY_RWCMD | ENPHY_ACCESS);
   1873  1.1  thorpej 	do {
   1874  1.1  thorpej 		enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
   1875  1.1  thorpej 	} while (enphy & ENPHY_ACCESS);
   1876  1.1  thorpej 	return ((enphy & ENPHY_PHYDATA) >> ENPHY_DATA_SHIFT);
   1877  1.1  thorpej }
   1878  1.1  thorpej 
   1879  1.1  thorpej /*
   1880  1.1  thorpej  * sip_mii_writereg:	[mii interface function]
   1881  1.1  thorpej  *
   1882  1.1  thorpej  *	Write a PHY register on the MII.
   1883  1.1  thorpej  */
   1884  1.1  thorpej void
   1885  1.1  thorpej sip_mii_writereg(self, phy, reg, val)
   1886  1.1  thorpej 	struct device *self;
   1887  1.1  thorpej 	int phy, reg, val;
   1888  1.1  thorpej {
   1889  1.1  thorpej 	struct sip_softc *sc = (struct sip_softc *) self;
   1890  1.1  thorpej 	u_int32_t enphy;
   1891  1.1  thorpej 
   1892  1.1  thorpej 	/*
   1893  1.1  thorpej 	 * The SiS 900 has only an internal PHY on the MII.  Only allow
   1894  1.1  thorpej 	 * MII address 0.
   1895  1.1  thorpej 	 */
   1896  1.1  thorpej 	if (phy != 0)
   1897  1.1  thorpej 		return;
   1898  1.1  thorpej 
   1899  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
   1900  1.1  thorpej 	    (val << ENPHY_DATA_SHIFT) | (reg << ENPHY_REGADDR_SHIFT) |
   1901  1.1  thorpej 	    ENPHY_ACCESS);
   1902  1.1  thorpej 	do {
   1903  1.1  thorpej 		enphy = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_ENPHY);
   1904  1.1  thorpej 	} while (enphy & ENPHY_ACCESS);
   1905  1.1  thorpej }
   1906  1.1  thorpej 
   1907  1.1  thorpej /*
   1908  1.1  thorpej  * sip_mii_statchg:	[mii interface function]
   1909  1.1  thorpej  *
   1910  1.1  thorpej  *	Callback from MII layer when media changes.
   1911  1.1  thorpej  */
   1912  1.1  thorpej void
   1913  1.1  thorpej sip_mii_statchg(self)
   1914  1.1  thorpej 	struct device *self;
   1915  1.1  thorpej {
   1916  1.1  thorpej 	struct sip_softc *sc = (struct sip_softc *) self;
   1917  1.1  thorpej 	u_int32_t flowctl;
   1918  1.1  thorpej 
   1919  1.1  thorpej 	/*
   1920  1.1  thorpej 	 * Update TXCFG for full-duplex operation.
   1921  1.1  thorpej 	 */
   1922  1.1  thorpej 	if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0)
   1923  1.1  thorpej 		sc->sc_txcfg |= (TXCFG_CSI | TXCFG_HBI);
   1924  1.1  thorpej 	else
   1925  1.1  thorpej 		sc->sc_txcfg &= ~(TXCFG_CSI | TXCFG_HBI);
   1926  1.1  thorpej 
   1927  1.1  thorpej 	/*
   1928  1.1  thorpej 	 * Update RXCFG for full-duplex or loopback.
   1929  1.1  thorpej 	 */
   1930  1.1  thorpej 	if ((sc->sc_mii.mii_media_active & IFM_FDX) != 0 ||
   1931  1.1  thorpej 	    IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_LOOP)
   1932  1.1  thorpej 		sc->sc_rxcfg |= RXCFG_ATX;
   1933  1.1  thorpej 	else
   1934  1.1  thorpej 		sc->sc_rxcfg &= ~RXCFG_ATX;
   1935  1.1  thorpej 
   1936  1.1  thorpej 	/*
   1937  1.1  thorpej 	 * Update IMR for use of 802.3x flow control.
   1938  1.1  thorpej 	 */
   1939  1.1  thorpej 	if ((sc->sc_mii.mii_media_active & IFM_FLOW) != 0) {
   1940  1.1  thorpej 		sc->sc_imr |= (ISR_PAUSE_END|ISR_PAUSE_ST);
   1941  1.1  thorpej 		flowctl = FLOWCTL_FLOWEN;
   1942  1.1  thorpej 	} else {
   1943  1.1  thorpej 		sc->sc_imr &= ~(ISR_PAUSE_END|ISR_PAUSE_ST);
   1944  1.1  thorpej 		flowctl = 0;
   1945  1.1  thorpej 	}
   1946  1.1  thorpej 
   1947  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXCFG, sc->sc_txcfg);
   1948  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXCFG, sc->sc_rxcfg);
   1949  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IMR, sc->sc_imr);
   1950  1.1  thorpej 	bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_FLOWCTL, flowctl);
   1951  1.1  thorpej 
   1952  1.1  thorpej 	/* XXX Update ifp->if_baudrate */
   1953  1.1  thorpej }
   1954  1.1  thorpej 
   1955  1.1  thorpej /*
   1956  1.1  thorpej  * sip_mediastatus:	[ifmedia interface function]
   1957  1.1  thorpej  *
   1958  1.1  thorpej  *	Get the current interface media status.
   1959  1.1  thorpej  */
   1960  1.1  thorpej void
   1961  1.1  thorpej sip_mediastatus(ifp, ifmr)
   1962  1.1  thorpej 	struct ifnet *ifp;
   1963  1.1  thorpej 	struct ifmediareq *ifmr;
   1964  1.1  thorpej {
   1965  1.1  thorpej 	struct sip_softc *sc = ifp->if_softc;
   1966  1.1  thorpej 
   1967  1.1  thorpej 	mii_pollstat(&sc->sc_mii);
   1968  1.1  thorpej 	ifmr->ifm_status = sc->sc_mii.mii_media_status;
   1969  1.1  thorpej 	ifmr->ifm_active = sc->sc_mii.mii_media_active;
   1970  1.1  thorpej }
   1971  1.1  thorpej 
   1972  1.1  thorpej /*
   1973  1.1  thorpej  * sip_mediachange:	[ifmedia interface function]
   1974  1.1  thorpej  *
   1975  1.1  thorpej  *	Set hardware to newly-selected media.
   1976  1.1  thorpej  */
   1977  1.1  thorpej int
   1978  1.1  thorpej sip_mediachange(ifp)
   1979  1.1  thorpej 	struct ifnet *ifp;
   1980  1.1  thorpej {
   1981  1.1  thorpej 	struct sip_softc *sc = ifp->if_softc;
   1982  1.1  thorpej 
   1983  1.1  thorpej 	if (ifp->if_flags & IFF_UP)
   1984  1.1  thorpej 		mii_mediachg(&sc->sc_mii);
   1985  1.1  thorpej 	return (0);
   1986  1.1  thorpej }
   1987