Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Device driver for the Silicon Integrated Systems...



details:   https://anonhg.NetBSD.org/src/rev/47776ad90de7
branches:  trunk
changeset: 473403:47776ad90de7
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Tue Jun 01 18:19:13 1999 +0000

description:
Device driver for the Silicon Integrated Systems SiS900 10/100 Ethernet
chip, found on the IBM Netstation.

diffstat:

 sys/dev/pci/if_sip.c    |  1929 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/pci/if_sipreg.h |   314 +++++++
 2 files changed, 2243 insertions(+), 0 deletions(-)

diffs (truncated from 2251 to 300 lines):

diff -r 82f50c96df84 -r 47776ad90de7 sys/dev/pci/if_sip.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/if_sip.c      Tue Jun 01 18:19:13 1999 +0000
@@ -0,0 +1,1929 @@
+/*     $NetBSD: if_sip.c,v 1.1 1999/06/01 18:19:13 thorpej Exp $       */
+
+/*-
+ * Copyright (c) 1999 Network Computer, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Network Computer, Inc. nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETWORK COMPUTER, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Device driver for the Silicon Integrated Systems SiS900 10/100 PCI
+ * Ethernet controller.
+ *    
+ * Written by Jason R. Thorpe for Network Computer, Inc.
+ */
+
+#include "opt_inet.h"
+#include "opt_ns.h"
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/queue.h>
+
+#include <vm/vm.h>             /* for PAGE_SIZE */
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_ether.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_inarp.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/mii/miivar.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/pci/if_sipreg.h>
+
+/*
+ * Devices supported by this driver.
+ */
+const struct sip_product {
+       pci_vendor_id_t         sip_vendor;
+       pci_product_id_t        sip_product;
+       const char              *sip_name;
+} sip_products[] = {
+       { PCI_VENDOR_SIS,       PCI_PRODUCT_SIS_900,
+         "SiS 900 10/100 Ethernet" },
+
+       { 0,                    0,
+         NULL },
+};
+
+/*
+ * Transmit descriptor list size.  This is arbitrary, but allocate
+ * enough descriptors for 64 pending transmissions, and 16 segments
+ * per packet.  This MUST work out to a power of 2.
+ */
+#define        SIP_NTXSEGS             16
+
+#define        SIP_TXQUEUELEN          64
+#define        SIP_NTXDESC             (SIP_TXQUEUELEN * SIP_NTXSEGS)
+#define        SIP_NTXDESC_MASK        (SIP_NTXDESC - 1)
+#define        SIP_NEXTTX(x)           (((x) + 1) & SIP_NTXDESC_MASK)
+
+/*
+ * Receive descriptor list size.  We have one Rx buffer per incoming
+ * packet, so this logic is a little simpler.
+ */
+#define        SIP_NRXDESC             64
+#define        SIP_NRXDESC_MASK        (SIP_NRXDESC - 1)
+#define        SIP_NEXTRX(x)           (((x) + 1) & SIP_NRXDESC_MASK)
+
+/*
+ * Control structures are DMA'd to the SiS900 chip.  We allocate them in
+ * a single clump that maps to a single DMA segment to make several things
+ * easier.
+ */
+struct sip_control_data {
+       /*
+        * The transmit descriptors.
+        */
+       struct sip_desc scd_txdescs[SIP_NTXDESC];
+
+       /*
+        * The receive descriptors.
+        */
+       struct sip_desc scd_rxdescs[SIP_NRXDESC];
+};
+
+#define        SIP_CDOFF(x)    offsetof(struct sip_control_data, x)
+#define        SIP_CDTXOFF(x)  SIP_CDOFF(scd_txdescs[(x)])
+#define        SIP_CDRXOFF(x)  SIP_CDOFF(scd_rxdescs[(x)])
+
+/*
+ * Software state for transmit jobs.
+ */
+struct sip_txsoft {
+       struct mbuf *txs_mbuf;          /* head of our mbuf chain */
+       bus_dmamap_t txs_dmamap;        /* our DMA map */
+       int txs_firstdesc;              /* first descriptor in packet */
+       int txs_lastdesc;               /* last descriptor in packet */
+       SIMPLEQ_ENTRY(sip_txsoft) txs_q;
+};
+
+SIMPLEQ_HEAD(sip_txsq, sip_txsoft);
+
+/*
+ * Software state for receive jobs.
+ */
+struct sip_rxsoft {
+       struct mbuf *rxs_mbuf;          /* head of our mbuf chain */
+       bus_dmamap_t rxs_dmamap;        /* our DMA map */
+};
+
+/*
+ * Software state per device.
+ */
+struct sip_softc {
+       struct device sc_dev;           /* generic device information */
+       bus_space_tag_t sc_st;          /* bus space tag */
+       bus_space_handle_t sc_sh;       /* bus space handle */
+       bus_dma_tag_t sc_dmat;          /* bus DMA tag */
+       struct ethercom sc_ethercom;    /* ethernet common data */
+       void *sc_sdhook;                /* shutdown hook */
+
+       void *sc_ih;                    /* interrupt cookie */
+
+       struct mii_data sc_mii;         /* MII/media information */
+
+       bus_dmamap_t sc_cddmamap;       /* control data DMA map */
+#define        sc_cddma        sc_cddmamap->dm_segs[0].ds_addr
+
+       /*
+        * Software state for transmit and receive descriptors.
+        */
+       struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN];
+       struct sip_rxsoft sc_rxsoft[SIP_NRXDESC];
+
+       /*
+        * Control data structures.
+        */
+       struct sip_control_data *sc_control_data;
+#define        sc_txdescs      sc_control_data->scd_txdescs
+#define        sc_rxdescs      sc_control_data->scd_rxdescs
+
+       u_int32_t sc_txcfg;             /* prototype TXCFG register */
+       u_int32_t sc_rxcfg;             /* prototype RXCFG register */
+       u_int32_t sc_imr;               /* prototype IMR register */
+       u_int32_t sc_rfcr;              /* prototype RFCR register */
+
+       u_int32_t sc_tx_fill_thresh;    /* transmit fill threshold */
+       u_int32_t sc_tx_drain_thresh;   /* transmit drain threshold */
+
+       u_int32_t sc_rx_drain_thresh;   /* receive drain threshold */
+
+       int     sc_flags;               /* misc. flags; see below */
+
+       int     sc_txfree;              /* number of free Tx descriptors */
+       int     sc_txnext;              /* next ready Tx descriptor */
+
+       struct sip_txsq sc_txfreeq;     /* free Tx descsofts */
+       struct sip_txsq sc_txdirtyq;    /* dirty Tx descsofts */
+
+       int     sc_rxptr;               /* next ready Rx descriptor/descsoft */
+};
+
+/* sc_flags */
+#define        SIPF_PAUSED     0x00000001      /* paused (802.3x flow control) */
+
+#define        SIP_CDTXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDTXOFF((x)))
+#define        SIP_CDRXADDR(sc, x)     ((sc)->sc_cddma + SIP_CDRXOFF((x)))
+
+#define        SIP_CDTXSYNC(sc, x, n, ops)                                     \
+do {                                                                   \
+       int __x, __n;                                                   \
+                                                                       \
+       __x = (x);                                                      \
+       __n = (n);                                                      \
+                                                                       \
+       /* If it will wrap around, sync to the end of the ring. */      \
+       if ((__x + __n) > SIP_NTXDESC) {                                \
+               bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,       \
+                   SIP_CDTXOFF(__x), sizeof(struct sip_desc) *         \
+                   (SIP_NTXDESC - __x), (ops));                        \
+               __n -= (SIP_NTXDESC - __x);                             \
+               __x = 0;                                                \
+       }                                                               \
+                                                                       \
+       /* Now sync whatever is left. */                                \
+       bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,               \
+           SIP_CDTXOFF(__x), sizeof(struct sip_desc) * __n, (ops));    \
+} while (0)
+
+#define        SIP_CDRXSYNC(sc, x, ops)                                        \
+       bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap,               \
+           SIP_CDRXOFF((x)), sizeof(struct sip_desc), (ops))
+
+/*
+ * Note we rely on MCLBYTES being a power of two below.
+ */
+#define        SIP_INIT_RXDESC(sc, x)                                          \
+do {                                                                   \
+       struct sip_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)];               \
+       struct sip_desc *__sipd = &(sc)->sc_rxdescs[(x)];               \
+                                                                       \
+       __sipd->sipd_link = SIP_CDRXADDR((sc), SIP_NEXTRX((x)));        \
+       __sipd->sipd_bufptr = __rxs->rxs_dmamap->dm_segs[0].ds_addr;    \
+       __sipd->sipd_cmdsts = CMDSTS_INTR |                             \
+           ((MCLBYTES - 1) & CMDSTS_SIZE_MASK);                        \
+       SIP_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
+} while (0)
+
+void   sip_start __P((struct ifnet *));
+void   sip_watchdog __P((struct ifnet *));
+int    sip_ioctl __P((struct ifnet *, u_long, caddr_t));
+
+void   sip_shutdown __P((void *));
+
+void   sip_reset __P((struct sip_softc *));
+void   sip_init __P((struct sip_softc *));
+void   sip_stop __P((struct sip_softc *));
+int    sip_add_rxbuf __P((struct sip_softc *, int));
+void   sip_read_eeprom __P((struct sip_softc *, int, int, u_int16_t *));
+void   sip_set_filter __P((struct sip_softc *));
+void   sip_tick __P((void *));
+
+int    sip_intr __P((void *));
+void   sip_txintr __P((struct sip_softc *));
+void   sip_rxintr __P((struct sip_softc *));
+
+int    sip_mii_readreg __P((struct device *, int, int));
+void   sip_mii_writereg __P((struct device *, int, int, int));
+void   sip_mii_statchg __P((struct device *));
+
+int    sip_mediachange __P((struct ifnet *));
+void   sip_mediastatus __P((struct ifnet *, struct ifmediareq *));
+
+int    sip_match __P((struct device *, struct cfdata *, void *));
+void   sip_attach __P((struct device *, struct device *, void *));
+
+struct cfattach sip_ca = {
+       sizeof(struct sip_softc), sip_match, sip_attach,
+};
+
+const struct sip_product *sip_lookup __P((const struct pci_attach_args *));
+
+const struct sip_product *
+sip_lookup(pa)



Home | Main Index | Thread Index | Old Index