Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/sgimips/hpc Support for the Seeq 8003 Ethernet atta...
details: https://anonhg.NetBSD.org/src/rev/12e5999718bc
branches: trunk
changeset: 509708:12e5999718bc
user: thorpej <thorpej%NetBSD.org@localhost>
date: Fri May 11 03:22:21 2001 +0000
description:
Support for the Seeq 8003 Ethernet attached to the HPC ASIC,
found on Indigo2 and Indy.
>From Rafal K. Boni.
diffstat:
sys/arch/sgimips/hpc/if_sq.c | 1038 ++++++++++++++++++++++++++++++++++++++++++
sys/arch/sgimips/hpc/sqvar.h | 166 ++++++
2 files changed, 1204 insertions(+), 0 deletions(-)
diffs (truncated from 1212 to 300 lines):
diff -r e1e4eac50172 -r 12e5999718bc sys/arch/sgimips/hpc/if_sq.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/sgimips/hpc/if_sq.c Fri May 11 03:22:21 2001 +0000
@@ -0,0 +1,1038 @@
+/* $NetBSD: if_sq.c,v 1.1 2001/05/11 03:22:21 thorpej Exp $ */
+
+/*
+ * Copyright (c) 2001 Rafal K. Boni
+ * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Portions of this code are derived from software contributed to The
+ * NetBSD Foundation by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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. 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 "opt_inet.h"
+#include "opt_ns.h"
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.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/syslog.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/endian.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
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_inarp.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+/* XXXrkb: cheap hack until parents pass in DMA tags */
+#define _SGIMIPS_BUS_DMA_PRIVATE
+
+#include <machine/bus.h>
+#include <machine/arcs.h>
+#include <machine/intr.h>
+
+#include <dev/ic/seeq8003reg.h>
+
+#include <sgimips/hpc/sqvar.h>
+#include <sgimips/hpc/hpcvar.h>
+#include <sgimips/hpc/hpcreg.h>
+
+#define static
+
+/*
+ * Short TODO list:
+ * (1) Do counters for bad-RX packets.
+ * (2) Inherit DMA tag via config machinery, don't hard-code it.
+ * (3) Allow multi-segment transmits, instead of copying to a single,
+ * contiguous mbuf.
+ * (4) Verify sq_stop() turns off enough stuff; I was still getting
+ * seeq interrupts after sq_stop().
+ * (5) Fix up printfs in driver (most should only fire ifdef SQ_DEBUG
+ * or something similar.
+ * (6) Implement EDLC modes: especially packet auto-pad and simplex
+ * mode.
+ * (7) Should the driver filter out its own transmissions in non-EDLC
+ * mode?
+ * (8) Multicast support -- multicast filter, address management, ...
+ * (9) Deal with RB0 (recv buffer overflow) on reception. Will need
+ * to figure out if RB0 is read-only as stated in one spot in the
+ * HPC spec or read-write (ie, is the 'write a one to clear it')
+ * the correct thing?
+ */
+
+static int sq_match(struct device *, struct cfdata *, void *);
+static void sq_attach(struct device *, struct device *, void *);
+static int sq_init(struct ifnet *);
+static void sq_start(struct ifnet *);
+static void sq_stop(struct ifnet *, int);
+static void sq_watchdog(struct ifnet *);
+static int sq_ioctl(struct ifnet *, u_long, caddr_t);
+
+static int sq_intr(void *);
+static int sq_rxintr(struct sq_softc *);
+static int sq_txintr(struct sq_softc *);
+static void sq_reset(struct sq_softc *);
+static int sq_add_rxbuf(struct sq_softc *, int);
+static void sq_dump_buffer(u_int32_t addr, u_int32_t len);
+
+static void enaddr_aton(const char*, u_int8_t*);
+
+/* Actions */
+#define SQ_RESET 1
+#define SQ_ADD_TO_DMA 2
+#define SQ_START_DMA 3
+#define SQ_DONE_DMA 4
+#define SQ_RESTART_DMA 5
+#define SQ_TXINTR_ENTER 6
+#define SQ_TXINTR_EXIT 7
+#define SQ_TXINTR_BUSY 8
+
+struct sq_action_trace {
+ int action;
+ int bufno;
+ int status;
+ int freebuf;
+};
+
+int sq_trace_idx = 0;
+struct sq_action_trace sq_trace[100];
+
+void sq_trace_dump(struct sq_softc* sc);
+
+#define SQ_TRACE(act, buf, stat, free) do { \
+ sq_trace[sq_trace_idx].action = (act); \
+ sq_trace[sq_trace_idx].bufno = (buf); \
+ sq_trace[sq_trace_idx].status = (stat); \
+ sq_trace[sq_trace_idx].freebuf = (free); \
+ if (++sq_trace_idx == 100) { \
+ bzero(&sq_trace, sizeof(sq_trace)); \
+ sq_trace_idx = 0; \
+ } \
+} while (0)
+
+struct cfattach sq_ca = {
+ sizeof(struct sq_softc), sq_match, sq_attach
+};
+
+static int
+sq_match(struct device *parent, struct cfdata *match, void *aux)
+{
+ /* XXX! */
+ return 1;
+}
+
+static void
+sq_attach(struct device *parent, struct device *self, void *aux)
+{
+ int i, err;
+ char* macaddr;
+ struct sq_softc *sc = (void *)self;
+ struct hpc_attach_args *haa = aux;
+ struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+
+ sc->sc_hpct = haa->ha_iot;
+ if ((err = bus_space_subregion(haa->ha_iot, haa->ha_ioh,
+ HPC_ENET_REGS,
+ HPC_ENET_REGS_SIZE,
+ &sc->sc_hpch)) != 0) {
+ printf(": unable to map HPC DMA registers, error = %d\n", err);
+ goto fail_0;
+ }
+
+ sc->sc_regt = haa->ha_iot;
+ if ((err = bus_space_subregion(haa->ha_iot, haa->ha_ioh,
+ HPC_ENET_DEVREGS,
+ HPC_ENET_DEVREGS_SIZE,
+ &sc->sc_regh)) != 0) {
+ printf(": unable to map Seeq registers, error = %d\n", err);
+ goto fail_0;
+ }
+
+ /* XXXrkb: should be inherited from parent bus, but works for now */
+ sc->sc_dmat = &sgimips_default_bus_dma_tag;
+
+ if ((err = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct sq_control),
+ PAGE_SIZE, PAGE_SIZE, &sc->sc_cdseg,
+ 1, &sc->sc_ncdseg, BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to allocate control data, error = %d\n", err);
+ goto fail_0;
+ }
+
+ if ((err = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg,
+ sizeof(struct sq_control),
+ (caddr_t *)&sc->sc_control,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
+ printf(": unable to map control data, error = %d\n", err);
+ goto fail_1;
+ }
+
+ if ((err = bus_dmamap_create(sc->sc_dmat, sizeof(struct sq_control),
+ 1, sizeof(struct sq_control), PAGE_SIZE,
+ BUS_DMA_NOWAIT, &sc->sc_cdmap)) != 0) {
+ printf(": unable to create DMA map for control data, error "
+ "= %d\n", err);
+ goto fail_2;
+ }
+
+ if ((err = bus_dmamap_load(sc->sc_dmat, sc->sc_cdmap, sc->sc_control,
+ sizeof(struct sq_control),
+ NULL, BUS_DMA_NOWAIT)) != 0) {
+ printf(": unable to load DMA map for control data, error "
+ "= %d\n", err);
+ goto fail_3;
+ }
+
+ bzero(sc->sc_control, sizeof(struct sq_control));
+
+ /* Create transmit buffer DMA maps */
+ for (i = 0; i < SQ_NTXDESC; i++) {
+ if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
+ 0, BUS_DMA_NOWAIT,
+ &sc->sc_txmap[i])) != 0) {
+ printf(": unable to create tx DMA map %d, error = %d\n",
+ i, err);
+ goto fail_4;
+ }
+ }
+
+ /* Create transmit buffer DMA maps */
+ for (i = 0; i < SQ_NRXDESC; i++) {
+ if ((err = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
+ 0, BUS_DMA_NOWAIT,
+ &sc->sc_rxmap[i])) != 0) {
+ printf(": unable to create rx DMA map %d, error = %d\n",
+ i, err);
+ goto fail_5;
+ }
+ }
+
+ /* Pre-allocate the receive buffers. */
+ for (i = 0; i < SQ_NRXDESC; i++) {
+ if ((err = sq_add_rxbuf(sc, i)) != 0) {
+ printf(": unable to allocate or map rx buffer %d\n,"
+ " error = %d\n", i, err);
+ goto fail_6;
+ }
+ }
+
+ if ((macaddr = ARCS->GetEnvironmentVariable("eaddr")) == NULL) {
+ printf(": unable to get MAC address!\n");
+ goto fail_6;
+ }
+
+ if ((cpu_intr_establish(3, IPL_NET, sq_intr, sc)) == NULL) {
+ printf(": unable to establish interrupt!\n");
+ goto fail_6;
+ }
+
+
+ printf(": SGI Seeq-8003\n");
+
+ enaddr_aton(macaddr, sc->sc_enaddr);
+
+ printf("%s: station address %s\n", sc->sc_dev.dv_xname,
+ ether_sprintf(sc->sc_enaddr));
+
+ bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+ ifp->if_softc = sc;
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_init = sq_init;
+ ifp->if_stop = sq_stop;
+ ifp->if_start = sq_start;
+ ifp->if_ioctl = sq_ioctl;
+ ifp->if_watchdog = sq_watchdog;
+ ifp->if_flags =
+ IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ if_attach(ifp);
+ ether_ifattach(ifp, sc->sc_enaddr);
Home |
Main Index |
Thread Index |
Old Index