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