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