Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic A new DP83932 ``SONIC'' driver, which uses bus_dm...



details:   https://anonhg.NetBSD.org/src/rev/0efd72bd0243
branches:  trunk
changeset: 512096:0efd72bd0243
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Thu Jul 05 14:37:41 2001 +0000

description:
A new DP83932 ``SONIC'' driver, which uses bus_dma(9) and does I/O
directly to mbufs.  Handles both 32-bit and 16-bit, big- and little-
endian configurations of the chip (we could squeeze out some conditionals
yet, though).

diffstat:

 sys/dev/ic/dp83932.c    |  1208 +++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/ic/dp83932reg.h |   347 +++++++++++++
 sys/dev/ic/dp83932var.h |   376 ++++++++++++++
 3 files changed, 1931 insertions(+), 0 deletions(-)

diffs (truncated from 1943 to 300 lines):

diff -r 037dd2e54b5f -r 0efd72bd0243 sys/dev/ic/dp83932.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/dp83932.c      Thu Jul 05 14:37:41 2001 +0000
@@ -0,0 +1,1208 @@
+/*     $NetBSD: dp83932.c,v 1.1 2001/07/05 14:37:41 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 National Semiconductor DP83932
+ * Systems-Oriented Network Interface Controller (SONIC).
+ */
+
+#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 <uvm/uvm_extern.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_ether.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/ic/dp83932reg.h>
+#include <dev/ic/dp83932var.h>
+
+void   sonic_start(struct ifnet *);
+void   sonic_watchdog(struct ifnet *);
+int    sonic_ioctl(struct ifnet *, u_long, caddr_t);
+int    sonic_init(struct ifnet *);
+void   sonic_stop(struct ifnet *, int);
+
+void   sonic_shutdown(void *);
+
+void   sonic_reset(struct sonic_softc *);
+void   sonic_rxdrain(struct sonic_softc *);
+int    sonic_add_rxbuf(struct sonic_softc *, int);
+void   sonic_set_filter(struct sonic_softc *);
+
+uint16_t sonic_txintr(struct sonic_softc *);
+void   sonic_rxintr(struct sonic_softc *);
+
+int    sonic_copy_small = 0;
+
+/*
+ * sonic_attach:
+ *
+ *     Attach a SONIC interface to the system.
+ */
+void
+sonic_attach(struct sonic_softc *sc, const uint8_t *enaddr)
+{
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       int i, rseg, error;
+       bus_dma_segment_t seg;
+       size_t cdatasize;
+
+       /*
+        * Allocate the control data structures, and create and load the
+        * DMA map for it.
+        */
+       if (sc->sc_32bit)
+               cdatasize = sizeof(struct sonic_control_data32);
+       else
+               cdatasize = sizeof(struct sonic_control_data16);
+
+       if ((error = bus_dmamem_alloc(sc->sc_dmat, cdatasize,
+            PAGE_SIZE, (64 * 1024), &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,
+           cdatasize, (caddr_t *) &sc->sc_cdata16,
+           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,
+            cdatasize, 1, cdatasize, 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_cdata16, cdatasize, 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 < SONIC_NTXDESC; i++) {
+               if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+                    SONIC_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 < SONIC_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;
+               }
+               sc->sc_rxsoft[i].ds_mbuf = NULL;
+       }
+
+       /*
+        * Reset the chip to a known state.
+        */
+       sonic_reset(sc);
+
+       printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
+           ether_sprintf(enaddr));
+
+       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 = sonic_ioctl;
+       ifp->if_start = sonic_start;
+       ifp->if_watchdog = sonic_watchdog;
+       ifp->if_init = sonic_init;
+       ifp->if_stop = sonic_stop;
+       IFQ_SET_READY(&ifp->if_snd);
+
+       /*
+        * Attach the interface.
+        */
+       if_attach(ifp);
+       ether_ifattach(ifp, enaddr);
+
+       /*
+        * Make sure the interface is shutdown during reboot.
+        */
+       sc->sc_sdhook = shutdownhook_establish(sonic_shutdown, sc);
+       if (sc->sc_sdhook == NULL)
+               printf("%s: WARNING: unable to establish shutdown hook\n",
+                   sc->sc_dev.dv_xname);
+       return;
+
+       /*
+        * Free any resources we've allocated during the failed attach
+        * attempt.  Do this in reverse order and fall through.
+        */
+ fail_5:
+       for (i = 0; i < SONIC_NRXDESC; i++) {
+               if (sc->sc_rxsoft[i].ds_dmamap != NULL)
+                       bus_dmamap_destroy(sc->sc_dmat,
+                           sc->sc_rxsoft[i].ds_dmamap);
+       }
+ fail_4:
+       for (i = 0; i < SONIC_NTXDESC; i++) {
+               if (sc->sc_txsoft[i].ds_dmamap != NULL)
+                       bus_dmamap_destroy(sc->sc_dmat,
+                           sc->sc_txsoft[i].ds_dmamap);
+       }
+       bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
+ fail_3:
+       bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
+ fail_2:
+       bus_dmamem_unmap(sc->sc_dmat, (caddr_t) sc->sc_cdata16, cdatasize);
+ fail_1:
+       bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ fail_0:
+       return;
+}
+
+/*
+ * sonic_shutdown:
+ *
+ *     Make sure the interface is stopped at reboot.
+ */
+void
+sonic_shutdown(void *arg)
+{
+       struct sonic_softc *sc = arg;
+
+       sonic_stop(&sc->sc_ethercom.ec_if, 1);
+}
+
+/*
+ * sonic_start:                [ifnet interface function]
+ *
+ *     Start packet transmission on the interface.
+ */
+void
+sonic_start(struct ifnet *ifp)
+{
+       struct sonic_softc *sc = ifp->if_softc;
+       struct mbuf *m0, *m;
+       struct sonic_tda16 *tda16;
+       struct sonic_tda32 *tda32;
+       struct sonic_descsoft *ds;
+       bus_dmamap_t dmamap;
+       int error, olasttx, nexttx, opending, seg, totlen, olseg;
+
+       if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
+               return;
+
+       /*
+        * Remember the previous txpending and the current "last txdesc
+        * used" index.
+        */
+       opending = sc->sc_txpending;
+       olasttx = sc->sc_txlast;
+
+       /*
+        * Loop through the send queue, setting up transmit descriptors
+        * until we drain the queue, or use up all available transmit
+        * descriptors.  Leave one at the end for sanity's sake.
+        */
+       while (sc->sc_txpending < (SONIC_NTXDESC - 1)) {
+               /*
+                * Grab a packet off the queue.
+                */
+               IFQ_POLL(&ifp->if_snd, m0);
+               if (m0 == NULL)
+                       break;
+               m = NULL;
+
+               /*
+                * Get the next available transmit descriptor.
+                */
+               nexttx = SONIC_NEXTTX(sc->sc_txlast);
+               ds = &sc->sc_txsoft[nexttx];
+               dmamap = ds->ds_dmamap;
+
+               /*
+                * Load the DMA map.  If this fails, the packet either
+                * didn't fit in the allotted number of frags, or we were
+                * short on resources.  In this case, we'll copy and try
+                * again.
+                */
+               if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,



Home | Main Index | Thread Index | Old Index