split le driver, if_name/if_unit -> if_xname/if_softc
authorderaadt <deraadt@openbsd.org>
Fri, 10 May 1996 12:42:21 +0000 (12:42 +0000)
committerderaadt <deraadt@openbsd.org>
Fri, 10 May 1996 12:42:21 +0000 (12:42 +0000)
sys/arch/mvme68k/conf/files.mvme68k
sys/arch/mvme68k/dev/if_ie.c
sys/arch/mvme68k/dev/if_le.c
sys/arch/mvme68k/dev/if_lereg.h
sys/arch/mvme68k/dev/if_levar.h [new file with mode: 0644]

index 37bcf0c..9bdab9b 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.mvme68k,v 1.3 1996/04/28 11:22:55 deraadt Exp $
+#      $OpenBSD: files.mvme68k,v 1.4 1996/05/10 12:42:21 deraadt Exp $
 
 # config file for mvme68k
 
@@ -37,8 +37,7 @@ attach bugtty at mainbus
 file arch/mvme68k/dev/bugtty.c                 bugtty needs-count
 file arch/mvme68k/dev/bug.c                    bugtty
 
-device le: ifnet, ether
-attach le at pcc
+attach le at pcc
 file    arch/mvme68k/dev/if_le.c               le
 
 device ie: ifnet, ether
index 2370698..e6157f1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ie.c,v 1.5 1996/05/05 13:37:27 mickey Exp $ */
+/*     $OpenBSD: if_ie.c,v 1.6 1996/05/10 12:42:23 deraadt Exp $ */
 
 /*-
  * Copyright (c) 1995 Theo de Raadt
@@ -289,7 +289,7 @@ static void ie_obreset __P((struct ie_softc *));
 static void ie_obattend __P((struct ie_softc *));
 static void ie_obrun __P((struct ie_softc *));
 
-void iewatchdog __P((/* short */));
+void iewatchdog __P((struct ifnet *));
 int ieintr __P((void *));
 int iefailintr __P((void *));
 int ieinit __P((struct ie_softc *));
@@ -487,8 +487,8 @@ ieattach(parent, self, aux)
                /* XXX should reclaim resources? */
                return;
        }
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = ie_cd.cd_name;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
        ifp->if_start = iestart;
        ifp->if_ioctl = ieioctl;
        ifp->if_watchdog = iewatchdog;
@@ -546,10 +546,10 @@ ieattach(parent, self, aux)
  * an interrupt after a transmit has been started on it.
  */
 void
-iewatchdog(unit)
-       short unit;
+iewatchdog(ifp)
+       struct ifnet *ifp;
 {
-       struct ie_softc *sc = ie_cd.cd_devs[unit];
+       struct ie_softc *sc = ifp->if_softc;
 
        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        ++sc->sc_arpcom.ac_if.if_oerrors;
@@ -1287,7 +1287,7 @@ void
 iestart(ifp)
        struct ifnet *ifp;
 {
-       struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
+       struct ie_softc *sc = ifp->if_softc;
        struct mbuf *m0, *m;
        u_char *buffer;
        u_short len;
@@ -1819,7 +1819,7 @@ ieioctl(ifp, cmd, data)
        u_long cmd;
        caddr_t data;
 {
-       struct ie_softc *sc = ie_cd.cd_devs[ifp->if_unit];
+       struct ie_softc *sc = ifp->if_softc;
        struct ifaddr *ifa = (struct ifaddr *)data;
        struct ifreq *ifr = (struct ifreq *)data;
        int s, error = 0;
index 40ef293..3462c18 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_le.c,v 1.6 1996/05/06 21:53:39 deraadt Exp $ */
+/*     $OpenBSD: if_le.c,v 1.7 1996/05/10 12:42:24 deraadt Exp $ */
 
 /*-
  * Copyright (c) 1982, 1992, 1993
 
 #include "bpfilter.h"
 
-/*
- * AMD 7990 LANCE
- */
 #include <sys/param.h>
-#include <sys/device.h>
 #include <sys/systm.h>
-#include <sys/kernel.h>
 #include <sys/mbuf.h>
-#include <sys/buf.h>
-#include <sys/socket.h>
 #include <sys/syslog.h>
-#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/device.h>
 #include <sys/malloc.h>
-#include <sys/errno.h>
-
-#include <vm/vm.h>
 
 #include <net/if.h>
-#include <net/netisr.h>
-#include <net/route.h>
-#if NBPFILTER > 0
-#include <sys/select.h>
-#include <net/bpf.h>
-#include <net/bpfdesc.h>
-#endif
 
 #ifdef INET
 #include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
 #include <netinet/if_ether.h>
 #endif
 
-#include <machine/cpu.h>
 #include <machine/autoconf.h>
-#include <machine/pmap.h>
+#include <machine/cpu.h>
+
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
 
 #include <mvme68k/dev/if_lereg.h>
+#include <mvme68k/dev/if_levar.h>
 #include <mvme68k/dev/pccreg.h>
 
-/* DVMA address to LANCE address -- the Sbus/MMU will resupply the 0xff */
-#define LANCE_ADDR(x) ((int)x)
-
-int    ledebug = 0;            /* console error messages */
-
-#ifdef PACKETSTATS
-long   lexpacketsizes[LEMTU+1];
-long   lerpacketsizes[LEMTU+1];
-#endif
-
-/* Per interface statistics */
-/* XXX this should go in something like if_levar.h */
-struct lestats {
-       long    lexints;        /* transmitter interrupts */
-       long    lerints;        /* receiver interrupts */
-       long    lerbufs;        /* total buffers received during interrupts */
-       long    lerhits;        /* times current rbuf was full */
-       long    lerscans;       /* rbufs scanned before finding first full */
-};
-
-/*
- * Ethernet software status per interface.
- *
- * Each interface is referenced by a network interface structure,
- * le_if, which the routing code uses to locate the interface.
- * This structure contains the output queue for the interface, its address, ...
- */
-struct le_softc {
-       struct  device sc_dev;          /* base device */
-       struct  evcnt sc_intrcnt;       /* # of interrupts, per le */
-       struct  evcnt sc_errcnt;        /* # of errors, per le */
-       struct  intrhand sc_ih;
-
-       struct  arpcom sc_ac;           /* common Ethernet structures */
-#define        sc_if   sc_ac.ac_if             /* network-visible interface */
-#define        sc_addr sc_ac.ac_enaddr         /* hardware Ethernet address */
-       struct  lereg1 *sc_r1;          /* LANCE registers */
-       struct  lereg2 *sc_r2;          /* dual-port RAM */
-       int     sc_rmd;                 /* predicted next rmd to process */
-       int     sc_runt;
-       int     sc_jab;
-       int     sc_merr;
-       int     sc_babl;
-       int     sc_cerr;
-       int     sc_miss;
-       int     sc_xint;
-       int     sc_xown;
-       int     sc_uflo;
-       int     sc_rxlen;
-       int     sc_rxoff;
-       int     sc_txoff;
-       int     sc_busy;
-       short   sc_iflags;
-       struct  lestats sc_lestats;     /* per interface statistics */
-};
-
-
 /* autoconfiguration driver */
 void   leattach(struct device *, struct device *, void *);
 int    lematch(struct device *, void *, void *);
 
-struct cfattach le_ca = {
+struct cfattach le_ca = {
        sizeof(struct le_softc), lematch, leattach
 };
 
-struct cfdriver le_cd = {
-       NULL, "le", DV_IFNET, 0
-};
+hide void lewrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+hide u_int16_t lerdcsr __P((struct am7990_softc *, u_int16_t));
+hide void lehwinit __P((struct am7990_softc *));
 
-/* Forwards */
-void   leattach(struct device *, struct device *, void *);
-void   lesetladrf(struct le_softc *);
-void   lereset(struct device *);
-int    leinit(int);
-void   lestart(struct ifnet *);
-int    leintr(void *);
-void   lexint(struct le_softc *);
-void   lerint(struct le_softc *);
-void   leread(struct le_softc *, char *, int);
-int    leput(char *, struct mbuf *);
-struct mbuf *leget(char *, int, int, struct ifnet *);
-int    leioctl(struct ifnet *, u_long, caddr_t);
-void   leerror(struct le_softc *, int);
-void   lererror(struct le_softc *, char *);
-void   lexerror(struct le_softc *);
+hide void
+lewrcsr(sc, port, val)
+       struct am7990_softc *sc;
+       u_int16_t port, val;
+{
+       register struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
+
+       ler1->ler1_rap = port;
+       ler1->ler1_rdp = val;
+}
+
+hide u_int16_t
+lerdcsr(sc, port)
+       struct am7990_softc *sc;
+       u_int16_t port;
+{
+       register struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
+       u_int16_t val;
 
-extern void *etherbuf;
+       ler1->ler1_rap = port;
+       val = ler1->ler1_rdp;
+       return (val);
+}
+
+hide void
+lehwinit(sc)
+       struct am7990_softc *sc;
+{
+}
 
 int
 lematch(parent, vcf, args)
@@ -183,766 +121,48 @@ lematch(parent, vcf, args)
  * to accept packets.
  */
 void
-leattach(parent, self, args)
+leattach(parent, self, aux)
        struct device *parent;
        struct device *self;
-       void *args;
+       void *aux;
 {
-       register struct le_softc *sc = (struct le_softc *)self;
-       register struct lereg2 *ler2;
-       struct ifnet *ifp = &sc->sc_if;
-       struct confargs *ca = args;
+       register struct le_softc *lesc = (struct le_softc *)self;
+       struct am7990_softc *sc = &lesc->sc_am7990;
+       struct confargs *ca = aux;
        register int a;
        int pri = ca->ca_ipl;
+       extern void *etherbuf;
 
        /* XXX the following declarations should be elsewhere */
        extern void myetheraddr(u_char *);
 
+       printf(" pri %d", pri);
+
        /* connect the interrupt */
-       sc->sc_ih.ih_fn = leintr;
-       sc->sc_ih.ih_arg = sc;
-       sc->sc_ih.ih_ipl = pri;
-       pccintr_establish(PCCV_LE, &sc->sc_ih);
+       lesc->sc_ih.ih_fn = am7990_intr;
+       lesc->sc_ih.ih_arg = sc;
+       lesc->sc_ih.ih_ipl = pri;
+       pccintr_establish(PCCV_LE, &lesc->sc_ih);
 
-       sc->sc_r1 = (struct lereg1 *)ca->ca_vaddr;
+       lesc->sc_r1 = (struct lereg1 *)ca->ca_vaddr;
+       sc->sc_conf3 = LE_C3_BSWP /*| LE_C3_ACON | LE_C3_BCON*/;
+       sc->sc_addr = (u_long)etherbuf;
+       sc->sc_memsize = MEMSIZE;
 
-       ler2 = sc->sc_r2 = (struct lereg2 *) etherbuf;
+       myetheraddr(sc->sc_arpcom.ac_enaddr);
 
-       myetheraddr(sc->sc_addr);
-       printf(": address %s\n", ether_sprintf(sc->sc_addr));
+       evcnt_attach(&sc->sc_dev, "intr", &lesc->sc_intrcnt);
+       evcnt_attach(&sc->sc_dev, "errs", &lesc->sc_errcnt);
 
-       /*
-        * Setup for transmit/receive
-        *
-        * According to Van, some versions of the Lance only use this
-        * address to receive packets; it doesn't put them in
-        * output packets. We'll want to make sure that lestart()
-        * installs the address.
-        */
-       ler2->ler2_padr[0] = sc->sc_addr[1];
-       ler2->ler2_padr[1] = sc->sc_addr[0];
-       ler2->ler2_padr[2] = sc->sc_addr[3];
-       ler2->ler2_padr[3] = sc->sc_addr[2];
-       ler2->ler2_padr[4] = sc->sc_addr[5];
-       ler2->ler2_padr[5] = sc->sc_addr[4];
-       a = LANCE_ADDR(&ler2->ler2_rmd);
-       ler2->ler2_rlen = LE_RLEN | (a >> 16);
-       ler2->ler2_rdra = a;
-       a = LANCE_ADDR(&ler2->ler2_tmd);
-       ler2->ler2_tlen = LE_TLEN | (a >> 16);
-       ler2->ler2_tdra = a;
+       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;
 
-       /*
-        * Set up event counters.
-        */
-       evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
-       evcnt_attach(&sc->sc_dev, "errs", &sc->sc_errcnt);
-
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = "le";
-       ifp->if_ioctl = leioctl;
-       ifp->if_start = lestart;
-       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-#ifdef IFF_NOTRAILERS
-       /* XXX still compile when the blasted things are gone... */
-       ifp->if_flags |= IFF_NOTRAILERS;
-#endif
-#if NBPFILTER > 0
-       bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
-#endif
-       if_attach(ifp);
-       ether_ifattach(ifp);
+       sc->sc_rdcsr = lerdcsr;
+       sc->sc_wrcsr = lewrcsr;
+       sc->sc_hwinit = lehwinit;
 
        ((struct pccreg *)ca->ca_master)->pcc_leirq = pri | PCC_IRQ_IEN;
 }
-
-/*
- * Setup the logical address filter
- */
-void
-lesetladrf(sc)
-       register struct le_softc *sc;
-{
-       register struct lereg2 *ler2 = sc->sc_r2;
-       register struct ifnet *ifp = &sc->sc_if;
-       register struct ether_multi *enm;
-       register u_char *cp, c;
-       register u_long crc;
-       register int i, len;
-       struct ether_multistep step;
-
-       /*
-        * Set up multicast address filter by passing all multicast
-        * addresses through a crc generator, and then using the high
-        * order 6 bits as a index into the 64 bit logical address
-        * filter. The high order two bits select the word, while the
-        * rest of the bits select the bit within the word.
-        */
-
-       ler2->ler2_ladrf[0] = 0;
-       ler2->ler2_ladrf[1] = 0;
-       ler2->ler2_ladrf[2] = 0;
-       ler2->ler2_ladrf[3] = 0;
-       ifp->if_flags &= ~IFF_ALLMULTI;
-       ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
-       while (enm != NULL) {
-               if (bcmp((caddr_t)&enm->enm_addrlo,
-                   (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) != 0) {
-                       /*
-                        * We must listen to a range of multicast
-                        * addresses. For now, just accept all
-                        * multicasts, rather than trying to set only
-                        * those filter bits needed to match the range.
-                        * (At this time, the only use of address
-                        * ranges is for IP multicast routing, for
-                        * which the range is big enough to require all
-                        * bits set.)
-                        */
-                       ler2->ler2_ladrf[0] = 0xffff;
-                       ler2->ler2_ladrf[1] = 0xffff;
-                       ler2->ler2_ladrf[2] = 0xffff;
-                       ler2->ler2_ladrf[3] = 0xffff;
-                       ifp->if_flags |= IFF_ALLMULTI;
-                       return;
-               }
-
-               /*
-                * One would think, given the AM7990 document's polynomial
-                * of 0x04c11db6, that this should be 0x6db88320 (the bit
-                * reversal of the AMD value), but that is not right.  See
-                * the BASIC listing: bit 0 (our bit 31) must then be set.
-                */
-               cp = (unsigned char *)&enm->enm_addrlo;
-               crc = 0xffffffff;
-               for (len = 6; --len >= 0;) {
-                       c = *cp++;
-                       for (i = 0; i < 8; i++) {
-                               if ((c & 0x01) ^ (crc & 0x01)) {
-                                       crc >>= 1;
-                                       crc = crc ^ 0xedb88320;
-                               } else
-                                       crc >>= 1;
-                               c >>= 1;
-                       }
-               }
-               /* Just want the 6 most significant bits. */
-               crc = crc >> 26;
-
-               /* Turn on the corresponding bit in the filter. */
-               ler2->ler2_ladrf[crc >> 4] |= 1 << (crc & 0xf);
-
-               ETHER_NEXT_MULTI(step, enm);
-       }
-}
-
-void
-lereset(dev)
-       struct device *dev;
-{
-       register struct le_softc *sc = (struct le_softc *)dev;
-       register struct lereg1 *ler1 = sc->sc_r1;
-       register struct lereg2 *ler2 = sc->sc_r2;
-       register int i, a, timo, stat;
-
-#if NBPFILTER > 0
-       if (sc->sc_if.if_flags & IFF_PROMISC)
-               ler2->ler2_mode = LE_MODE_NORMAL | LE_MODE_PROM;
-       else
-#endif
-               ler2->ler2_mode = LE_MODE_NORMAL;
-       ler1->ler1_rap = LE_CSR0;
-       ler1->ler1_rdp = LE_C0_STOP;
-
-       /* Setup the logical address filter */
-       lesetladrf(sc);
-
-       /* init receive and transmit rings */
-       for (i = 0; i < LERBUF; i++) {
-               a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]);
-               ler2->ler2_rmd[i].rmd0 = a;
-               ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
-               ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
-               ler2->ler2_rmd[i].rmd2 = -LEMTU | LE_XMD2_ONES;
-               ler2->ler2_rmd[i].rmd3 = 0;
-       }
-       for (i = 0; i < LETBUF; i++) {
-               a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]);
-               ler2->ler2_tmd[i].tmd0 = a;
-               ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
-               ler2->ler2_tmd[i].tmd1_bits = 0;
-               ler2->ler2_tmd[i].tmd2 = LE_XMD2_ONES;
-               ler2->ler2_tmd[i].tmd3 = 0;
-       }
-
-bzero((void *)&ler2->ler2_rbuf[0][0], (LERBUF + LETBUF) * LEMTU);
-       /* lance will stuff packet into receive buffer 0 next */
-       sc->sc_rmd = 0;
-
-       /* tell the chip where to find the initialization block */
-       a = LANCE_ADDR(&ler2->ler2_mode);
-       ler1->ler1_rap = LE_CSR1;
-       ler1->ler1_rdp = a;
-       ler1->ler1_rap = LE_CSR2;
-       ler1->ler1_rdp = a >> 16;
-       ler1->ler1_rap = LE_CSR3;
-       ler1->ler1_rdp = LE_C3_BSWP /*| LE_C3_ACON | LE_C3_BCON*/;
-       ler1->ler1_rap = LE_CSR0;
-       ler1->ler1_rdp = LE_C0_INIT;
-       timo = 100000;
-       while (((stat = ler1->ler1_rdp) & (LE_C0_ERR | LE_C0_IDON)) == 0) {
-               if (--timo == 0) {
-                       printf("%s: init timeout, stat=%b\n",
-                           sc->sc_dev.dv_xname, stat, LE_C0_BITS);
-                       break;
-               }
-       }
-       if (stat & LE_C0_ERR)
-               printf("%s: init failed, ler1=0x%x, stat=%b\n",
-                   sc->sc_dev.dv_xname, ler1, stat, LE_C0_BITS);
-       else
-               ler1->ler1_rdp = LE_C0_IDON;    /* clear IDON */
-       ler1->ler1_rdp = LE_C0_STRT | LE_C0_INEA;
-       sc->sc_if.if_flags &= ~IFF_OACTIVE;
-}
-
-/*
- * Initialization of interface
- */
-int
-leinit(unit)
-       int unit;
-{
-       register struct le_softc *sc = le_cd.cd_devs[unit];
-       register struct ifnet *ifp = &sc->sc_if;
-       register int s;
-
-       if ((ifp->if_flags & IFF_RUNNING) == 0) {
-               s = splnet();
-               ifp->if_flags |= IFF_RUNNING;
-               lereset(&sc->sc_dev);
-               lestart(ifp);
-               splx(s);
-       }
-       return (0);
-}
-
-/*
- * Start output on interface.  Get another datagram to send
- * off of the interface queue, and copy it to the interface
- * before starting the output.
- */
-void
-lestart(ifp)
-       register struct ifnet *ifp;
-{
-       register struct le_softc *sc = le_cd.cd_devs[ifp->if_unit];
-       register struct letmd *tmd;
-       register struct mbuf *m;
-       register int len;
-       if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 
-               return;
-       IF_DEQUEUE(&sc->sc_if.if_snd, m);
-       if (m == 0) 
-               return;
-
-       len = leput((char *)sc->sc_r2->ler2_tbuf[0], m);
-
-#if NBPFILTER > 0
-       /*
-        * If bpf is listening on this interface, let it
-        * see the packet before we commit it to the wire.
-        */
-       if (sc->sc_if.if_bpf)
-               bpf_tap(sc->sc_if.if_bpf, (char *)sc->sc_r2->ler2_tbuf[0], len);
-#endif
-
-#ifdef PACKETSTATS
-       if (len <= LEMTU)
-               lexpacketsizes[len]++;
-#endif
-       tmd = sc->sc_r2->ler2_tmd;
-       tmd->tmd3 = 0;
-       tmd->tmd2 = -len | LE_XMD2_ONES;
-       tmd->tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
-       sc->sc_if.if_flags |= IFF_OACTIVE;
-       return;
-}
-
-int
-leintr(dev)
-       register void *dev;
-{
-       register struct le_softc *sc = dev;
-       register struct lereg1 *ler1 = sc->sc_r1;
-       register int csr0;
-
-       csr0 = ler1->ler1_rdp;
-       if ((csr0 & LE_C0_INTR) == 0)
-               return (0);
-       sc->sc_intrcnt.ev_count++;
-
-       if (csr0 & LE_C0_ERR) {
-               sc->sc_errcnt.ev_count++;
-               leerror(sc, csr0);
-               if (csr0 & LE_C0_MERR) {
-                       sc->sc_merr++;
-                       lereset(&sc->sc_dev);
-                       return (1);
-               }
-               if (csr0 & LE_C0_BABL)
-                       sc->sc_babl++;
-               if (csr0 & LE_C0_CERR)
-                       sc->sc_cerr++;
-               if (csr0 & LE_C0_MISS)
-                       sc->sc_miss++;
-               ler1->ler1_rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_INEA;
-       }
-       if ((csr0 & LE_C0_RXON) == 0) {
-               sc->sc_rxoff++;
-               lereset(&sc->sc_dev);
-               return (1);
-       }
-       if ((csr0 & LE_C0_TXON) == 0) {
-               sc->sc_txoff++;
-               lereset(&sc->sc_dev);
-               return (1);
-       }
-       if (csr0 & LE_C0_RINT) {
-               /* interrupt is cleared in lerint */
-               lerint(sc);
-       }
-       if (csr0 & LE_C0_TINT) {
-               ler1->ler1_rdp = LE_C0_TINT|LE_C0_INEA;
-               lexint(sc);
-       }
-       return (1);
-}
-
-/*
- * Ethernet interface transmitter interrupt.
- * Start another output if more data to send.
- */
-void
-lexint(sc)
-       register struct le_softc *sc;
-{
-       register struct letmd *tmd = sc->sc_r2->ler2_tmd;
-
-       sc->sc_lestats.lexints++;
-       if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
-               sc->sc_xint++;
-               return;
-       }
-       if (tmd->tmd1_bits & LE_T1_OWN) {
-               sc->sc_xown++;
-               return;
-       }
-       if (tmd->tmd1_bits & LE_T1_ERR) {
-err:
-               lexerror(sc);
-               sc->sc_if.if_oerrors++;
-               if (tmd->tmd3 & (LE_T3_BUFF|LE_T3_UFLO)) {
-                       sc->sc_uflo++;
-                       lereset(&sc->sc_dev);
-               } else if (tmd->tmd3 & LE_T3_LCOL)
-                       sc->sc_if.if_collisions++;
-               else if (tmd->tmd3 & LE_T3_RTRY)
-                       sc->sc_if.if_collisions += 16;
-       }
-       else if (tmd->tmd3 & LE_T3_BUFF)
-               /* XXX documentation says BUFF not included in ERR */
-               goto err;
-       else if (tmd->tmd1_bits & LE_T1_ONE)
-               sc->sc_if.if_collisions++;
-       else if (tmd->tmd1_bits & LE_T1_MORE)
-               /* what is the real number? */
-               sc->sc_if.if_collisions += 2;
-       else
-               sc->sc_if.if_opackets++;
-       sc->sc_if.if_flags &= ~IFF_OACTIVE;
-       lestart(&sc->sc_if);
-}
-
-#define        LENEXTRMP \
-       if (++bix == LERBUF) bix = 0, rmd = sc->sc_r2->ler2_rmd; else ++rmd
-
-/*
- * Ethernet interface receiver interrupt.
- * If input error just drop packet.
- * Decapsulate packet based on type and pass to type specific
- * higher-level input routine.
- */
-void
-lerint(sc)
-       register struct le_softc *sc;
-{
-       register int bix = sc->sc_rmd;
-       register struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];
-
-       sc->sc_lestats.lerints++;
-       /*
-        * Out of sync with hardware, should never happen?
-        */
-       if (rmd->rmd1_bits & LE_R1_OWN) {
-               do {
-                       sc->sc_lestats.lerscans++;
-                       LENEXTRMP;
-               } while ((rmd->rmd1_bits & LE_R1_OWN) && bix != sc->sc_rmd);
-               if (bix == sc->sc_rmd)
-                       printf("%s: RINT with no buffer\n",
-                           sc->sc_dev.dv_xname);
-       } else
-               sc->sc_lestats.lerhits++;
-
-       /*
-        * Process all buffers with valid data
-        */
-       while ((rmd->rmd1_bits & LE_R1_OWN) == 0) {
-               int len = rmd->rmd3;
-
-               /* Clear interrupt to avoid race condition */
-               sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
-
-               if (rmd->rmd1_bits & LE_R1_ERR) {
-                       sc->sc_rmd = bix;
-                       lererror(sc, "bad packet");
-                       sc->sc_if.if_ierrors++;
-               } else if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) !=
-                   (LE_R1_STP|LE_R1_ENP)) {
-                       /* XXX make a define for LE_R1_STP|LE_R1_ENP? */
-                       /*
-                        * Find the end of the packet so we can see how long
-                        * it was.  We still throw it away.
-                        */
-                       do {
-                               sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
-                               rmd->rmd3 = 0;
-                               rmd->rmd1_bits = LE_R1_OWN;
-                               LENEXTRMP;
-                       } while (!(rmd->rmd1_bits &
-                           (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)));
-                       sc->sc_rmd = bix;
-                       lererror(sc, "chained buffer");
-                       sc->sc_rxlen++;
-                       /*
-                        * If search terminated without successful completion
-                        * we reset the hardware (conservative).
-                        */
-                       if ((rmd->rmd1_bits &
-                           (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)) !=
-                           LE_R1_ENP) {
-                               lereset(&sc->sc_dev);
-                               return;
-                       }
-               } else {
-                       leread(sc, (char *)sc->sc_r2->ler2_rbuf[bix], len);
-#ifdef PACKETSTATS
-                       lerpacketsizes[len]++;
-#endif
-                       sc->sc_lestats.lerbufs++;
-               }
-               rmd->rmd3 = 0;
-               rmd->rmd1_bits = LE_R1_OWN;
-               LENEXTRMP;
-       }
-       sc->sc_rmd = bix;
-}
-
-void
-leread(sc, pkt, len)
-       register struct le_softc *sc;
-       char *pkt;
-       int len;
-{
-       register struct ether_header *et;
-       register struct ifnet *ifp = &sc->sc_if;
-       struct mbuf *m;
-       struct ifqueue *inq;
-       int flags;
-
-       ifp->if_ipackets++;
-       et = (struct ether_header *)pkt;
-       et->ether_type = ntohs((u_short)et->ether_type);
-       /* adjust input length to account for header and CRC */
-       len -= sizeof(struct ether_header) + 4;
-
-       if (len <= 0) {
-               if (ledebug)
-                       log(LOG_WARNING,
-                           "%s: ierror(runt packet): from %s: len=%d\n",
-                           sc->sc_dev.dv_xname,
-                           ether_sprintf(et->ether_shost), len);
-               sc->sc_runt++;
-               ifp->if_ierrors++;
-               return;
-       }
-
-       /* Setup mbuf flags we'll need later */
-       flags = 0;
-       if (bcmp((caddr_t)etherbroadcastaddr,
-           (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
-               flags |= M_BCAST;
-       if (et->ether_dhost[0] & 1)
-               flags |= M_MCAST;
-
-#if NBPFILTER > 0
-       /*
-        * Check if there's a bpf filter listening on this interface.
-        * If so, hand off the raw packet to enet, then discard things
-        * not destined for us (but be sure to keep broadcast/multicast).
-        */
-       if (sc->sc_if.if_bpf) {
-               bpf_tap(sc->sc_if.if_bpf, pkt,
-                   len + sizeof(struct ether_header));
-               if ((flags & (M_BCAST | M_MCAST)) == 0 &&
-                   bcmp(et->ether_dhost, sc->sc_addr,
-                           sizeof(et->ether_dhost)) != 0)
-                       return;
-       }
-#endif
-       m = leget(pkt, len, 0, ifp);
-       if (m == 0)
-               return;
-       ether_input(ifp, et, m);
-}
-
-/*
- * Routine to copy from mbuf chain to transmit
- * buffer in board local memory.
- *
- * ### this can be done by remapping in some cases
- */
-int
-leput(lebuf, m)
-       register char *lebuf;
-       register struct mbuf *m;
-{
-       register struct mbuf *mp;
-       register int len, tlen = 0;
-
-       for (mp = m; mp; mp = mp->m_next) {
-               len = mp->m_len;
-               if (len == 0)
-                       continue;
-               tlen += len;
-               bcopy(mtod(mp, char *), lebuf, len);
-               lebuf += len;
-       }
-       m_freem(m);
-       if (tlen < LEMINSIZE) {
-               bzero(lebuf, LEMINSIZE - tlen);
-               tlen = LEMINSIZE;
-       }
-       return (tlen);
-}
-
-/*
- * Routine to copy from board local memory into mbufs.
- */
-struct mbuf *
-leget(lebuf, totlen, off0, ifp)
-       char *lebuf;
-       int totlen, off0;
-       struct ifnet *ifp;
-{
-       register struct mbuf *m;
-       struct mbuf *top = 0, **mp = &top;
-       register int off = off0, len;
-       register char *cp;
-       char *epkt;
-
-       lebuf += sizeof(struct ether_header);
-       cp = lebuf;
-       epkt = cp + totlen;
-       if (off) {
-               cp += off + 2 * sizeof(u_short);
-               totlen -= 2 * sizeof(u_short);
-       }
-
-       MGETHDR(m, M_DONTWAIT, MT_DATA);
-       if (m == 0)
-               return (0);
-       m->m_pkthdr.rcvif = ifp;
-       m->m_pkthdr.len = totlen;
-       m->m_len = MHLEN;
-
-       while (totlen > 0) {
-               if (top) {
-                       MGET(m, M_DONTWAIT, MT_DATA);
-                       if (m == 0) {
-                               m_freem(top);
-                               return (0);
-                       }
-                       m->m_len = MLEN;
-               }
-               len = min(totlen, epkt - cp);
-               if (len >= MINCLSIZE) {
-                       MCLGET(m, M_DONTWAIT);
-                       if (m->m_flags & M_EXT)
-                               m->m_len = len = min(len, MCLBYTES);
-                       else
-                               len = m->m_len;
-               } else {
-                       /*
-                        * Place initial small packet/header at end of mbuf.
-                        */
-                       if (len < m->m_len) {
-                               if (top == 0 && len + max_linkhdr <= m->m_len)
-                                       m->m_data += max_linkhdr;
-                               m->m_len = len;
-                       } else
-                               len = m->m_len;
-               }
-               bcopy(cp, mtod(m, caddr_t), (unsigned)len);
-               cp += len;
-               *mp = m;
-               mp = &m->m_next;
-               totlen -= len;
-               if (cp == epkt)
-                       cp = lebuf;
-       }
-       return (top);
-}
-
-/*
- * Process an ioctl request.
- */
-int
-leioctl(ifp, cmd, data)
-       register struct ifnet *ifp;
-       u_long cmd;
-       caddr_t data;
-{
-       register struct ifaddr *ifa;
-       register struct le_softc *sc = le_cd.cd_devs[ifp->if_unit];
-       register struct lereg1 *ler1;
-       int s = splnet(), error = 0;
-
-       if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
-               splx(s);
-               return error;
-       }
-
-       switch (cmd) {
-
-       case SIOCSIFADDR:
-               ifa = (struct ifaddr *)data;
-               ifp->if_flags |= IFF_UP;
-               switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
-               case AF_INET:
-                       (void)leinit(ifp->if_unit);
-                       arp_ifinit(&sc->sc_ac, ifa);
-                       break;
-#endif
-               default:
-                       (void)leinit(ifp->if_unit);
-                       break;
-               }
-               break;
-
-       case SIOCSIFFLAGS:
-               ler1 = sc->sc_r1;
-               if ((ifp->if_flags & IFF_UP) == 0 &&
-                   ifp->if_flags & IFF_RUNNING) {
-                       ler1->ler1_rdp = LE_C0_STOP;
-                       ifp->if_flags &= ~IFF_RUNNING;
-               } else if (ifp->if_flags & IFF_UP &&
-                   (ifp->if_flags & IFF_RUNNING) == 0)
-                       (void)leinit(ifp->if_unit);
-               /*
-                * If the state of the promiscuous bit changes, the interface
-                * must be reset to effect the change.
-                */
-               if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
-                   (ifp->if_flags & IFF_RUNNING)) {
-                       sc->sc_iflags = ifp->if_flags;
-                       lereset(&sc->sc_dev);
-                       lestart(ifp);
-               }
-               break;
-
-       case SIOCADDMULTI:
-               error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
-               goto update_multicast;
-
-       case SIOCDELMULTI:
-               error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
-       update_multicast:
-               if (error == ENETRESET) {
-                       /*
-                        * Multicast list has changed; set the hardware
-                        * filter accordingly.
-                        */
-                       lereset(&sc->sc_dev);
-                       error = 0;
-               }
-               break;
-
-       default:
-               error = EINVAL;
-       }
-       splx(s);
-       return (error);
-}
-
-void
-leerror(sc, stat)
-       register struct le_softc *sc;
-       int stat;
-{
-       if (!ledebug)
-               return;
-
-       /*
-        * Not all transceivers implement heartbeat
-        * so we only log CERR once.
-        */
-       if ((stat & LE_C0_CERR) && sc->sc_cerr)
-               return;
-       log(LOG_WARNING, "%s: error: stat=%b\n",
-           sc->sc_dev.dv_xname, stat, LE_C0_BITS);
-}
-
-void
-lererror(sc, msg)
-       register struct le_softc *sc;
-       char *msg;
-{
-       register struct lermd *rmd;
-       int len;
-
-       if (!ledebug)
-               return;
-
-       rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];
-       len = rmd->rmd3;
-       log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
-           sc->sc_dev.dv_xname, msg, len > 11 ?
-           ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) :
-           "unknown",
-           sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS);
-}
-
-void
-lexerror(sc)
-       register struct le_softc *sc;
-{
-       register struct letmd *tmd;
-       register int len, tmd3, tdr;
-
-       if (!ledebug)
-               return;
-
-       tmd = sc->sc_r2->ler2_tmd;
-       tmd3 = tmd->tmd3;
-       tdr = tmd3 & LE_T3_TDR_MASK;
-       len = -(tmd->tmd2 & ~LE_XMD2_ONES);
-       log(LOG_WARNING,
-    "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n",
-           sc->sc_dev.dv_xname, len > 5 ?
-           ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",
-           0, len,
-           tmd->tmd1_bits, LE_T1_BITS,
-           tmd3, LE_T3_BITS, tdr, tdr * 100);
-}
index e2cb7f5..d3bcfd9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_lereg.h,v 1.3 1996/04/28 11:03:22 deraadt Exp $ */
+/*     $OpenBSD: if_lereg.h,v 1.4 1996/05/10 12:42:24 deraadt Exp $ */
 
 /*-
  * Copyright (c) 1982, 1992, 1993
  * @(#)if_lereg.h      8.2 (Berkeley) 10/30/93
  */
 
-#define        LEMTU           1518
-#define        LEMINSIZE       60      /* should be 64 if mode DTCR is set */
-#define        LERBUF          8
-#define        LERBUFLOG2      3
-#define        LE_RLEN         (LERBUFLOG2 << 13)
-#define        LETBUF          1
-#define        LETBUFLOG2      0
-#define        LE_TLEN         (LETBUFLOG2 << 13)
+#define MEMSIZE 0x4000
 
-/* Local Area Network Controller for Ethernet (LANCE) registers */
-struct lereg1 {
-       volatile u_short        ler1_rdp;       /* register data port */
-       volatile u_short        ler1_rap;       /* register address port */
-};
-
-/* register addresses */
-#define        LE_CSR0         0               /* Control and status register */
-#define        LE_CSR1         1               /* low address of init block */
-#define        LE_CSR2         2               /* high address of init block */
-#define        LE_CSR3         3               /* Bus master and control */
-
-/* Control and status register 0 (csr0) */
-#define        LE_C0_ERR       0x8000          /* error summary */
-#define        LE_C0_BABL      0x4000          /* transmitter timeout error */
-#define        LE_C0_CERR      0x2000          /* collision */
-#define        LE_C0_MISS      0x1000          /* missed a packet */
-#define        LE_C0_MERR      0x0800          /* memory error */
-#define        LE_C0_RINT      0x0400          /* receiver interrupt */
-#define        LE_C0_TINT      0x0200          /* transmitter interrupt */
-#define        LE_C0_IDON      0x0100          /* initalization done */
-#define        LE_C0_INTR      0x0080          /* interrupt condition */
-#define        LE_C0_INEA      0x0040          /* interrupt enable */
-#define        LE_C0_RXON      0x0020          /* receiver on */
-#define        LE_C0_TXON      0x0010          /* transmitter on */
-#define        LE_C0_TDMD      0x0008          /* transmit demand */
-#define        LE_C0_STOP      0x0004          /* disable all external activity */
-#define        LE_C0_STRT      0x0002          /* enable external activity */
-#define        LE_C0_INIT      0x0001          /* begin initalization */
-
-#define LE_C0_BITS \
-    "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\
-\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"
-
-/* Control and status register 3 (csr3) */
-#define        LE_C3_BSWP      0x4             /* byte swap */
-#define        LE_C3_ACON      0x2             /* ALE control, eh? */
-#define        LE_C3_BCON      0x1             /* byte control */
 /*
- * Current size is 13,758 bytes with 8 x 1518 receive buffers and
- * 1 x 1518 transmit buffer.
+ * LANCE registers.
  */
-struct lereg2 {
-       /* initialization block */
-       volatile u_short        ler2_mode;      /* mode */
-       volatile u_char ler2_padr[6];           /* physical address */
-       volatile u_short        ler2_ladrf[4];  /* logical address filter */
-       volatile u_short        ler2_rdra;      /* receive descriptor addr */
-       volatile u_short        ler2_rlen;      /* rda high and ring size */
-       volatile u_short        ler2_tdra;      /* transmit descriptor addr */
-       volatile u_short        ler2_tlen;      /* tda high and ring size */
-       /* receive message descriptors. bits/hadr are byte order dependent. */
-       struct  lermd {
-               volatile u_short        rmd0;   /* low address of packet */
-               volatile u_char rmd1_bits;      /* descriptor bits */
-               volatile u_char rmd1_hadr;      /* high address of packet */
-               volatile short  rmd2;           /* buffer byte count */
-               volatile u_short        rmd3;   /* message byte count */
-       } ler2_rmd[LERBUF];
-       /* transmit message descriptors */
-       struct  letmd {
-               volatile u_short        tmd0;   /* low address of packet */
-               volatile u_char tmd1_bits;      /* descriptor bits */
-               volatile u_char tmd1_hadr;      /* high address of packet */
-               volatile short  tmd2;           /* buffer byte count */
-               volatile u_short        tmd3;   /* transmit error bits */
-       } ler2_tmd[LETBUF];
-       volatile char   ler2_rbuf[LERBUF][LEMTU];
-       volatile char   ler2_tbuf[LETBUF][LEMTU];
+struct lereg1 {
+        volatile u_int16_t      ler1_rdp;       /* data port */
+        volatile u_int16_t      ler1_rap;       /* register select port */
 };
-
-/* Initialzation block (mode) */
-#define        LE_MODE_PROM    0x8000          /* promiscuous mode */
-/*                     0x7f80             reserved, must be zero */
-#define        LE_MODE_INTL    0x0040          /* internal loopback */
-#define        LE_MODE_DRTY    0x0020          /* disable retry */
-#define        LE_MODE_COLL    0x0010          /* force a collision */
-#define        LE_MODE_DTCR    0x0008          /* disable transmit CRC */
-#define        LE_MODE_LOOP    0x0004          /* loopback mode */
-#define        LE_MODE_DTX     0x0002          /* disable transmitter */
-#define        LE_MODE_DRX     0x0001          /* disable receiver */
-#define        LE_MODE_NORMAL  0               /* none of the above */
-
-
-/* Receive message descriptor 1 (rmd1_bits) */ 
-#define        LE_R1_OWN       0x80            /* LANCE owns the packet */
-#define        LE_R1_ERR       0x40            /* error summary */
-#define        LE_R1_FRAM      0x20            /* framing error */
-#define        LE_R1_OFLO      0x10            /* overflow error */
-#define        LE_R1_CRC       0x08            /* CRC error */
-#define        LE_R1_BUFF      0x04            /* buffer error */
-#define        LE_R1_STP       0x02            /* start of packet */
-#define        LE_R1_ENP       0x01            /* end of packet */
-
-#define LE_R1_BITS \
-    "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP"
-
-/* Transmit message descriptor 1 (tmd1_bits) */ 
-#define        LE_T1_OWN       0x80            /* LANCE owns the packet */
-#define        LE_T1_ERR       0x40            /* error summary */
-#define        LE_T1_MORE      0x10            /* multiple collisions */
-#define        LE_T1_ONE       0x08            /* single collision */
-#define        LE_T1_DEF       0x04            /* defferred transmit */
-#define        LE_T1_STP       0x02            /* start of packet */
-#define        LE_T1_ENP       0x01            /* end of packet */
-
-#define LE_T1_BITS \
-    "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP"
-
-/* Transmit message descriptor 3 (tmd3) */ 
-#define        LE_T3_BUFF      0x8000          /* buffer error */
-#define        LE_T3_UFLO      0x4000          /* underflow error */
-#define        LE_T3_LCOL      0x1000          /* late collision */
-#define        LE_T3_LCAR      0x0800          /* loss of carrier */
-#define        LE_T3_RTRY      0x0400          /* retry error */
-#define        LE_T3_TDR_MASK  0x03ff          /* time domain reflectometry counter */
-
-#define LE_XMD2_ONES   0xf000
-
-#define LE_T3_BITS \
-    "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"
diff --git a/sys/arch/mvme68k/dev/if_levar.h b/sys/arch/mvme68k/dev/if_levar.h
new file mode 100644 (file)
index 0000000..45e8d78
--- /dev/null
@@ -0,0 +1,55 @@
+/*     $NetBSD: if_levar.h,v 1.5 1996/05/07 01:27:32 thorpej Exp $     */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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 University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
+ */
+
+/*
+ * Ethernet software status per interface.
+ *
+ * Each interface is referenced by a network interface structure,
+ * arpcom.ac_if, which the routing code uses to locate the interface.
+ * This structure contains the output queue for the interface, its address, ...
+ */
+struct le_softc {
+       struct  am7990_softc sc_am7990; /* glue to MI code */
+
+       struct  intrhand sc_ih;         /* interrupt vectoring */
+       struct  lereg1 *sc_r1;          /* LANCE registers */
+       struct  evcnt   sc_intrcnt;
+       struct  evcnt   sc_errcnt;
+};