summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/sbus/dma_sbus.c281
-rw-r--r--sys/dev/sbus/files.sbus26
-rw-r--r--sys/dev/sbus/if_le.c287
-rw-r--r--sys/dev/sbus/if_le_ledma.c451
-rw-r--r--sys/dev/sbus/lebuffervar.h50
5 files changed, 1095 insertions, 0 deletions
diff --git a/sys/dev/sbus/dma_sbus.c b/sys/dev/sbus/dma_sbus.c
new file mode 100644
index 00000000000..2b435244a42
--- /dev/null
+++ b/sys/dev/sbus/dma_sbus.c
@@ -0,0 +1,281 @@
+/* $NetBSD: dma_sbus.c,v 1.5 2000/07/09 20:57:42 pk Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1994 Peter Galbavy. 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Peter Galbavy.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/autoconf.h>
+
+#include <dev/sbus/sbusvar.h>
+
+#include <dev/ic/lsi64854reg.h>
+#include <dev/ic/lsi64854var.h>
+
+#include <scsi/scsi_all.h>
+#include <scsi/scsiconf.h>
+
+#include <dev/ic/ncr53c9xreg.h>
+#include <dev/ic/ncr53c9xvar.h>
+
+struct dma_softc {
+ struct lsi64854_softc sc_lsi64854; /* base device */
+ struct sbusdev sc_sd; /* sbus device */
+};
+
+int dmamatch_sbus __P((struct device *, void *, void *));
+void dmaattach_sbus __P((struct device *, struct device *, void *));
+
+int dmaprint_sbus __P((void *, const char *));
+
+void *dmabus_intr_establish __P((
+ bus_space_tag_t,
+ int, /*bus interrupt priority*/
+ int, /*`device class' level*/
+ int, /*flags*/
+ int (*) __P((void *)), /*handler*/
+ void *)); /*handler arg*/
+
+static bus_space_tag_t dma_alloc_bustag __P((struct dma_softc *sc));
+
+struct cfattach dma_sbus_ca = {
+ sizeof(struct dma_softc), dmamatch_sbus, dmaattach_sbus
+};
+
+struct cfattach ledma_ca = {
+ sizeof(struct dma_softc), dmamatch_sbus, dmaattach_sbus
+};
+
+struct cfdriver ledma_cd = {
+ NULL, "ledma", DV_DULL
+};
+
+int
+dmaprint_sbus(aux, busname)
+ void *aux;
+ const char *busname;
+{
+ struct sbus_attach_args *sa = aux;
+ bus_space_tag_t t = sa->sa_bustag;
+ struct dma_softc *sc = t->cookie;
+
+ sa->sa_bustag = sc->sc_lsi64854.sc_bustag; /* XXX */
+ sbus_print(aux, busname); /* XXX */
+ sa->sa_bustag = t; /* XXX */
+ return (UNCONF);
+}
+
+int
+dmamatch_sbus(parent, vcf, aux)
+ struct device *parent;
+ void *vcf;
+ void *aux;
+{
+ struct cfdata *cf = vcf;
+ struct sbus_attach_args *sa = aux;
+
+ return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
+ strcmp("espdma", sa->sa_name) == 0);
+}
+
+void
+dmaattach_sbus(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct sbus_attach_args *sa = aux;
+ struct dma_softc *dsc = (void *)self;
+ struct lsi64854_softc *sc = &dsc->sc_lsi64854;
+ bus_space_handle_t bh;
+ bus_space_tag_t sbt;
+ int sbusburst, burst;
+ int node;
+
+ node = sa->sa_node;
+
+ sc->sc_bustag = sa->sa_bustag;
+ sc->sc_dmatag = sa->sa_dmatag;
+
+ /* Map registers */
+ if (sa->sa_npromvaddrs != 0)
+ sc->sc_regs = (bus_space_handle_t)sa->sa_promvaddrs[0];
+ else {
+ if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
+ sa->sa_offset,
+ sa->sa_size,
+ 0, 0, &bh) != 0) {
+ printf("%s: cannot map registers\n", self->dv_xname);
+ return;
+ }
+ sc->sc_regs = bh;
+ }
+
+ /*
+ * Get transfer burst size from PROM and plug it into the
+ * controller registers. This is needed on the Sun4m; do
+ * others need it too?
+ */
+ sbusburst = ((struct sbus_softc *)parent)->sc_burst;
+ if (sbusburst == 0)
+ sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
+
+ burst = getpropint(node,"burst-sizes", -1);
+ if (burst == -1)
+ /* take SBus burst sizes */
+ burst = sbusburst;
+
+ /* Clamp at parent's burst sizes */
+ burst &= sbusburst;
+ sc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
+ (burst & SBUS_BURST_16) ? 16 : 0;
+
+ if (sc->sc_dev.dv_cfdata->cf_attach == &ledma_ca) {
+ char *cabletype;
+ u_int32_t csr;
+ /*
+ * Check to see which cable type is currently active and
+ * set the appropriate bit in the ledma csr so that it
+ * gets used. If we didn't netboot, the PROM won't have
+ * the "cable-selection" property; default to TP and then
+ * the user can change it via a "media" option to ifconfig.
+ */
+ cabletype = getpropstring(node, "cable-selection");
+ csr = L64854_GCSR(sc);
+ if (strcmp(cabletype, "tpe") == 0) {
+ csr |= E_TP_AUI;
+ } else if (strcmp(cabletype, "aui") == 0) {
+ csr &= ~E_TP_AUI;
+ } else {
+ /* assume TP if nothing there */
+ csr |= E_TP_AUI;
+ }
+ L64854_SCSR(sc, csr);
+ delay(20000); /* manual says we need a 20ms delay */
+ sc->sc_channel = L64854_CHANNEL_ENET;
+ } else {
+ sc->sc_channel = L64854_CHANNEL_SCSI;
+ }
+
+ sbus_establish(&dsc->sc_sd, &sc->sc_dev);
+ sbt = dma_alloc_bustag(dsc);
+ lsi64854_attach(sc);
+
+ /* Attach children */
+ for (node = firstchild(sa->sa_node); node; node = nextsibling(node)) {
+ struct sbus_attach_args sa;
+ sbus_setup_attach_args((struct sbus_softc *)parent,
+ sbt, sc->sc_dmatag, node, &sa);
+ (void) config_found(&sc->sc_dev, (void *)&sa, dmaprint_sbus);
+ sbus_destroy_attach_args(&sa);
+ }
+}
+
+void *
+dmabus_intr_establish(t, pri, level, flags, handler, arg)
+ bus_space_tag_t t;
+ int pri;
+ int level;
+ int flags;
+ int (*handler) __P((void *));
+ void *arg;
+{
+ struct lsi64854_softc *sc = t->cookie;
+
+ /* XXX - for now only le; do esp later */
+ if (sc->sc_channel == L64854_CHANNEL_ENET) {
+ sc->sc_intrchain = handler;
+ sc->sc_intrchainarg = arg;
+ handler = lsi64854_enet_intr;
+ arg = sc;
+ }
+ return (bus_intr_establish(sc->sc_bustag, pri, level, flags,
+ handler, arg));
+}
+
+bus_space_tag_t
+dma_alloc_bustag(sc)
+ struct dma_softc *sc;
+{
+ bus_space_tag_t sbt;
+
+ sbt = (bus_space_tag_t)
+ malloc(sizeof(struct sparc_bus_space_tag), M_DEVBUF, M_NOWAIT);
+ if (sbt == NULL)
+ return (NULL);
+
+ bzero(sbt, sizeof *sbt);
+ sbt->cookie = sc;
+ sbt->parent = sc->sc_lsi64854.sc_bustag;
+ sbt->sparc_intr_establish = dmabus_intr_establish;
+ return (sbt);
+}
diff --git a/sys/dev/sbus/files.sbus b/sys/dev/sbus/files.sbus
new file mode 100644
index 00000000000..338e0cc4c51
--- /dev/null
+++ b/sys/dev/sbus/files.sbus
@@ -0,0 +1,26 @@
+# $NetBSD: files.sbus,v 1.16 2000/12/08 17:29:12 martin Exp $
+#
+# Config file and device description for machine-independent SBUS code.
+# Included by ports that need it.
+
+device sbus { slot = -1, offset = -1 }
+#notyet:file dev/sbus/sbus.c sbus
+
+# Sbus NCR539x SCSI & Lance Ethernet
+device dma {}: lsi64854
+attach dma at sbus with dma_sbus
+device ledma {}: lsi64854
+attach ledma at sbus
+file dev/sbus/dma_sbus.c dma_sbus | ledma
+
+device lebuffer {}
+attach lebuffer at sbus
+file dev/sbus/lebuffer.c lebuffer
+
+# device definition in sys/conf/files
+attach le at sbus with le_sbus
+attach le at lebuffer with le_lebuffer
+attach le at ledma with le_ledma
+file dev/sbus/if_le.c le_sbus
+file dev/sbus/if_le_lebuffer.c le_lebuffer
+file dev/sbus/if_le_ledma.c le_ledma
diff --git a/sys/dev/sbus/if_le.c b/sys/dev/sbus/if_le.c
new file mode 100644
index 00000000000..f127570c5dd
--- /dev/null
+++ b/sys/dev/sbus/if_le.c
@@ -0,0 +1,287 @@
+/* $NetBSD: if_le.c,v 1.17 2001/05/30 11:46:35 mrg Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
+ *
+ * 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.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/autoconf.h>
+
+#include <dev/sbus/sbusvar.h>
+#include <dev/sbus/lebuffervar.h> /*XXX*/
+
+#include <dev/ic/lancereg.h>
+#include <dev/ic/lancevar.h>
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+/*
+ * LANCE registers.
+ */
+#define LEREG1_RDP 0 /* Register Data port */
+#define LEREG1_RAP 2 /* Register Address port */
+
+struct le_softc {
+ struct am7990_softc sc_am7990; /* glue to MI code */
+ struct sbusdev sc_sd; /* sbus device */
+ bus_space_tag_t sc_bustag;
+ bus_dma_tag_t sc_dmatag;
+ bus_dmamap_t sc_dmamap;
+ bus_space_handle_t sc_reg;
+};
+
+#define MEMSIZE 0x4000 /* LANCE memory size */
+
+int lematch_sbus __P((struct device *, void *, void *));
+void leattach_sbus __P((struct device *, struct device *, void *));
+
+/*
+ * Media types supported.
+ */
+struct cfattach le_sbus_ca = {
+ sizeof(struct le_softc), lematch_sbus, leattach_sbus
+};
+
+extern struct cfdriver le_cd;
+
+#ifdef DDB
+#define integrate
+#define hide
+#else
+#define integrate static __inline
+#define hide static
+#endif
+
+static void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+static u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t));
+
+static void
+lewrcsr(sc, port, val)
+ struct am7990_softc *sc;
+ u_int16_t port, val;
+{
+ struct le_softc *lesc = (struct le_softc *)sc;
+
+ bus_space_write_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RAP, port);
+ bus_space_write_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RDP, val);
+
+#if defined(SUN4M)
+ /*
+ * We need to flush the Sbus->Mbus write buffers. This can most
+ * easily be accomplished by reading back the register that we
+ * just wrote (thanks to Chris Torek for this solution).
+ */
+ if (CPU_ISSUN4M) {
+ volatile u_int16_t discard;
+ discard = bus_space_read_2(lesc->sc_bustag, lesc->sc_reg,
+ LEREG1_RDP);
+ }
+#endif
+}
+
+static u_int16_t
+lerdcsr(sc, port)
+ struct am7990_softc *sc;
+ u_int16_t port;
+{
+ struct le_softc *lesc = (struct le_softc *)sc;
+
+ bus_space_write_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RAP, port);
+ return (bus_space_read_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RDP));
+}
+
+
+int
+lematch_sbus(parent, vcf, aux)
+ struct device *parent;
+ void *vcf;
+ void *aux;
+{
+ struct cfdata *cf = vcf;
+ struct sbus_attach_args *sa = aux;
+
+ return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0);
+}
+
+void
+leattach_sbus(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct sbus_attach_args *sa = aux;
+ struct le_softc *lesc = (struct le_softc *)self;
+ struct am7990_softc *sc = &lesc->sc_am7990;
+ bus_dma_tag_t dmatag;
+ struct sbusdev *sd;
+ /* XXX the following declarations should be elsewhere */
+ extern void myetheraddr __P((u_char *));
+
+
+ lesc->sc_bustag = sa->sa_bustag;
+ lesc->sc_dmatag = dmatag = sa->sa_dmatag;
+
+ if (sbus_bus_map(sa->sa_bustag,
+ sa->sa_slot,
+ sa->sa_offset,
+ sa->sa_size,
+ BUS_SPACE_MAP_LINEAR,
+ 0, &lesc->sc_reg) != 0) {
+ printf("%s @ sbus: cannot map registers\n", self->dv_xname);
+ return;
+ }
+
+ /*
+ * Look for an "unallocated" lebuffer and pair it with
+ * this `le' device on the assumption that we're on
+ * a pre-historic ROM that doesn't establish le<=>lebuffer
+ * parent-child relationships.
+ */
+ for (sd = ((struct sbus_softc *)parent)->sc_sbdev; sd != NULL;
+ sd = sd->sd_bchain) {
+
+ struct lebuf_softc *lebuf = (struct lebuf_softc *)sd->sd_dev;
+
+ if (strncmp("lebuffer", sd->sd_dev->dv_xname, 8) != 0)
+ continue;
+
+ if (lebuf->attached != 0)
+ continue;
+
+ sc->sc_mem = lebuf->sc_buffer;
+ sc->sc_memsize = lebuf->sc_bufsiz;
+ sc->sc_addr = 0; /* Lance view is offset by buffer location */
+ lebuf->attached = 1;
+
+ /* That old black magic... */
+ sc->sc_conf3 = getpropint(sa->sa_node,
+ "busmaster-regval",
+ LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON);
+ break;
+ }
+
+ lesc->sc_sd.sd_reset = (void *)am7990_reset;
+ sbus_establish(&lesc->sc_sd, &sc->sc_dev);
+
+ if (sc->sc_mem == 0) {
+ bus_dma_segment_t seg;
+ int rseg, error;
+
+#ifndef BUS_DMA_24BIT
+/* XXX - This flag is not defined on all archs */
+#define BUS_DMA_24BIT 0
+#endif
+ /* Get a DMA handle */
+ if ((error = bus_dmamap_create(dmatag, MEMSIZE, 1, MEMSIZE, 0,
+ BUS_DMA_NOWAIT|BUS_DMA_24BIT,
+ &lesc->sc_dmamap)) != 0) {
+ printf("%s: DMA map create error %d\n",
+ self->dv_xname, error);
+ return;
+ }
+
+ /* Allocate DMA buffer */
+ if ((error = bus_dmamem_alloc(dmatag, MEMSIZE, 0, 0,
+ &seg, 1, &rseg,
+ BUS_DMA_NOWAIT|BUS_DMA_24BIT)) != 0){
+ printf("%s: DMA buffer allocation error %d\n",
+ self->dv_xname, error);
+ return;
+ }
+
+ /* Map DMA buffer into kernel space */
+ if ((error = bus_dmamem_map(dmatag, &seg, rseg, MEMSIZE,
+ (caddr_t *)&sc->sc_mem,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf("%s: DMA buffer map error %d\n",
+ self->dv_xname, error);
+ bus_dmamem_free(lesc->sc_dmatag, &seg, rseg);
+ return;
+ }
+
+ /* Load DMA buffer */
+ if ((error = bus_dmamap_load(dmatag, lesc->sc_dmamap, sc->sc_mem,
+ MEMSIZE, NULL, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf("%s: DMA buffer map load error %d\n",
+ self->dv_xname, error);
+ bus_dmamem_free(dmatag, &seg, rseg);
+ bus_dmamem_unmap(dmatag, sc->sc_mem, MEMSIZE);
+ return;
+ }
+
+ sc->sc_addr = lesc->sc_dmamap->dm_segs[0].ds_addr & 0xffffff;
+ sc->sc_memsize = MEMSIZE;
+ sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
+ }
+
+ myetheraddr(sc->sc_arpcom.ac_enaddr);
+
+ sc->sc_hasifmedia = 1;
+
+ sc->sc_copytodesc = am7990_copytobuf_contig;
+ sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
+ sc->sc_copytobuf = am7990_copytobuf_contig;
+ sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
+ sc->sc_zerobuf = am7990_zerobuf_contig;
+
+ sc->sc_rdcsr = lerdcsr;
+ sc->sc_wrcsr = lewrcsr;
+
+ am7990_config(&lesc->sc_am7990);
+
+ /* Establish interrupt handler */
+ if (sa->sa_nintr != 0)
+ (void)bus_intr_establish(lesc->sc_bustag, sa->sa_pri,
+ IPL_NET, 0, am7990_intr, sc);
+}
diff --git a/sys/dev/sbus/if_le_ledma.c b/sys/dev/sbus/if_le_ledma.c
new file mode 100644
index 00000000000..be2a1098db1
--- /dev/null
+++ b/sys/dev/sbus/if_le_ledma.c
@@ -0,0 +1,451 @@
+/* $NetBSD: if_le_ledma.c,v 1.14 2001/05/30 11:46:35 mrg Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
+ *
+ * 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.
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/sbus/sbusvar.h>
+
+#include <dev/ic/lsi64854reg.h>
+#include <dev/ic/lsi64854var.h>
+
+#include <dev/ic/lancereg.h>
+#include <dev/ic/lancevar.h>
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+/*
+ * LANCE registers.
+ */
+#define LEREG1_RDP 0 /* Register Data port */
+#define LEREG1_RAP 2 /* Register Address port */
+
+struct le_softc {
+ struct am7990_softc sc_am7990; /* glue to MI code */
+ struct sbusdev sc_sd; /* sbus device */
+ bus_space_tag_t sc_bustag;
+ bus_dmamap_t sc_dmamap;
+ bus_space_handle_t sc_reg; /* LANCE registers */
+ struct lsi64854_softc *sc_dma; /* pointer to my dma */
+ u_int sc_laddr; /* LANCE DMA address */
+};
+
+#define MEMSIZE (16*1024) /* LANCE memory size */
+#define LEDMA_BOUNDARY (16*1024*1024) /* must not cross 16MB boundary */
+
+int lematch_ledma __P((struct device *, void *, void *));
+void leattach_ledma __P((struct device *, struct device *, void *));
+
+/*
+ * Media types supported by the Sun4m.
+ */
+
+void lesetutp __P((struct am7990_softc *));
+void lesetaui __P((struct am7990_softc *));
+
+int lemediachange __P((struct ifnet *));
+void lemediastatus __P((struct ifnet *, struct ifmediareq *));
+
+struct cfattach le_ledma_ca = {
+ sizeof(struct le_softc), lematch_ledma, leattach_ledma
+};
+
+#if 0
+struct cfdriver le_cd = {
+ NULL, "le", DV_DULL
+};
+#endif
+
+#if defined(_KERNEL_OPT)
+#include "opt_ddb.h"
+#endif
+
+#ifdef DDB
+#define integrate
+#define hide
+#else
+#define integrate static __inline
+#define hide static
+#endif
+
+static void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+static u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t));
+hide void lehwreset __P((struct am7990_softc *));
+hide void lehwinit __P((struct am7990_softc *));
+hide void lenocarrier __P((struct am7990_softc *));
+
+static void
+lewrcsr(sc, port, val)
+ struct am7990_softc *sc;
+ u_int16_t port, val;
+{
+ struct le_softc *lesc = (struct le_softc *)sc;
+
+ bus_space_write_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RAP, port);
+ bus_space_write_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RDP, val);
+
+#if defined(SUN4M)
+ /*
+ * We need to flush the Sbus->Mbus write buffers. This can most
+ * easily be accomplished by reading back the register that we
+ * just wrote (thanks to Chris Torek for this solution).
+ */
+ if (CPU_ISSUN4M) {
+ volatile u_int16_t discard;
+ discard = bus_space_read_2(lesc->sc_bustag, lesc->sc_reg,
+ LEREG1_RDP);
+ }
+#endif
+}
+
+static u_int16_t
+lerdcsr(sc, port)
+ struct am7990_softc *sc;
+ u_int16_t port;
+{
+ struct le_softc *lesc = (struct le_softc *)sc;
+
+ bus_space_write_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RAP, port);
+ return (bus_space_read_2(lesc->sc_bustag, lesc->sc_reg, LEREG1_RDP));
+}
+
+void
+lesetutp(sc)
+ struct am7990_softc *sc;
+{
+ struct lsi64854_softc *dma = ((struct le_softc *)sc)->sc_dma;
+ u_int32_t csr;
+
+ csr = L64854_GCSR(dma);
+ csr |= E_TP_AUI;
+ L64854_SCSR(dma, csr);
+ delay(20000); /* must not touch le for 20ms */
+}
+
+void
+lesetaui(sc)
+ struct am7990_softc *sc;
+{
+ struct lsi64854_softc *dma = ((struct le_softc *)sc)->sc_dma;
+ u_int32_t csr;
+
+ csr = L64854_GCSR(dma);
+ csr &= ~E_TP_AUI;
+ L64854_SCSR(dma, csr);
+ delay(20000); /* must not touch le for 20ms */
+}
+
+int
+lemediachange(ifp)
+ struct ifnet *ifp;
+{
+ struct am7990_softc *sc = ifp->if_softc;
+ struct ifmedia *ifm = &sc->sc_ifmedia;
+
+ if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
+ return (EINVAL);
+
+ /*
+ * Switch to the selected media. If autoselect is
+ * set, we don't really have to do anything. We'll
+ * switch to the other media when we detect loss of
+ * carrier.
+ */
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_10_T:
+ lesetutp(sc);
+ break;
+
+ case IFM_10_5:
+ lesetaui(sc);
+ break;
+
+ case IFM_AUTO:
+ break;
+
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+void
+lemediastatus(ifp, ifmr)
+ struct ifnet *ifp;
+ struct ifmediareq *ifmr;
+{
+ struct am7990_softc *sc = ifp->if_softc;
+ struct lsi64854_softc *dma = ((struct le_softc *)sc)->sc_dma;
+
+ /*
+ * Notify the world which media we're currently using.
+ */
+ if (L64854_GCSR(dma) & E_TP_AUI)
+ ifmr->ifm_active = IFM_ETHER|IFM_10_T;
+ else
+ ifmr->ifm_active = IFM_ETHER|IFM_10_5;
+}
+
+hide void
+lehwreset(sc)
+ struct am7990_softc *sc;
+{
+ struct le_softc *lesc = (struct le_softc *)sc;
+ struct lsi64854_softc *dma = lesc->sc_dma;
+ u_int32_t csr;
+ u_int aui_bit;
+
+ /*
+ * Reset DMA channel.
+ */
+ csr = L64854_GCSR(dma);
+ aui_bit = csr & E_TP_AUI;
+ DMA_RESET(dma);
+
+ /* Write bits 24-31 of Lance address */
+ bus_space_write_4(dma->sc_bustag, dma->sc_regs, L64854_REG_ENBAR,
+ lesc->sc_laddr & 0xff000000);
+
+ DMA_ENINTR(dma);
+
+ /*
+ * Disable E-cache invalidates on chip writes.
+ * Retain previous cable selection bit.
+ */
+ csr = L64854_GCSR(dma);
+ csr |= (E_DSBL_WR_INVAL | aui_bit);
+ L64854_SCSR(dma, csr);
+ delay(20000); /* must not touch le for 20ms */
+}
+
+hide void
+lehwinit(sc)
+ struct am7990_softc *sc;
+{
+
+ /*
+ * Make sure we're using the currently-enabled media type.
+ * XXX Actually, this is probably unnecessary, now.
+ */
+ switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_cur->ifm_media)) {
+ case IFM_10_T:
+ lesetutp(sc);
+ break;
+
+ case IFM_10_5:
+ lesetaui(sc);
+ break;
+ }
+}
+
+hide void
+lenocarrier(sc)
+ struct am7990_softc *sc;
+{
+ struct le_softc *lesc = (struct le_softc *)sc;
+
+ /*
+ * Check if the user has requested a certain cable type, and
+ * if so, honor that request.
+ */
+ printf("%s: lost carrier on ", sc->sc_dev.dv_xname);
+
+ if (L64854_GCSR(lesc->sc_dma) & E_TP_AUI) {
+ printf("UTP port");
+ switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) {
+ case IFM_10_5:
+ case IFM_AUTO:
+ printf(", switching to AUI port");
+ lesetaui(sc);
+ }
+ } else {
+ printf("AUI port");
+ switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) {
+ case IFM_10_T:
+ case IFM_AUTO:
+ printf(", switching to UTP port");
+ lesetutp(sc);
+ }
+ }
+ printf("\n");
+}
+
+int
+lematch_ledma(parent, vcf, aux)
+ struct device *parent;
+ void *vcf;
+ void *aux;
+{
+ struct cfdata *cf = vcf;
+ struct sbus_attach_args *sa = aux;
+
+ return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0);
+}
+
+
+void
+leattach_ledma(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct sbus_attach_args *sa = aux;
+ struct le_softc *lesc = (struct le_softc *)self;
+ struct lsi64854_softc *lsi = (struct lsi64854_softc *)parent;
+ struct am7990_softc *sc = &lesc->sc_am7990;
+ bus_dma_tag_t dmatag = sa->sa_dmatag;
+ bus_dma_segment_t seg;
+ int rseg, error;
+ /* XXX the following declarations should be elsewhere */
+ extern void myetheraddr __P((u_char *));
+
+ lesc->sc_bustag = sa->sa_bustag;
+
+ /* Establish link to `ledma' device */
+ lesc->sc_dma = lsi;
+ lesc->sc_dma->sc_client = lesc;
+
+ /* Map device registers */
+ if (bus_space_map2(sa->sa_bustag,
+ sa->sa_slot,
+ sa->sa_offset,
+ sa->sa_size,
+ BUS_SPACE_MAP_LINEAR,
+ 0, &lesc->sc_reg) != 0) {
+ printf("%s @ ledma: cannot map registers\n", self->dv_xname);
+ return;
+ }
+
+ /* Allocate buffer memory */
+ sc->sc_memsize = MEMSIZE;
+
+ /* Get a DMA handle */
+ if ((error = bus_dmamap_create(dmatag, MEMSIZE, 1, MEMSIZE,
+ LEDMA_BOUNDARY, BUS_DMA_NOWAIT,
+ &lesc->sc_dmamap)) != 0) {
+ printf("%s: DMA map create error %d\n", self->dv_xname, error);
+ return;
+ }
+
+ /* Allocate DMA buffer */
+ if ((error = bus_dmamem_alloc(dmatag, MEMSIZE, 0, LEDMA_BOUNDARY,
+ &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
+ printf("%s @ ledma: DMA buffer alloc error %d\n",
+ self->dv_xname, error);
+ return;
+ }
+
+ /* Map DMA buffer into kernel space */
+ if ((error = bus_dmamem_map(dmatag, &seg, rseg, MEMSIZE,
+ (caddr_t *)&sc->sc_mem,
+ BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf("%s @ ledma: DMA buffer map error %d\n",
+ self->dv_xname, error);
+ bus_dmamem_free(dmatag, &seg, rseg);
+ return;
+ }
+
+ /* Load DMA buffer */
+ if ((error = bus_dmamap_load(dmatag, lesc->sc_dmamap, sc->sc_mem,
+ MEMSIZE, NULL, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
+ printf("%s: DMA buffer map load error %d\n",
+ self->dv_xname, error);
+ bus_dmamem_free(dmatag, &seg, rseg);
+ bus_dmamem_unmap(dmatag, sc->sc_mem, MEMSIZE);
+ return;
+ }
+
+ lesc->sc_laddr = lesc->sc_dmamap->dm_segs[0].ds_addr;
+ sc->sc_addr = lesc->sc_laddr & 0xffffff;
+ sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
+
+
+ /* Assume SBus is grandparent */
+ lesc->sc_sd.sd_reset = (void *)am7990_reset;
+ sbus_establish(&lesc->sc_sd, parent);
+
+ ifmedia_init(&sc->sc_ifmedia, 0, lemediachange, lemediastatus);
+ ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
+ ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5, 0, NULL);
+ ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO);
+ sc->sc_hasifmedia = 1;
+
+ myetheraddr(sc->sc_arpcom.ac_enaddr);
+
+ sc->sc_copytodesc = am7990_copytobuf_contig;
+ sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
+ sc->sc_copytobuf = am7990_copytobuf_contig;
+ sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
+ sc->sc_zerobuf = am7990_zerobuf_contig;
+
+ sc->sc_rdcsr = lerdcsr;
+ sc->sc_wrcsr = lewrcsr;
+ sc->sc_hwinit = lehwinit;
+ sc->sc_nocarrier = lenocarrier;
+ sc->sc_hwreset = lehwreset;
+
+ /* Establish interrupt handler */
+ if (sa->sa_nintr != 0)
+ (void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, IPL_NET, 0,
+ am7990_intr, sc);
+
+ am7990_config(&lesc->sc_am7990);
+
+ /* now initialize DMA */
+ lehwreset(sc);
+}
diff --git a/sys/dev/sbus/lebuffervar.h b/sys/dev/sbus/lebuffervar.h
new file mode 100644
index 00000000000..09ec238d3b4
--- /dev/null
+++ b/sys/dev/sbus/lebuffervar.h
@@ -0,0 +1,50 @@
+/* $NetBSD: lebuffervar.h,v 1.2 1998/07/27 19:25:34 pk Exp $ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * 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.
+ */
+
+struct lebuf_softc {
+ struct device sc_dev; /* us as a device */
+ bus_space_tag_t sc_bustag;
+ bus_dma_tag_t sc_dmatag;
+ struct sbusdev sc_sd; /* sbus device */
+ u_int sc_rev; /* revision */
+ int sc_node; /* PROM node ID */
+ int sc_burst; /* DVMA burst size in effect */
+ caddr_t sc_buffer; /* VA of the buffer we provide */
+ int sc_bufsiz; /* Size of buffer */
+ int attached; /* 1: in use by `le' device */
+};