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