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