Source-Changes-HG archive

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

[src/trunk]: src/sys/dev Add support for the Adaptec AIC-6915 10/100 Ethernet...



details:   https://anonhg.NetBSD.org/src/rev/9ace0916a16e
branches:  trunk
changeset: 511378:9ace0916a16e
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Mon Jun 18 22:05:35 2001 +0000

description:
Add support for the Adaptec AIC-6915 10/100 Ethernet.  This is
a 64-bit PCI chip, available in 1, 2, and 4 port models.

diffstat:

 sys/dev/ic/aic6915.c    |  1469 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/ic/aic6915reg.h |   686 +++++++++++++++++++++
 sys/dev/ic/aic6915var.h |   200 ++++++
 sys/dev/pci/if_sf_pci.c |   286 +++++++++
 4 files changed, 2641 insertions(+), 0 deletions(-)

diffs (truncated from 2657 to 300 lines):

diff -r 802375f7deab -r 9ace0916a16e sys/dev/ic/aic6915.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/aic6915.c      Mon Jun 18 22:05:35 2001 +0000
@@ -0,0 +1,1469 @@
+/*     $NetBSD: aic6915.c,v 1.1 2001/06/18 22:05:35 thorpej Exp $      */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ * 
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 THE NETBSD FOUNDATION, 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 Adaptec AIC-6915 (``Starfire'')
+ * 10/100 Ethernet controller.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/callout.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 <uvm/uvm_extern.h>
+
+#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
+ 
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/mii/miivar.h>
+
+#include <dev/ic/aic6915reg.h>
+#include <dev/ic/aic6915var.h>
+
+void   sf_start(struct ifnet *);
+void   sf_watchdog(struct ifnet *);
+int    sf_ioctl(struct ifnet *, u_long, caddr_t);
+int    sf_init(struct ifnet *);
+void   sf_stop(struct ifnet *, int);
+
+void   sf_shutdown(void *);
+
+void   sf_txintr(struct sf_softc *);
+void   sf_rxintr(struct sf_softc *);
+void   sf_stats_update(struct sf_softc *);
+
+void   sf_reset(struct sf_softc *);
+void   sf_macreset(struct sf_softc *);
+void   sf_rxdrain(struct sf_softc *);
+int    sf_add_rxbuf(struct sf_softc *, int);
+uint8_t        sf_read_eeprom(struct sf_softc *, int);
+void   sf_set_filter(struct sf_softc *);
+
+int    sf_mii_read(struct device *, int, int);
+void   sf_mii_write(struct device *, int, int, int);
+void   sf_mii_statchg(struct device *);
+
+void   sf_tick(void *);
+
+int    sf_mediachange(struct ifnet *);
+void   sf_mediastatus(struct ifnet *, struct ifmediareq *);
+
+int    sf_copy_small = 0;
+
+#define        sf_funcreg_read(sc, reg)                                        \
+       bus_space_read_4((sc)->sc_st, (sc)->sc_sh_func, (reg))
+#define        sf_funcreg_write(sc, reg, val)                                  \
+       bus_space_write_4((sc)->sc_st, (sc)->sc_sh_func, (reg), (val))
+
+static __inline uint32_t
+sf_reg_read(struct sf_softc *sc, bus_addr_t reg)
+{
+
+       if (__predict_false(sc->sc_iomapped)) {
+               bus_space_write_4(sc->sc_st, sc->sc_sh, SF_IndirectIoAccess,
+                   reg);
+               return (bus_space_read_4(sc->sc_st, sc->sc_sh,
+                   SF_IndirectIoDataPort));
+       }
+
+       return (bus_space_read_4(sc->sc_st, sc->sc_sh, reg));
+}
+
+static __inline void
+sf_reg_write(struct sf_softc *sc, bus_addr_t reg, uint32_t val)
+{
+
+       if (__predict_false(sc->sc_iomapped)) {
+               bus_space_write_4(sc->sc_st, sc->sc_sh, SF_IndirectIoAccess,
+                   reg);
+               bus_space_write_4(sc->sc_st, sc->sc_sh, SF_IndirectIoDataPort,
+                   val);
+               return;
+       }
+
+       bus_space_write_4(sc->sc_st, sc->sc_sh, reg, val);
+}
+
+#define        sf_genreg_read(sc, reg)                                         \
+       sf_reg_read((sc), (reg) + SF_GENREG_OFFSET)
+#define        sf_genreg_write(sc, reg, val)                                   \
+       sf_reg_write((sc), (reg) + SF_GENREG_OFFSET, (val))
+
+/*
+ * sf_attach:
+ *
+ *     Attach a Starfire interface to the system.
+ */
+void
+sf_attach(struct sf_softc *sc)
+{
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       int i, rseg, error;
+       bus_dma_segment_t seg;
+       u_int8_t enaddr[ETHER_ADDR_LEN];
+
+       callout_init(&sc->sc_tick_callout);
+
+       /*
+        * If we're I/O mapped, the functional register handle is
+        * the same as the base handle.  If we're memory mapped,
+        * carve off a chunk of the register space for the functional
+        * registers, to save on arithmetic later.
+        */
+       if (sc->sc_iomapped)
+               sc->sc_sh_func = sc->sc_sh;
+       else {
+               if ((error = bus_space_subregion(sc->sc_st, sc->sc_sh,
+                   SF_GENREG_OFFSET, SF_FUNCREG_SIZE, &sc->sc_sh_func)) != 0) {
+                       printf("%s: unable to sub-region functional "
+                           "registers, error = %d\n", sc->sc_dev.dv_xname,
+                           error);
+                       return;
+               }
+       }
+
+       /*
+        * Initialize the transmit threshold for this interface.  The
+        * manual describes the default as 4 * 16 bytes.  We start out
+        * at 10 * 16 bytes, to avoid a bunch of initial underruns on
+        * several platforms.
+        */
+       sc->sc_txthresh = 10;
+
+       /*
+        * Allocate the control data structures, and create and load the
+        * DMA map for it.
+        */
+       if ((error = bus_dmamem_alloc(sc->sc_dmat,
+           sizeof(struct sf_control_data), PAGE_SIZE, 0, &seg, 1, &rseg,
+           BUS_DMA_NOWAIT)) != 0) {
+               printf("%s: unable to allocate control data, error = %d\n",
+                   sc->sc_dev.dv_xname, error);
+               goto fail_0;
+       }
+
+       if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
+           sizeof(struct sf_control_data), (caddr_t *)&sc->sc_control_data,
+           BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+               printf("%s: unable to map control data, error = %d\n",
+                   sc->sc_dev.dv_xname, error);
+               goto fail_1;
+       }
+
+       if ((error = bus_dmamap_create(sc->sc_dmat,
+           sizeof(struct sf_control_data), 1,
+           sizeof(struct sf_control_data), 0, BUS_DMA_NOWAIT,
+           &sc->sc_cddmamap)) != 0) {
+               printf("%s: unable to create control data DMA map, "
+                   "error = %d\n", sc->sc_dev.dv_xname, error);
+               goto fail_2;
+       }
+
+       if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
+           sc->sc_control_data, sizeof(struct sf_control_data), NULL,
+           BUS_DMA_NOWAIT)) != 0) {
+               printf("%s: unable to load control data DMA map, error = %d\n",
+                   sc->sc_dev.dv_xname, error);
+               goto fail_3;
+       }
+
+       /*
+        * Create the transmit buffer DMA maps.
+        */
+       for (i = 0; i < SF_NTXDESC; i++) {
+               if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+                   SF_NTXFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
+                   &sc->sc_txsoft[i].ds_dmamap)) != 0) {
+                       printf("%s: unable to create tx DMA map %d, "
+                           "error = %d\n", sc->sc_dev.dv_xname, i, error);
+                       goto fail_4;
+               }
+       }
+
+       /*
+        * Create the receive buffer DMA maps.
+        */
+       for (i = 0; i < SF_NRXDESC; i++) {
+               if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
+                   MCLBYTES, 0, BUS_DMA_NOWAIT,
+                   &sc->sc_rxsoft[i].ds_dmamap)) != 0) {
+                       printf("%s: unable to create rx DMA map %d, "
+                           "error = %d\n", sc->sc_dev.dv_xname, i, error);
+                       goto fail_5;
+               }
+       }
+
+       /*
+        * Reset the chip to a known state.
+        */
+       sf_reset(sc);
+
+       /*
+        * Read the Ethernet address from the EEPROM.
+        */
+       for (i = 0; i < ETHER_ADDR_LEN; i++)
+               enaddr[i] = sf_read_eeprom(sc, (15 + (ETHER_ADDR_LEN - 1)) - i);
+
+       printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
+           ether_sprintf(enaddr));
+
+       if (sf_funcreg_read(sc, SF_PciDeviceConfig) & PDC_System64)
+               printf("%s: 64-bit PCI slot detected\n", sc->sc_dev.dv_xname);
+
+       /*
+        * Initialize our media structures and probe the MII.
+        */
+       sc->sc_mii.mii_ifp = ifp;
+       sc->sc_mii.mii_readreg = sf_mii_read;
+       sc->sc_mii.mii_writereg = sf_mii_write;
+       sc->sc_mii.mii_statchg = sf_mii_statchg;
+       ifmedia_init(&sc->sc_mii.mii_media, 0, sf_mediachange,
+           sf_mediastatus);
+       mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
+           MII_OFFSET_ANY, 0);
+       if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
+               ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
+               ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
+       } else
+               ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
+
+       strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
+       ifp->if_softc = sc;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_ioctl = sf_ioctl;
+       ifp->if_start = sf_start;
+       ifp->if_watchdog = sf_watchdog;
+       ifp->if_init = sf_init;
+       ifp->if_stop = sf_stop;
+       IFQ_SET_READY(&ifp->if_snd);
+
+       /*
+        * Attach the interface.
+        */
+       if_attach(ifp);



Home | Main Index | Thread Index | Old Index