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