diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2001-08-19 17:09:25 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2001-08-19 17:09:25 +0000 |
commit | 00a5ac5bf07f4c56d75db8d065a8733b32293c9e (patch) | |
tree | 01b63b61a5b063db566398983e0e7479caf2ad29 | |
parent | d0aa74316482c264764998fc7751670b0c6e6a8e (diff) |
enough from netbsd to get le at ledma attached
-rw-r--r-- | sys/dev/sbus/dma_sbus.c | 281 | ||||
-rw-r--r-- | sys/dev/sbus/files.sbus | 26 | ||||
-rw-r--r-- | sys/dev/sbus/if_le.c | 287 | ||||
-rw-r--r-- | sys/dev/sbus/if_le_ledma.c | 451 | ||||
-rw-r--r-- | sys/dev/sbus/lebuffervar.h | 50 |
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 */ +}; |