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