if_name/if_unit -> if_xname/if_softc
authorderaadt <deraadt@openbsd.org>
Fri, 10 May 1996 12:41:10 +0000 (12:41 +0000)
committerderaadt <deraadt@openbsd.org>
Fri, 10 May 1996 12:41:10 +0000 (12:41 +0000)
25 files changed:
sys/dev/ic/am7990.c
sys/dev/ic/am7990var.h
sys/dev/ic/elink3.c
sys/dev/ic/i82595reg.h [new file with mode: 0644]
sys/dev/ic/pdq_ifsubr.c
sys/dev/ic/pdqvar.h
sys/dev/ic/smc90cx6.c
sys/dev/isa/if_ed.c
sys/dev/isa/if_eg.c
sys/dev/isa/if_el.c
sys/dev/isa/if_fe.c
sys/dev/isa/if_ie.c
sys/dev/isa/if_iy.c [new file with mode: 0644]
sys/dev/isa/if_le.c
sys/dev/isa/if_le_isa.c [new file with mode: 0644]
sys/dev/isa/if_levar.h
sys/dev/pci/if_de.c
sys/dev/pci/if_fpa.c
sys/dev/pci/if_le_pci.c [new file with mode: 0644]
sys/dev/pci/if_levar.h [new file with mode: 0644]
sys/dev/tc/if_le.c
sys/dev/tc/if_le_dec.c [new file with mode: 0644]
sys/dev/tc/if_le_ioasic.c
sys/dev/tc/if_le_tc.c
sys/dev/tc/if_levar.h

index 2b243bd..5f89ebb 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: am7990.c,v 1.7 1996/05/05 13:39:31 mickey Exp $       */
-/*     $NetBSD: am7990.c,v 1.18 1996/04/22 02:40:50 christos Exp $     */
+/*     $OpenBSD: am7990.c,v 1.8 1996/05/10 12:41:10 deraadt Exp $      */
+/*     $NetBSD: am7990.c,v 1.19 1996/05/07 01:38:35 thorpej Exp $      */
 
 /*-
  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
  *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
  */
 
+#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 <sys/ioctl.h>
 #include <sys/errno.h>
 
+#include <net/if.h>
+
 #ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
 #include <net/bpfdesc.h>
 #endif
 
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
 #ifdef LEDEBUG
-void recv_print __P((struct le_softc *, int));
-void xmit_print __P((struct le_softc *, int));
+void am7990_recv_print __P((struct am7990_softc *, int));
+void am7990_xmit_print __P((struct am7990_softc *, int));
 #endif
 
+integrate void am7990_rint __P((struct am7990_softc *));
+integrate void am7990_tint __P((struct am7990_softc *));
+
+integrate int am7990_put __P((struct am7990_softc *, int, struct mbuf *));
+integrate struct mbuf *am7990_get __P((struct am7990_softc *, int, int));
+integrate void am7990_read __P((struct am7990_softc *, int, int)); 
+
+hide void am7990_shutdown __P((void *));
+
 #define        ifp     (&sc->sc_arpcom.ac_if)
 
+#if 0  /* XXX what do we do about this?!  --thorpej */
+static inline u_int16_t ether_cmp __P((void *, void *));
+
+/*
+ * Compare two Ether/802 addresses for equality, inlined and
+ * unrolled for speed.  I'd love to have an inline assembler
+ * version of this...   XXX: Who wanted that? mycroft?
+ * I wrote one, but the following is just as efficient.
+ * This expands to 10 short m68k instructions! -gwr
+ * Note: use this like bcmp()
+ */
+static inline u_short
+ether_cmp(one, two)
+       void *one, *two;
+{
+       register u_int16_t *a = (u_short *) one;
+       register u_int16_t *b = (u_short *) two;
+       register u_int16_t diff;
+
+       diff  = *a++ - *b++;
+       diff |= *a++ - *b++;
+       diff |= *a++ - *b++;
+
+       return (diff);
+}
+
+#define ETHER_CMP      ether_cmp
+#endif /* XXX */
+
 #ifndef        ETHER_CMP
 #define        ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN)
 #endif
 
+/*
+ * am7990 configuration driver.  Attachments are provided by
+ * machine-dependent driver front-ends.
+ */
+struct cfdriver le_cd = {
+       NULL, "le", DV_IFNET
+};
+
 void
-leconfig(sc)
-       struct le_softc *sc;
+am7990_config(sc)
+       struct am7990_softc *sc;
 {
        int mem;
 
        /* Make sure the chip is stopped. */
-       lestop(sc);
+       am7990_stop(sc);
 
        /* Initialize ifnet structure. */
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_start = lestart;
-       ifp->if_ioctl = leioctl;
-       ifp->if_watchdog = lewatchdog;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
+       ifp->if_start = am7990_start;
+       ifp->if_ioctl = am7990_ioctl;
+       ifp->if_watchdog = am7990_watchdog;
        ifp->if_flags =
            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
 #ifdef LANCE_REVC_BUG
@@ -111,13 +174,17 @@ leconfig(sc)
                sc->sc_ntbuf = 8;
                break;
        default:
-               panic("leconfig: weird memory size");
+               panic("am7990_config: weird memory size");
        }
 
        printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
        printf("%s: %d receive buffers, %d transmit buffers\n",
            sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
 
+       sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc);
+       if (sc->sc_sh == NULL)
+               panic("am7990_config: can't establish shutdownhook");
+
        mem = 0;
        sc->sc_initaddr = mem;
        mem += sizeof(struct leinit);
@@ -136,34 +203,22 @@ leconfig(sc)
 }
 
 void
-lereset(sc)
-       struct le_softc *sc;
+am7990_reset(sc)
+       struct am7990_softc *sc;
 {
        int s;
 
        s = splimp();
-       leinit(sc);
+       am7990_init(sc);
        splx(s);
 }
 
-void
-lewatchdog(unit)
-       int unit;
-{
-       struct le_softc *sc = LE_SOFTC(unit);
-
-       log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
-       ++ifp->if_oerrors;
-
-       lereset(sc);
-}
-
 /*
  * Set up the initialization block and the descriptor rings.
  */
 void
-lememinit(sc)
-       register struct le_softc *sc;
+am7990_meminit(sc)
+       register struct am7990_softc *sc;
 {
        u_long a;
        int bix;
@@ -183,7 +238,7 @@ lememinit(sc)
            (sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2];
        init.init_padr[2] =
            (sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4];
-       lesetladrf(&sc->sc_arpcom, init.init_ladrf);
+       am7990_setladrf(&sc->sc_arpcom, init.init_ladrf);
 
        sc->sc_last_rd = 0;
        sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
@@ -228,11 +283,11 @@ lememinit(sc)
 }
 
 void
-lestop(sc)
-       struct le_softc *sc;
+am7990_stop(sc)
+       struct am7990_softc *sc;
 {
 
-       lewrcsr(sc, LE_CSR0, LE_C0_STOP);
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
 }
 
 /*
@@ -240,45 +295,47 @@ lestop(sc)
  * and transmit/receive descriptor rings.
  */
 void
-leinit(sc)
-       register struct le_softc *sc;
+am7990_init(sc)
+       register struct am7990_softc *sc;
 {
        register int timo;
        u_long a;
 
-       lewrcsr(sc, LE_CSR0, LE_C0_STOP);
-       LE_DELAY(100);
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
+       DELAY(100);
 
        /* Set the correct byte swapping mode, etc. */
-       lewrcsr(sc, LE_CSR3, sc->sc_conf3);
+       (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
 
        /* Set up LANCE init block. */
-       lememinit(sc);
+       am7990_meminit(sc);
 
        /* Give LANCE the physical address of its init block. */
        a = sc->sc_addr + LE_INITADDR(sc);
-       lewrcsr(sc, LE_CSR1, a);
-       lewrcsr(sc, LE_CSR2, a >> 16);
+       (*sc->sc_wrcsr)(sc, LE_CSR1, a);
+       (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
 
        /* Try to initialize the LANCE. */
-       LE_DELAY(100);
-       lewrcsr(sc, LE_CSR0, LE_C0_INIT);
+       DELAY(100);
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
 
        /* Wait for initialization to finish. */
        for (timo = 100000; timo; timo--)
-               if (lerdcsr(sc, LE_CSR0) & LE_C0_IDON)
+               if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
                        break;
 
-       if (lerdcsr(sc, LE_CSR0) & LE_C0_IDON) {
+       if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
                /* Start the LANCE. */
-               lewrcsr(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT | LE_C0_IDON);
+               (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |
+                   LE_C0_IDON);
                ifp->if_flags |= IFF_RUNNING;
                ifp->if_flags &= ~IFF_OACTIVE;
                ifp->if_timer = 0;
-               lestart(ifp);
+               am7990_start(ifp);
        } else
                printf("%s: card failed to initialize\n", sc->sc_dev.dv_xname);
-       lehwinit(sc);
+       if (sc->sc_hwinit)
+               (*sc->sc_hwinit)(sc);
 }
 
 /*
@@ -286,8 +343,8 @@ leinit(sc)
  * network buffer memory.
  */
 integrate int
-leput(sc, boff, m)
-       struct le_softc *sc;
+am7990_put(sc, boff, m)
+       struct am7990_softc *sc;
        int boff;
        register struct mbuf *m;
 {
@@ -319,8 +376,8 @@ leput(sc, boff, m)
  * we copy into clusters.
  */
 integrate struct mbuf *
-leget(sc, boff, totlen)
-       struct le_softc *sc;
+am7990_get(sc, boff, totlen)
+       struct am7990_softc *sc;
        int boff, totlen;
 {
        register struct mbuf *m;
@@ -367,8 +424,8 @@ leget(sc, boff, totlen)
  * Pass a packet to the higher levels.
  */
 integrate void
-leread(sc, boff, len)
-       register struct le_softc *sc;
+am7990_read(sc, boff, len)
+       register struct am7990_softc *sc;
        int boff, len;
 {
        struct mbuf *m;
@@ -385,7 +442,7 @@ leread(sc, boff, len)
        }
 
        /* Pull packet off interface. */
-       m = leget(sc, boff, len);
+       m = am7990_get(sc, boff, len);
        if (m == 0) {
                ifp->if_ierrors++;
                return;
@@ -441,8 +498,8 @@ leread(sc, boff, len)
 }
 
 integrate void
-lerint(sc)
-       struct le_softc *sc;
+am7990_rint(sc)
+       struct am7990_softc *sc;
 {
        register int bix;
        int rp;
@@ -487,9 +544,10 @@ lerint(sc)
                } else {
 #ifdef LEDEBUG
                        if (sc->sc_debug)
-                               recv_print(sc, sc->sc_last_rd);
+                               am7990_recv_print(sc, sc->sc_last_rd);
 #endif
-                       leread(sc, LE_RBUFADDR(sc, bix), (int)rmd.rmd3 - 4);
+                       am7990_read(sc, LE_RBUFADDR(sc, bix),
+                           (int)rmd.rmd3 - 4);
                }
 
                rmd.rmd1_bits = LE_R1_OWN;
@@ -515,8 +573,8 @@ lerint(sc)
 }
 
 integrate void
-letint(sc)
-       register struct le_softc *sc;
+am7990_tint(sc)
+       register struct am7990_softc *sc;
 {
        register int bix;
        struct letmd tmd;
@@ -546,20 +604,23 @@ letint(sc)
 
                if (tmd.tmd1_bits & LE_T1_ERR) {
                        if (tmd.tmd3 & LE_T3_BUFF)
-                               printf("%s: transmit buffer error\n", sc->sc_dev.dv_xname);
+                               printf("%s: transmit buffer error\n",
+                                   sc->sc_dev.dv_xname);
                        else if (tmd.tmd3 & LE_T3_UFLO)
                                printf("%s: underflow\n", sc->sc_dev.dv_xname);
                        if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
-                               lereset(sc);
+                               am7990_reset(sc);
                                return;
                        }
                        if (tmd.tmd3 & LE_T3_LCAR)
-                               printf("%s: lost carrier\n", sc->sc_dev.dv_xname);
+                               printf("%s: lost carrier\n",
+                                   sc->sc_dev.dv_xname);
                        if (tmd.tmd3 & LE_T3_LCOL)
                                ifp->if_collisions++;
                        if (tmd.tmd3 & LE_T3_RTRY) {
                                printf("%s: excessive collisions, tdr %d\n",
-                                   sc->sc_dev.dv_xname, tmd.tmd3 & LE_T3_TDR_MASK);
+                                   sc->sc_dev.dv_xname,
+                                   tmd.tmd3 & LE_T3_TDR_MASK);
                                ifp->if_collisions += 16;
                        }
                        ifp->if_oerrors++;
@@ -580,7 +641,7 @@ letint(sc)
 
        sc->sc_first_td = bix;
 
-       lestart(ifp);
+       am7990_start(ifp);
 
        if (sc->sc_no_td == 0)
                ifp->if_timer = 0;
@@ -590,22 +651,22 @@ letint(sc)
  * Controller interrupt.
  */
 int
-leintr(arg)
+am7990_intr(arg)
        register void *arg;
 {
-       register struct le_softc *sc = arg;
+       register struct am7990_softc *sc = arg;
        register u_int16_t isr;
 
-       isr = lerdcsr(sc, LE_CSR0);
+       isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
 #ifdef LEDEBUG
        if (sc->sc_debug)
-               printf("%s: leintr entering with isr=%04x\n",
+               printf("%s: am7990_intr entering with isr=%04x\n",
                    sc->sc_dev.dv_xname, isr);
 #endif
        if ((isr & LE_C0_INTR) == 0)
                return (0);
 
-       lewrcsr(sc, LE_CSR0,
+       (*sc->sc_wrcsr)(sc, LE_CSR0,
            isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
                   LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
        if (isr & LE_C0_ERR) {
@@ -629,7 +690,7 @@ leintr(arg)
                }
                if (isr & LE_C0_MERR) {
                        printf("%s: memory error\n", sc->sc_dev.dv_xname);
-                       lereset(sc);
+                       am7990_reset(sc);
                        return (1);
                }
        }
@@ -637,26 +698,38 @@ leintr(arg)
        if ((isr & LE_C0_RXON) == 0) {
                printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
                ifp->if_ierrors++;
-               lereset(sc);
+               am7990_reset(sc);
                return (1);
        }
        if ((isr & LE_C0_TXON) == 0) {
                printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
                ifp->if_oerrors++;
-               lereset(sc);
+               am7990_reset(sc);
                return (1);
        }
 
        if (isr & LE_C0_RINT)
-               lerint(sc);
+               am7990_rint(sc);
        if (isr & LE_C0_TINT)
-               letint(sc);
+               am7990_tint(sc);
 
        return (1);
 }
 
 #undef ifp
 
+void
+am7990_watchdog(ifp)
+       struct ifnet *ifp;
+{
+       struct am7990_softc *sc = ifp->if_softc;
+
+       log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
+       ++ifp->if_oerrors;
+
+       am7990_reset(sc);
+}
+
 /*
  * Setup output on interface.
  * Get another datagram to send off of the interface queue, and map it to the
@@ -664,10 +737,10 @@ leintr(arg)
  * Called only at splimp or interrupt level.
  */
 void
-lestart(ifp)
+am7990_start(ifp)
        register struct ifnet *ifp;
 {
-       register struct le_softc *sc = LE_SOFTC(ifp->if_unit);
+       register struct am7990_softc *sc = ifp->if_softc;
        register int bix;
        register struct mbuf *m;
        struct letmd tmd;
@@ -705,7 +778,7 @@ lestart(ifp)
                /*
                 * Copy the mbuf chain into the transmit buffer.
                 */
-               len = leput(sc, LE_TBUFADDR(sc, bix), m);
+               len = am7990_put(sc, LE_TBUFADDR(sc, bix), m);
 
 #ifdef LEDEBUG
                if (len > ETHERMTU + sizeof(struct ether_header))
@@ -725,10 +798,10 @@ lestart(ifp)
 
 #ifdef LEDEBUG
                if (sc->sc_debug)
-                       xmit_print(sc, sc->sc_last_td);
+                       am7990_xmit_print(sc, sc->sc_last_td);
 #endif
 
-               lewrcsr(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
+               (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
 
                if (++bix == sc->sc_ntbuf)
                        bix = 0;
@@ -747,12 +820,12 @@ lestart(ifp)
  * Process an ioctl request.
  */
 int
-leioctl(ifp, cmd, data)
+am7990_ioctl(ifp, cmd, data)
        register struct ifnet *ifp;
        u_long cmd;
        caddr_t data;
 {
-       struct le_softc *sc = LE_SOFTC(ifp->if_unit);
+       register struct am7990_softc *sc = ifp->if_softc;
        struct ifaddr *ifa = (struct ifaddr *)data;
        struct ifreq *ifr = (struct ifreq *)data;
        int s, error = 0;
@@ -772,12 +845,12 @@ leioctl(ifp, cmd, data)
                switch (ifa->ifa_addr->sa_family) {
 #ifdef INET
                case AF_INET:
-                       leinit(sc);
+                       am7990_init(sc);
                        arp_ifinit(&sc->sc_arpcom, ifa);
                        break;
 #endif
                default:
-                       leinit(sc);
+                       am7990_init(sc);
                        break;
                }
                break;
@@ -789,7 +862,7 @@ leioctl(ifp, cmd, data)
                         * If interface is marked down and it is running, then
                         * stop it.
                         */
-                       lestop(sc);
+                       am7990_stop(sc);
                        ifp->if_flags &= ~IFF_RUNNING;
                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                           (ifp->if_flags & IFF_RUNNING) == 0) {
@@ -797,14 +870,14 @@ leioctl(ifp, cmd, data)
                         * If interface is marked up and it is stopped, then
                         * start it.
                         */
-                       leinit(sc);
+                       am7990_init(sc);
                } else {
                        /*
                         * Reset the interface to pick up changes in any other
                         * flags that affect hardware registers.
                         */
-                       /*lestop(sc);*/
-                       leinit(sc);
+                       /*am7990_stop(sc);*/
+                       am7990_init(sc);
                }
 #ifdef LEDEBUG
                if (ifp->if_flags & IFF_DEBUG)
@@ -825,7 +898,7 @@ leioctl(ifp, cmd, data)
                         * Multicast list has changed; set the hardware filter
                         * accordingly.
                         */
-                       lereset(sc);
+                       am7990_reset(sc);
                        error = 0;
                }
                break;
@@ -839,10 +912,18 @@ leioctl(ifp, cmd, data)
        return (error);
 }
 
+hide void
+am7990_shutdown(arg)
+       void *arg;
+{
+
+       am7990_stop((struct am7990_softc *)arg);
+}
+
 #ifdef LEDEBUG
 void
-recv_print(sc, no)
-       struct le_softc *sc;
+am7990_recv_print(sc, no)
+       struct am7990_softc *sc;
        int no;
 {
        struct lermd rmd;
@@ -853,7 +934,8 @@ recv_print(sc, no)
        len = rmd.rmd3;
        printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
            len);
-       printf("%s: status %04x\n", sc->sc_dev.dv_xname, lerdcsr(sc, LE_CSR0));
+       printf("%s: status %04x\n", sc->sc_dev.dv_xname,
+           (*sc->sc_rdcsr)(sc, LE_CSR0));
        printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
            sc->sc_dev.dv_xname,
            rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
@@ -867,8 +949,8 @@ recv_print(sc, no)
 }
 
 void
-xmit_print(sc, no)
-       struct le_softc *sc;
+am7990_xmit_print(sc, no)
+       struct am7990_softc *sc;
        int no;
 {
        struct letmd tmd;
@@ -879,7 +961,8 @@ xmit_print(sc, no)
        len = -tmd.tmd2;
        printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
            len);
-       printf("%s: status %04x\n", sc->sc_dev.dv_xname, lerdcsr(sc, LE_CSR0));
+       printf("%s: status %04x\n", sc->sc_dev.dv_xname,
+           (*sc->sc_rdcsr)(sc, LE_CSR0));
        printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
            sc->sc_dev.dv_xname,
            tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
@@ -897,7 +980,7 @@ xmit_print(sc, no)
  * Set up the logical address filter.
  */
 void
-lesetladrf(ac, af)
+am7990_setladrf(ac, af)
        struct arpcom *ac;
        u_int16_t *af;
 {
@@ -974,7 +1057,6 @@ allmulti:
  *     (3) gap16 (16 bytes of data followed by 16 bytes of padding).
  */
 
-#ifdef LE_NEED_BUF_CONTIG
 /*
  * contig: contiguous data with no padding.
  *
@@ -983,7 +1065,7 @@ allmulti:
 
 void
 am7990_copytobuf_contig(sc, from, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        void *from;
        int boff, len;
 {
@@ -997,7 +1079,7 @@ am7990_copytobuf_contig(sc, from, boff, len)
 
 void
 am7990_copyfrombuf_contig(sc, to, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        void *to;
        int boff, len;
 {
@@ -1011,7 +1093,7 @@ am7990_copyfrombuf_contig(sc, to, boff, len)
 
 void
 am7990_zerobuf_contig(sc, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        int boff, len;
 {
        volatile caddr_t buf = sc->sc_mem;
@@ -1021,9 +1103,13 @@ am7990_zerobuf_contig(sc, boff, len)
         */
        bzero(buf + boff, len);
 }
-#endif /* LE_NEED_BUF_CONTIG */
 
-#ifdef LE_NEED_BUF_GAP2
+#if 0
+/*
+ * Examples only; duplicate these and tweak (if necessary) in
+ * machine-specific front-ends.
+ */
+
 /*
  * gap2: two bytes of data followed by two bytes of pad.
  *
@@ -1033,7 +1119,7 @@ am7990_zerobuf_contig(sc, boff, len)
 
 void
 am7990_copytobuf_gap2(sc, fromv, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        void *fromv;
        int boff;
        register int len;
@@ -1062,7 +1148,7 @@ am7990_copytobuf_gap2(sc, fromv, boff, len)
 
 void
 am7990_copyfrombuf_gap2(sc, tov, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        void *tov;
        int boff, len;
 {
@@ -1092,7 +1178,7 @@ am7990_copyfrombuf_gap2(sc, tov, boff, len)
 
 void
 am7990_zerobuf_gap2(sc, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        int boff, len;
 {
        volatile caddr_t buf = sc->sc_mem;
@@ -1111,9 +1197,7 @@ am7990_zerobuf_gap2(sc, boff, len)
                len -= 2;
        }
 }
-#endif /* LE_NEED_BUF_GAP2 */
 
-#ifdef LE_NEED_BUF_GAP16
 /*
  * gap16: 16 bytes of data followed by 16 bytes of pad.
  *
@@ -1122,7 +1206,7 @@ am7990_zerobuf_gap2(sc, boff, len)
 
 void
 am7990_copytobuf_gap16(sc, fromv, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        void *fromv;
        int boff;
        register int len;
@@ -1147,7 +1231,7 @@ am7990_copytobuf_gap16(sc, fromv, boff, len)
 
 void
 am7990_copyfrombuf_gap16(sc, tov, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        void *tov;
        int boff, len;
 {
@@ -1171,7 +1255,7 @@ am7990_copyfrombuf_gap16(sc, tov, boff, len)
 
 void
 am7990_zerobuf_gap16(sc, boff, len)
-       struct le_softc *sc;
+       struct am7990_softc *sc;
        int boff, len;
 {
        volatile caddr_t buf = sc->sc_mem;
@@ -1189,4 +1273,4 @@ am7990_zerobuf_gap16(sc, boff, len)
                xfer = min(len, 16);
        }
 }
-#endif /* LE_NEED_BUF_GAP16 */
+#endif /* Example only */
index 337bc87..1aa1afd 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: am7990var.h,v 1.4 1996/05/02 13:51:46 deraadt Exp $   */
-/*     $NetBSD: am7990var.h,v 1.6 1996/04/22 02:40:49 christos Exp $   */
+/*     $OpenBSD: am7990var.h,v 1.5 1996/05/10 12:41:11 deraadt Exp $   */
+/*     $NetBSD: am7990var.h,v 1.7 1996/05/07 01:38:37 thorpej Exp $    */
 
 /*
  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
 
 #ifdef DDB
 #define        integrate
+#define hide
 #else
 #define        integrate       static __inline
+#define hide           static
 #endif
 
-void leconfig __P((struct le_softc *));
-void leinit __P((struct le_softc *));
-int leioctl __P((struct ifnet *, u_long, caddr_t));
-void lememinit __P((struct le_softc *));
-void lereset __P((struct le_softc *));
-void lesetladrf __P((struct arpcom *, u_int16_t *));
-void lestart __P((struct ifnet *));
-void lestop __P((struct le_softc *));
-void lewatchdog __P((int));
+/*
+ * Ethernet software status per device.
+ *
+ * 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, ...
+ *
+ * NOTE: this structure MUST be the first element in machine-dependent
+ * le_softc structures!  This is designed SPECIFICALLY to make it possible
+ * to simply cast a "void *" to "struct le_softc *" or to
+ * "struct am7990_softc *".  Among other things, this saves a lot of hair
+ * in the interrupt handlers.
+ */
+struct am7990_softc {
+       struct  device sc_dev;          /* base device glue */
+       struct  arpcom sc_arpcom;       /* Ethernet common part */
+
+       /*
+        * Memory functions:
+        *
+        *      copy to/from descriptor
+        *      copy to/from buffer
+        *      zero bytes in buffer
+        */
+       void    (*sc_copytodesc)
+                   __P((struct am7990_softc *, void *, int, int));
+       void    (*sc_copyfromdesc)
+                   __P((struct am7990_softc *, void *, int, int));
+       void    (*sc_copytobuf)
+                   __P((struct am7990_softc *, void *, int, int));
+       void    (*sc_copyfrombuf)
+                   __P((struct am7990_softc *, void *, int, int));
+       void    (*sc_zerobuf)
+                   __P((struct am7990_softc *, int, int));
+
+       /*
+        * Machine-dependent functions:
+        *
+        *      read/write CSR
+        *      hardware init hook - may be NULL
+        */
+       u_int16_t (*sc_rdcsr)
+                   __P((struct am7990_softc *, u_int16_t));
+       void    (*sc_wrcsr)
+                   __P((struct am7990_softc *, u_int16_t, u_int16_t));
+       void    (*sc_hwinit) __P((struct am7990_softc *));
+
+       void    *sc_sh;         /* shutdownhook cookie */
+
+       u_int16_t sc_conf3;     /* CSR3 value */
 
-integrate void lehwinit __P((struct le_softc *));
-integrate u_int16_t lerdcsr __P((struct le_softc *, u_int16_t));
-integrate void lewrcsr __P((struct le_softc *, u_int16_t, u_int16_t));
+       void    *sc_mem;        /* base address of RAM -- CPU's view */
+       u_long  sc_addr;        /* base address of RAM -- LANCE's view */
 
-integrate void lerint __P((struct le_softc *));
-integrate void letint __P((struct le_softc *));
+       u_long  sc_memsize;     /* size of RAM */
 
-integrate int leput __P((struct le_softc *, int, struct mbuf *));
-integrate struct mbuf *leget __P((struct le_softc *, int, int));
-integrate void leread __P((struct le_softc *, int, int));
+       int     sc_nrbuf;       /* number of receive buffers */
+       int     sc_ntbuf;       /* number of transmit buffers */
+       int     sc_last_rd;
+       int     sc_first_td, sc_last_td, sc_no_td;
+
+       int     sc_initaddr;
+       int     sc_rmdaddr;
+       int     sc_tmdaddr;
+       int     sc_rbufaddr;
+       int     sc_tbufaddr;
+
+#ifdef LEDEBUG
+       int     sc_debug;
+#endif
+};
+
+/* Export this to machine-dependent drivers. */
+extern struct cfdriver le_cd;
+
+void am7990_config __P((struct am7990_softc *));
+void am7990_init __P((struct am7990_softc *));
+int am7990_ioctl __P((struct ifnet *, u_long, caddr_t));
+void am7990_meminit __P((struct am7990_softc *));
+void am7990_reset __P((struct am7990_softc *));
+void am7990_setladrf __P((struct arpcom *, u_int16_t *));
+void am7990_start __P((struct ifnet *));
+void am7990_stop __P((struct am7990_softc *));
+void am7990_watchdog __P((struct ifnet *));
+int am7990_intr __P((void *));
 
 /*
  * The following functions are only useful on certain cpu/bus
@@ -63,18 +130,16 @@ integrate void leread __P((struct le_softc *, int, int));
  * maximum efficiency, but machine-independent versions are provided
  * for drivers that have not yet been optimized.
  */
-#ifdef LE_NEED_BUF_CONTIG
-void am7990_copytobuf_contig __P((struct le_softc *, void *, int, int));
-void am7990_copyfrombuf_contig __P((struct le_softc *, void *, int, int));
-void am7990_zerobuf_contig __P((struct le_softc *, int, int));
-#endif /* LE_NEED_BUF_CONTIG */
-#ifdef LE_NEED_BUF_GAP2
-void am7990_copytobuf_gap2 __P((struct le_softc *, void *, int, int));
-void am7990_copyfrombuf_gap2 __P((struct le_softc *, void *, int, int));
-void am7990_zerobuf_gap2 __P((struct le_softc *, int, int));
-#endif /* LE_NEED_BUF_GAP2 */
-#ifdef LE_NEED_BUF_GAP16
-void am7990_copytobuf_gap16 __P((struct le_softc *, void *, int, int));
-void am7990_copyfrombuf_gap16 __P((struct le_softc *, void *, int, int));
-void am7990_zerobuf_gap16 __P((struct le_softc *, int, int));
-#endif /* LE_NEED_BUF_GAP16 */
+void am7990_copytobuf_contig __P((struct am7990_softc *, void *, int, int));
+void am7990_copyfrombuf_contig __P((struct am7990_softc *, void *, int, int));
+void am7990_zerobuf_contig __P((struct am7990_softc *, int, int));
+
+#if 0  /* Example only - see am7990.c */
+void am7990_copytobuf_gap2 __P((struct am7990_softc *, void *, int, int));
+void am7990_copyfrombuf_gap2 __P((struct am7990_softc *, void *, int, int));
+void am7990_zerobuf_gap2 __P((struct am7990_softc *, int, int));
+
+void am7990_copytobuf_gap16 __P((struct am7990_softc *, void *, int, int));
+void am7990_copyfrombuf_gap16 __P((struct am7990_softc *, void *, int, int));
+void am7990_zerobuf_gap16 __P((struct am7990_softc *, int, int));
+#endif /* Example only */
index fa99384..8eeba38 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: elink3.c,v 1.4 1996/05/03 19:08:47 christos Exp $      */
+/*     $NetBSD: elink3.c,v 1.5 1996/05/07 01:43:13 thorpej Exp $       */
 
 /*
  * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
@@ -80,7 +80,7 @@ static int epstatus __P((struct ep_softc *));
 void epinit __P((struct ep_softc *));
 int epioctl __P((struct ifnet *, u_long, caddr_t));
 void epstart __P((struct ifnet *));
-void epwatchdog __P((int));
+void epwatchdog __P((struct ifnet *));
 void epreset __P((struct ep_softc *));
 void epread __P((struct ep_softc *));
 struct mbuf *epget __P((struct ep_softc *, int));
@@ -96,12 +96,11 @@ epconfig(sc, conn)
        struct ep_softc *sc;
        u_int conn;
 {
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        bus_chipset_tag_t bc = sc->sc_bc;
        bus_io_handle_t ioh = sc->sc_ioh;
        u_short i;
 
-       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
-
        sc->ep_connectors = 0;
        if (conn & IS_AUI) {
                printf("aui");
@@ -139,8 +138,8 @@ epconfig(sc, conn)
 
        printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
 
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = ep_cd.cd_name;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
        ifp->if_start = epstart;
        ifp->if_ioctl = epioctl;
        ifp->if_watchdog = epwatchdog;
@@ -294,7 +293,7 @@ void
 epstart(ifp)
        struct ifnet *ifp;
 {
-       register struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit];
+       register struct ep_softc *sc = ifp->if_softc;
        bus_chipset_tag_t bc = sc->sc_bc;
        bus_io_handle_t ioh = sc->sc_ioh;
        struct mbuf *m, *m0;
@@ -798,7 +797,7 @@ epioctl(ifp, cmd, data)
        u_long cmd;
        caddr_t data;
 {
-       struct ep_softc *sc = ep_cd.cd_devs[ifp->if_unit];
+       struct ep_softc *sc = ifp->if_softc;
        struct ifaddr *ifa = (struct ifaddr *)data;
        struct ifreq *ifr = (struct ifreq *)data;
        int s, error = 0;
@@ -893,10 +892,10 @@ epreset(sc)
 }
 
 void
-epwatchdog(unit)
-       int unit;
+epwatchdog(ifp)
+       struct ifnet *ifp;
 {
-       struct ep_softc *sc = ep_cd.cd_devs[unit];
+       struct ep_softc *sc = ifp->if_softc;
 
        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        ++sc->sc_arpcom.ac_if.if_oerrors;
diff --git a/sys/dev/ic/i82595reg.h b/sys/dev/ic/i82595reg.h
new file mode 100644 (file)
index 0000000..9d6a981
--- /dev/null
@@ -0,0 +1,219 @@
+/*     $NetBSD: i82595reg.h,v 1.1 1996/05/06 21:36:51 is Exp $ */
+
+/*
+ * Copyright (c) 1996, Ignatios Souvatzis.
+ * 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 Ignatios Souvatzis
+ *     for the NetBSD project.
+ * 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 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 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.
+ */
+
+/*
+ * Intel 82595 Ethernet chip register, bit, and structure definitions.
+ *
+ * Written by is with reference to Intel's i82595FX data sheet, with some 
+ * clarification coming from looking at the Clarkson Packet Driver code for this
+ * chip written by Russ Nelson and others;
+ *
+ * and
+ *
+ * configuration EEPROM layout. Written with reference to Intels
+ * public "LAN595 Hardware and Software Specifications" document.
+ */
+
+/* registers */
+
+/* bank0 */
+
+#define COMMAND_REG 0  /* available in any bank */
+
+#define                MC_SETUP_CMD    0x03
+#define                XMT_CMD         0x04
+#define                TDR_CMD         0x05
+#define                DUMP_CMD        0x06
+#define                DIAG_CMD        0x07
+#define                RCV_ENABLE_CMD  0x08
+#define                RCV_DISABLE_CMD 0x0a
+#define                RCV_STOP_CMD    0x0b
+#define                RESET_CMD       0x0e
+#define                TRISTATE_CMD    0x16
+#define                NO_TRISTATE_CMD 0x17
+#define                POWER_DOWN_CMD  0x18
+#define                SLEEP_MODE_CMD  0x19
+#define                NEGOTIATE_CMD   0x1a
+#define                RESUME_XMT_CMD  0x1c
+#define                SEL_RESET_CMD   0x1e
+#define                BANK_SEL(n)     (n<<6)  /* 0, 1, 2 */
+
+#define STATUS_REG 1
+
+#define                RX_STP_INT      0x01
+#define                RX_INT          0x02
+#define                TX_INT          0x04
+#define                EXEC_INT        0x08
+#define                EXEC_STATUS     0x30
+
+#define ID_REG 2
+
+#define                ID_REG_MASK     0x2c
+#define                ID_REG_SIG      0x24
+#define                R_ROBIN_BITS    0xc0
+#define                R_ROBIN_SHIFT   6
+#define                AUTO_ENABLE     0x10
+
+#define INT_MASK_REG 3
+
+#define                RX_STOP_BIT     0x01
+#define                RX_BIT          0x02
+#define                TX_BIT          0x04
+#define                EXEC_BIT        0x08
+#define                ALL_INTS        0x0f
+
+#define RCV_START_LOW 4
+#define RCV_START_HIGH 5
+
+#define RCV_STOP_LOW 6
+#define RCV_STOP_HIGH 7
+
+#define XMT_ADDR_REG 0x0a
+#define HOST_ADDR_REG 0x0c
+#define MEM_PORT_REG 0x0e
+
+/* -------------------- bank1 -------------------- */
+
+#define REG1 1
+
+#define                WORD_WIDTH      0x02
+#define                INT_ENABLE      0x80
+
+#define INT_NO_REG 2
+
+#define RCV_LOWER_LIMIT_REG 8
+#define RCV_UPPER_LIMIT_REG 9
+
+#define XMT_LOWER_LIMIT_REG 10
+#define XMT_UPPER_LIMIT_REG 11
+
+/* bank2 */
+
+/* reg1, apparently */
+
+#define                XMT_CHAIN_INT   0x20    /* interupt at end of xmt chain */
+#define                XMT_CHAIN_ERRSTOP 0x40  /* int at end of chain even if err */
+#define                RCV_DISCARD_BAD 0x80    /* Throw bad frames away and continue */
+
+#define RECV_MODES_REG 2
+
+#define                PROMISC_MODE    0x01
+#define                NO_RX_CRC       0x04
+#define                NO_ADD_INS      0x10
+#define                MULTI_IA        0x20
+
+#define                MATCH_ID        (NO_ADD_INS | NO_RX_CRC | 0x02)
+#define                MATCH_ALL       (NO_ADD_INS | NO_RX_CRC | 0x01)
+#define                MATCH_BRDCST    (NO_ADD_INS | NO_RX_CRC)
+
+#define MEDIA_SELECT 3
+
+#define                TPE_BIT         0x04
+#define                BNC_BIT         0x20
+#define                TEST_MODE_MASK  0x3f
+
+#define I_ADD(n) (n+4) /* 0..5 -> 4..9 */
+
+#define EEPROM_REG 10
+
+#define                EEDO 8
+#define                EEDI 4
+#define                EECS 2
+#define                EESK 1
+
+/*
+ * EEPROM layout. Written with reference to Intels public "LAN595 Hardware and
+ * Software Specifications" document.
+ */
+
+#define EEPPW0         0
+#define                EEPP_BusWidth   0x0004
+#define                EEPP_FlashAdrs  0x0038
+#define                EEPP_FLASHTRANSFORM {-1, -1, 0xC8000, 0xCC000, 0xD0000, \
+                                       0xD4000, 0xD8000, 0xDC000}
+#define                EEPP_AutoIO     0x0040
+#define                EEPP_IOMapping  0xfc00
+
+#define EEPPW1         1
+#define                EEPP_Int        0x0007
+#define                EEPP_INTMAP     {3, 5, 9, 10, 11, -1, -1, -1}
+#define                EEPP_RINTMAP    {0xff, 0xff, 0x02, 0x00, 0xff, 0x01, 0xff, \
+                                0xff, 0xff, 0x02, 0x03, 0x04 }
+
+#define                EEPP_LinkInteg  0x0008
+#define                EEPP_PolarCorr  0x0010
+#define                EEPP_AuiTpe     0x0020
+#define                EEPP_Jabber     0x0040
+#define                EEPP_AutoPort   0x0080
+#define                EEPP_SmOut      0x0100
+#define                EEPP_BootFls    0x0200
+#define                EEPP_DramSize   0x1000
+#define                EEPP_AltReady   0x2000
+
+#define EEPPEther2     2
+#define EEPPEther1     3
+#define EEPPEther0     4
+
+#define EEPPEther2a    0x3c
+#define EEPPEther1a    0x3d
+#define EEPPEther0a    0x3e
+
+#define EEPPW5         5
+#define                EEPP_BncTpe     0x0001
+#define                EEPP_RomSlct    0x0006  /* none, NetWare, NDIS, rsrvd. */
+#define                EEPP_NumConn    0x0008  /* 0=2, 1=3 */
+
+#define EEPW6          6
+#define EEPP_BoardRev  0x00FF
+
+#define EEPP_LENGTH 0x40
+#define EEPP_CHKSUM 0xBABA /* Intel claim 0x0, but this seems to be wrong */
+
+#define I595_XMT_HDRLEN        8
+
+#define CMD_MASK       0x001f
+#define TX_DONE                0x0080
+#define CHAIN          0x8000
+
+#define XMT_STATUS     0x02
+#define XMT_CHAIN      0x04
+#define XMT_COUNT      0x06
+
+#define I595_RCV_HDRLEN        8
+
+#define RCV_DONE       0x0008
+#define RX_OK          0x2000
+#define RX_ERR         0x0d81
+
+
index 13fe3f5..4526538 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: pdq_ifsubr.c,v 1.1 1996/04/18 23:47:23 niklas Exp $   */
-/*     $NetBSD: pdq_ifsubr.c,v 1.2 1996/03/11 21:41:32 thorpej Exp $   */
+/*     $OpenBSD: pdq_ifsubr.c,v 1.2 1996/05/10 12:41:12 deraadt Exp $  */
+/*     $NetBSD: pdq_ifsubr.c,v 1.3 1996/05/07 01:43:15 thorpej Exp $   */
 
 /*-
  * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
@@ -407,8 +407,8 @@ pdq_ifioctl(
 void
 pdq_ifattach(
     pdq_softc_t *sc,
-    ifnet_ret_t (*ifinit)(int unit),
-    ifnet_ret_t (*ifwatchdog)(int unit))
+    pdq_ifinit_t ifinit,
+    pdq_ifwatchdog_t ifwatchdog)
 {
     struct ifnet *ifp = &sc->sc_if;
 
index d4ebce5..3b40d48 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: pdqvar.h,v 1.2 1996/04/18 23:47:25 niklas Exp $       */
-/*     $NetBSD: pdqvar.h,v 1.4 1996/03/11 21:41:35 thorpej Exp $       */
+/*     $OpenBSD: pdqvar.h,v 1.3 1996/05/10 12:41:13 deraadt Exp $      */
+/*     $NetBSD: pdqvar.h,v 1.5 1996/05/07 01:43:17 thorpej Exp $       */
 
 /*-
  * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
@@ -142,13 +142,21 @@ typedef struct {
 #define        sc_if           sc_ac.ac_if
 #define        sc_bpf          sc_if.if_bpf
 
+#if defined(__NetBSD__)
+typedef ifnet_ret_t (*pdq_ifwatchdog_t)(struct ifnet *ifp);
+typedef ifnet_ret_t (*pdq_ifinit_t)(struct ifnet *ifp);
+#else
+typedef ifnet_ret_t (*pdq_ifwatchdog_t)(int unit);
+typedef ifnet_ret_t (*pdq_ifinit_t)(int unit);
+#endif
+
 extern void pdq_ifreset(pdq_softc_t *sc);
 extern void pdq_ifinit(pdq_softc_t *sc);
 extern void pdq_ifwatchdog(pdq_softc_t *sc);
 extern ifnet_ret_t pdq_ifstart(struct ifnet *ifp);
 extern int pdq_ifioctl(struct ifnet *ifp, ioctl_cmd_t cmd, caddr_t data);
-extern void pdq_ifattach(pdq_softc_t *sc, ifnet_ret_t (*ifinit)(int unit),
-                        ifnet_ret_t (*ifwatchdog)(int unit));
+extern void pdq_ifattach(pdq_softc_t *sc, pdq_ifinit_t ifinit,
+                        pdq_ifwatchdog_t ifwatchdog);
 #endif /* PDQ_HWSUPPORT */
 #elif defined(DLPI_PDQ)
 #include <sys/param.h>
index afa12df..7b45e10 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: smc90cx6.c,v 1.16 1996/03/20 13:28:50 is Exp $ */
+/*     $NetBSD: smc90cx6.c,v 1.17 1996/05/07 01:43:18 thorpej Exp $ */
 
 /*
  * Copyright (c) 1994, 1995 Ignatios Souvatzis
@@ -183,7 +183,7 @@ void        bah_stop __P((struct bah_softc *));
 void   bah_start __P((struct ifnet *));
 int    bahintr __P((struct bah_softc *sc));
 int    bah_ioctl __P((struct ifnet *, unsigned long, caddr_t));
-void   bah_watchdog __P((int));
+void   bah_watchdog __P((struct ifnet *));
 void   movepout __P((u_char *from, u_char __volatile *to, int len));
 void   movepin __P((u_char __volatile *from, u_char *to, int len));
 void   bah_srint __P((void *vsc, void *dummy));
@@ -272,8 +272,8 @@ bah_zbus_attach(parent, self, aux)
         */
        bah_stop(sc); 
 
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = bah_cd.cd_name;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
        ifp->if_output = arc_output;
        ifp->if_start = bah_start;
        ifp->if_ioctl = bah_ioctl;
@@ -360,8 +360,8 @@ bah_reset(sc)
        linkaddress = sc->sc_base->dipswitches;
 
 #if defined(BAH_DEBUG) && (BAH_DEBUG > 2)
-       printf("bah%ld: reset: card reset, link addr = 0x%02x (%ld)\n",
-           ifp->if_unit, linkaddress, linkaddress);
+       printf("%s: reset: card reset, link addr = 0x%02x (%ld)\n",
+           sc->sc_dev.dv_xname, linkaddress, linkaddress);
 #endif
        sc->sc_arccom.ac_anaddr = linkaddress;
 
@@ -540,7 +540,7 @@ bah_start(ifp)
        u_long copystart, lencopy, perbyte;
 #endif
 
-       sc = bah_cd.cd_devs[ifp->if_unit];
+       sc = ifp->if_softc;
 
 #if defined(BAH_DEBUG) && (BAH_DEBUG > 3)
        printf("%s: start(0x%x)\n", sc->sc_dev.dv_xname, ifp);
@@ -1150,7 +1150,7 @@ bah_ioctl(ifp, command, data)
        int s, error;
 
        error = 0;
-       sc = bah_cd.cd_devs[ifp->if_unit];
+       sc = ifp->if_softc;
        ifa = (struct ifaddr *)data;
        s = splnet();
 
@@ -1217,14 +1217,10 @@ bah_ioctl(ifp, command, data)
  */
 
 void
-bah_watchdog(unit)
-int unit;
-{
-       struct bah_softc *sc;
+bah_watchdog(ifp)
        struct ifnet *ifp;
-
-       sc = bah_cd.cd_devs[unit];
-       ifp = &(sc->sc_arccom.ac_if);
+{
+       struct bah_softc *sc = ifp->if_softc;
 
        sc->sc_base->command = ARC_TXDIS;
        return;
index 5435c1f..d520b50 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: if_ed.c,v 1.14 1996/05/07 07:36:47 deraadt Exp $      */
-/*     $NetBSD: if_ed.c,v 1.96 1996/05/03 19:05:30 christos Exp $      */
+/*     $OpenBSD: if_ed.c,v 1.15 1996/05/10 12:41:16 deraadt Exp $      */
+/*     $NetBSD: if_ed.c,v 1.98 1996/05/07 01:55:13 thorpej Exp $       */
 
 /*
  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
@@ -77,6 +77,7 @@ struct ed_softc {
 
        bus_chipset_tag_t sc_bc;  /* bus identifier */
        bus_io_handle_t sc_ioh;   /* io handle */
+       bus_io_handle_t sc_delayioh; /* io handle for `delay port' */
        bus_mem_handle_t sc_memh; /* bus memory handle */
 
        bus_io_size_t   asic_base;      /* offset of ASIC I/O port */
@@ -128,7 +129,7 @@ int ed_find_Novell __P((struct ed_softc *, struct cfdata *,
 int edintr __P((void *));
 int edioctl __P((struct ifnet *, u_long, caddr_t));
 void edstart __P((struct ifnet *));
-void edwatchdog __P((int));
+void edwatchdog __P((struct ifnet *));
 void edreset __P((struct ed_softc *));
 void edinit __P((struct ed_softc *));
 void edstop __P((struct ed_softc *));
@@ -451,6 +452,7 @@ ed_find_WD80x3(sc, cf, ia)
 {
        bus_chipset_tag_t bc;
        bus_io_handle_t ioh;
+       bus_io_handle_t delayioh = ia->ia_delayioh;
        bus_mem_handle_t memh;
        u_int memsize;
        u_char iptr, isa16bit, sum;
@@ -537,7 +539,8 @@ ed_find_WD80x3(sc, cf, ia)
                isa16bit = 1;
                break;
        case ED_TYPE_WD8013EP:          /* also WD8003EP */
-               if (inb(asicbase + ED_WD_ICR) & ED_WD_ICR_16BIT) {
+               if (bus_io_read_1(bc, ioh, asicbase + ED_WD_ICR)
+                   & ED_WD_ICR_16BIT) {
                        isa16bit = 1;
                        memsize = 16384;
                        sc->type_str = "WD8013EP";
@@ -788,8 +791,8 @@ ed_find_WD80x3(sc, cf, ia)
        bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
            sc->wd_msr_proto | ED_WD_MSR_MENB);
 
-       (void) bus_io_read_1(bc, ioh, 0x84);            /* XXX */
-       (void) bus_io_read_1(bc, ioh, 0x84);            /* XXX */
+       (void) bus_io_read_1(bc, delayioh, 0);
+       (void) bus_io_read_1(bc, delayioh, 0);
 
        /* Now zero memory and verify that it is clear. */
        for (i = 0; i < memsize; ++i)
@@ -807,8 +810,8 @@ ed_find_WD80x3(sc, cf, ia)
                        if (isa16bit)
                                bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
                                    sc->wd_laar_proto);
-                       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
-                       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
+                       (void) bus_io_read_1(bc, delayioh, 0);
+                       (void) bus_io_read_1(bc, delayioh, 0);
                        goto out;
                }
 
@@ -824,8 +827,8 @@ ed_find_WD80x3(sc, cf, ia)
        if (isa16bit)
                bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
                    sc->wd_laar_proto);
-       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
-       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
+       (void) bus_io_read_1(bc, delayioh, 0);
+       (void) bus_io_read_1(bc, delayioh, 0);
 
        ia->ia_iosize = ED_WD_IO_PORTS;
        rv = 1;
@@ -1399,13 +1402,14 @@ edattach(parent, self, aux)
        ioh = sc->sc_ioh;               /* XXX */
 
        asicbase = sc->asic_base;
+       sc->sc_delayioh = ia->ia_delayioh;
 
        /* Set interface to stopped condition (reset). */
        edstop(sc);
 
        /* Initialize ifnet structure. */
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = ed_cd.cd_name;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
        ifp->if_start = edstart;
        ifp->if_ioctl = edioctl;
        ifp->if_watchdog = edwatchdog;
@@ -1518,10 +1522,10 @@ edstop(sc)
  * an interrupt after a transmit has been started on it.
  */
 void
-edwatchdog(unit)
-       int unit;
+edwatchdog(ifp)
+       struct ifnet *ifp;
 {
-       struct ed_softc *sc = ed_cd.cd_devs[unit];
+       struct ed_softc *sc = ifp->if_softc;
 
        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        ++sc->sc_arpcom.ac_if.if_oerrors;
@@ -1735,7 +1739,7 @@ void
 edstart(ifp)
        struct ifnet *ifp;
 {
-       struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit];
+       struct ed_softc *sc = ifp->if_softc;
        bus_chipset_tag_t bc = sc->sc_bc;
        bus_io_handle_t ioh = sc->sc_ioh;
        struct mbuf *m0, *m;
@@ -1796,8 +1800,8 @@ outloop:
                                    sc->wd_laar_proto | ED_WD_LAAR_M16EN);
                        bus_io_write_1(bc, ioh, asicbase + ED_WD_MSR,
                            sc->wd_msr_proto | ED_WD_MSR_MENB);
-                       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
-                       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
+                       (void) bus_io_read_1(bc, sc->sc_delayioh, 0);
+                       (void) bus_io_read_1(bc, sc->sc_delayioh, 0);
                        break;
                }
 
@@ -1822,8 +1826,8 @@ outloop:
                        if (sc->isa16bit)
                                bus_io_write_1(bc, ioh, asicbase + ED_WD_LAAR,
                                    sc->wd_laar_proto);
-                       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
-                       (void) bus_io_read_1(bc, ioh, 0x84);    /* XXX */
+                       (void) bus_io_read_1(bc, sc->sc_delayioh, 0);
+                       (void) bus_io_read_1(bc, sc->sc_delayioh, 0);
                        break;
                }
        } else
@@ -2118,9 +2122,10 @@ edintr(arg)
                                        bus_io_write_1(bc, ioh,
                                            asicbase + ED_WD_MSR,
                                            sc->wd_msr_proto | ED_WD_MSR_MENB);
-                                       /* XXX */
-                                       (void) bus_io_read_1(bc, ioh, 0x84);
-                                       (void) bus_io_read_1(bc, ioh, 0x84);
+                                       (void) bus_io_read_1(bc,
+                                           sc->sc_delayioh, 0);
+                                       (void) bus_io_read_1(bc,
+                                           sc->sc_delayioh, 0);
                                }
 
                                ed_rint(sc);
@@ -2134,9 +2139,10 @@ edintr(arg)
                                                bus_io_write_1(bc, ioh,
                                                    asicbase + ED_WD_LAAR,
                                                    sc->wd_laar_proto);
-                                       /* XXX */
-                                       (void) bus_io_read_1(bc, ioh, 0x84);
-                                       (void) bus_io_read_1(bc, ioh, 0x84);
+                                       (void) bus_io_read_1(bc,
+                                           sc->sc_delayioh, 0);
+                                       (void) bus_io_read_1(bc,
+                                           sc->sc_delayioh, 0);
                                }
                        }
                }
@@ -2183,7 +2189,7 @@ edioctl(ifp, cmd, data)
        u_long cmd;
        caddr_t data;
 {
-       struct ed_softc *sc = ed_cd.cd_devs[ifp->if_unit];
+       struct ed_softc *sc = ifp->if_softc;
        register struct ifaddr *ifa = (struct ifaddr *)data;
        struct ifreq *ifr = (struct ifreq *)data;
        int s, error = 0;
index c51baf8..463bbb0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_eg.c,v 1.24 1996/04/11 22:29:03 cgd Exp $   */
+/*     $NetBSD: if_eg.c,v 1.25 1996/05/07 01:55:17 thorpej Exp $       */
 
 /*
  * Copyright (c) 1993 Dean Huxley <dean@fsa.ca>
@@ -125,7 +125,7 @@ void eginit __P((struct eg_softc *));
 int egioctl __P((struct ifnet *, u_long, caddr_t));
 void egrecv __P((struct eg_softc *));
 void egstart __P((struct ifnet *));
-void egwatchdog __P((int));
+void egwatchdog __P((struct ifnet *));
 void egreset __P((struct eg_softc *));
 void egread __P((struct eg_softc *, caddr_t, int));
 struct mbuf *egget __P((struct eg_softc *, caddr_t, int));
@@ -396,8 +396,8 @@ egattach(parent, self, aux)
        }
 
        /* Initialize ifnet structure. */
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = eg_cd.cd_name;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
        ifp->if_start = egstart;
        ifp->if_ioctl = egioctl;
        ifp->if_watchdog = egwatchdog;
@@ -475,8 +475,8 @@ egrecv(sc)
                sc->eg_pcb[3] = 0;
                sc->eg_pcb[4] = 0;
                sc->eg_pcb[5] = 0;
-               sc->eg_pcb[6] = EG_BUFLEN; /* our buffer size */
-               sc->eg_pcb[7] = EG_BUFLEN >> 8;
+               sc->eg_pcb[6] = EG_BUFLEN & 0xff; /* our buffer size */
+               sc->eg_pcb[7] = (EG_BUFLEN >> 8) & 0xff;
                sc->eg_pcb[8] = 0; /* timeout, 0 == none */
                sc->eg_pcb[9] = 0;
                if (egwritePCB(sc) != 0)
@@ -489,7 +489,7 @@ void
 egstart(ifp)
        struct ifnet *ifp;
 {
-       register struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit];
+       register struct eg_softc *sc = ifp->if_softc;
        struct mbuf *m0, *m;
        caddr_t buffer;
        int len;
@@ -728,7 +728,7 @@ egioctl(ifp, cmd, data)
        u_long cmd;
        caddr_t data;
 {
-       struct eg_softc *sc = eg_cd.cd_devs[ifp->if_unit];
+       struct eg_softc *sc = ifp->if_softc;
        struct ifaddr *ifa = (struct ifaddr *)data;
        struct ifreq *ifr = (struct ifreq *)data;
        int s, error = 0;
@@ -810,10 +810,10 @@ egreset(sc)
 }
 
 void
-egwatchdog(unit)
-       int     unit;
+egwatchdog(ifp)
+       struct ifnet *ifp;
 {
-       struct eg_softc *sc = eg_cd.cd_devs[unit];
+       struct eg_softc *sc = ifp->if_softc;
 
        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        sc->sc_arpcom.ac_if.if_oerrors++;
index 42213f5..692b841 100644 (file)
@@ -1,5 +1,5 @@
-/*    $OpenBSD: if_el.c,v 1.9 1996/05/07 07:36:53 deraadt Exp $       */
-/*     $NetBSD: if_el.c,v 1.37 1996/04/29 20:03:17 christos Exp $      */
+/*    $OpenBSD: if_el.c,v 1.10 1996/05/10 12:41:18 deraadt Exp $       */
+/*     $NetBSD: if_el.c,v 1.38 1996/05/07 01:55:20 thorpej Exp $       */
 
 /*
  * Copyright (c) 1994, Matthew E. Kimmel.  Permission is hereby granted
@@ -82,7 +82,7 @@ int elintr __P((void *));
 void elinit __P((struct el_softc *));
 int elioctl __P((struct ifnet *, u_long, caddr_t));
 void elstart __P((struct ifnet *));
-void elwatchdog __P((int));
+void elwatchdog __P((struct ifnet *));
 void elreset __P((struct el_softc *));
 void elstop __P((struct el_softc *));
 static int el_xmit __P((struct el_softc *));
@@ -184,8 +184,8 @@ elattach(parent, self, aux)
        elstop(sc);
 
        /* Initialize ifnet structure. */
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = el_cd.cd_name;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
        ifp->if_start = elstart;
        ifp->if_ioctl = elioctl;
        ifp->if_watchdog = elwatchdog;
@@ -303,7 +303,7 @@ void
 elstart(ifp)
        struct ifnet *ifp;
 {
-       struct el_softc *sc = el_cd.cd_devs[ifp->if_unit];
+       struct el_softc *sc = ifp->if_softc;
        int iobase = sc->sc_iobase;
        struct mbuf *m, *m0;
        int s, i, off, retries;
@@ -615,7 +615,7 @@ elioctl(ifp, cmd, data)
        u_long cmd;
        caddr_t data;
 {
-       struct el_softc *sc = el_cd.cd_devs[ifp->if_unit];
+       struct el_softc *sc = ifp->if_softc;
        struct ifaddr *ifa = (struct ifaddr *)data;
        int s, error = 0;
 
@@ -682,10 +682,10 @@ elioctl(ifp, cmd, data)
  * Device timeout routine.
  */
 void
-elwatchdog(unit)
-       int unit;
+elwatchdog(ifp)
+       struct ifnet *ifp;
 {
-       struct el_softc *sc = el_cd.cd_devs[unit];
+       struct el_softc *sc = ifp->if_softc;
 
        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        sc->sc_arpcom.ac_if.if_oerrors++;
index baa3f87..7f1a211 100644 (file)
@@ -201,7 +201,7 @@ void        fe_init         __P((struct fe_softc *));
 int    fe_ioctl        __P((struct ifnet *, u_long, caddr_t));
 void   fe_start        __P((struct ifnet *));
 void   fe_reset        __P((struct fe_softc *));
-void   fe_watchdog     __P((int));
+void   fe_watchdog     __P((struct ifnet *));
 
 /* Local functions.  Order of declaration is confused.  FIXME. */
 int    fe_probe_fmv    __P((struct fe_softc *, struct isa_attach_args *));
@@ -991,8 +991,8 @@ feattach(parent, self, aux)
        fe_stop(sc);
 
        /* Initialize ifnet structure. */
-       ifp->if_unit = sc->sc_dev.dv_unit;
-       ifp->if_name = fe_cd.cd_name;
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
        ifp->if_start = fe_start;
        ifp->if_ioctl = fe_ioctl;
        ifp->if_watchdog = fe_watchdog;
@@ -1194,10 +1194,10 @@ fe_stop(sc)
  * generate an interrupt after a transmit has been started on it.
  */
 void
-fe_watchdog(unit)
-       int unit;
+fe_watchdog(ifp)
+       struct ifnet *ifp;
 {
-       struct fe_softc *sc = fe_cd.cd_devs[unit];
+       struct fe_softc *sc = ifp->if_softc;
 
        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
 #if FE_DEBUG >= 3
@@ -1419,7 +1419,7 @@ void
 fe_start(ifp)
        struct ifnet *ifp;
 {
-       struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit];
+       struct fe_softc *sc = ifp->if_softc;
        struct mbuf *m;
 
 #if FE_DEBUG >= 1
@@ -1920,7 +1920,7 @@ fe_ioctl(ifp, command, data)
        u_long command;
        caddr_t data;
 {
-       struct fe_softc *sc = fe_cd.cd_devs[ifp->if_unit];
+       struct fe_softc *sc = ifp->if_softc;
        register struct ifaddr *ifa = (struct ifaddr *)data;
        struct ifreq *ifr = (struct ifreq *)data;
        int s, error = 0;
index 8c29261..77c9907 100644 (file)
@@ -1,5 +1,5 @@
-/*    $OpenBSD: if_ie.c,v 1.9 1996/05/07 07:36:59 deraadt Exp $       */
-/*     $NetBSD: if_ie.c,v 1.49 1996/04/30 22:21:54 thorpej Exp $       */
+/*    $OpenBSD: if_ie.c,v 1.10 1996/05/10 12:41:20 deraadt Exp $       */
+/*     $NetBSD: if_ie.c,v 1.50 1996/05/07 01:55:25 thorpej Exp $       */
 
 /*-
  * Copyright (c) 1993, 1994, 1995 Charles Hannum.
@@ -261,7 +261,7 @@ struct ie_softc {
 #endif
 };
 
-void iewatchdog __P((int));
+void iewatchdog __P((struct ifnet *));
 int ieintr __P((void *));
 void iestop __P((struct ie_softc *));
 int ieinit __P((struct ie_softc *));
@@ -788,8 +788,8 @@ ieattach(parent, self, aux)
        struct isa_attach_args *ia = aux;
        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
 
-       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;
@@ -818,10 +818,10 @@ ieattach(parent, self, aux)
  * an interrupt after a transmit has been started on it.
  */
 void
-iewatchdog(unit)
-       int 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;
@@ -1473,7 +1473,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;
@@ -2142,7 +2142,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;
diff --git a/sys/dev/isa/if_iy.c b/sys/dev/isa/if_iy.c
new file mode 100644 (file)
index 0000000..2e8ee04
--- /dev/null
@@ -0,0 +1,1353 @@
+/*     $NetBSD: if_iy.c,v 1.2 1996/05/07 01:55:28 thorpej Exp $        */
+/* #define IYDEBUG */
+/* #define IYMEMDEBUG */
+/*-
+ * Copyright (c) 1996 Ignatios Souvatzis.
+ * 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 contains software developed by Ignatios Souvatzis for
+ *     the NetBSD project.
+ * 4. The names 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 "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/buf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <net/netisr.h>
+#include <net/route.h>
+
+#if NBPFILTER > 0
+#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
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#include <vm/vm.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/ic/i82595reg.h>
+
+#define        ETHER_MIN_LEN   64
+#define        ETHER_MAX_LEN   1518
+
+/*
+ * Ethernet status, per interface.
+ */
+struct iy_softc {
+       struct device sc_dev;
+       void *sc_ih;
+
+       int sc_iobase;
+       struct arpcom sc_arpcom;
+
+#define MAX_MBS 8
+       struct mbuf *mb[MAX_MBS];
+       int next_mb, last_mb;
+
+       int mappedirq;
+
+       int hard_vers;
+
+       int promisc;
+
+       int sram, tx_size, rx_size;
+
+       int tx_start, tx_end, tx_last;
+       int rx_start;
+
+#ifdef IYDEBUG
+       int sc_debug;
+#endif
+};
+
+void iywatchdog __P((struct ifnet *));
+int iyioctl __P((struct ifnet *, u_long, caddr_t));
+int iyintr __P((void *));
+void iyinit __P((struct iy_softc *));
+void iystop __P((struct iy_softc *));
+void iystart __P((struct ifnet *));
+
+void iy_intr_rx __P((struct iy_softc *));
+void iy_intr_tx __P((struct iy_softc *));
+void eepro_reset_595 __P((struct iy_softc *));
+int eepro_probe __P((struct iy_softc *, struct isa_attach_args *));
+void eepro_eeprom_outbits __P((struct iy_softc *, int, int));
+void eepro_eeprom_clock __P((struct iy_softc *, int));
+u_short eepro_read_eeprom __P((struct iy_softc *, int));
+int eepro_eeprom_inbits __P((struct iy_softc *));
+
+void iyreset __P((struct iy_softc *));
+void iy_readframe __P((struct iy_softc *, int));
+void iy_drop_packet_buffer __P((struct iy_softc *));
+void iy_find_mem_size __P((struct iy_softc *));
+void iyrint __P((struct iy_softc *));
+void iytint __P((struct iy_softc *));
+void iyxmit __P((struct iy_softc *));
+void iyget __P((struct iy_softc *, int, int));
+void iymbuffill __P((void *)); 
+void iymbufempty __P((void *));
+void iyprobemem __P((struct iy_softc *));
+
+/*
+ * void iymeminit __P((void *, struct iy_softc *));
+ * static int iy_mc_setup __P((struct iy_softc *, void *));
+ * static void iy_mc_reset __P((struct iy_softc *));
+ */
+#ifdef IYDEBUGX
+void print_rbd __P((volatile struct iy_recv_buf_desc *));
+
+int in_ifrint = 0;
+int in_iftint = 0;
+#endif
+
+int iyprobe __P((struct device *, void *, void *));
+void iyattach __P((struct device *, struct device *, void *));
+
+static u_int16_t eepromread __P((int, int));
+
+struct cfattach iy_ca = {
+       sizeof(struct iy_softc), iyprobe, iyattach
+};
+
+struct cfdriver iy_cd = {
+       NULL, "iy", DV_IFNET
+};
+
+static u_int8_t eepro_irqmap[] = EEPP_INTMAP;
+static u_int8_t eepro_revirqmap[] = EEPP_RINTMAP;
+
+int
+iyprobe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct iy_softc *sc = match;
+       struct isa_attach_args *ia = aux;
+
+       u_int16_t eaddr[8];
+       int iobase;
+       int i;
+
+       u_int16_t checksum = 0;
+       u_int16_t eepromtmp;
+       u_int8_t c, d;
+
+       
+       iobase = ia->ia_iobase;
+
+       if (iobase == -1)
+               return 0;
+
+       /* try to find the round robin sig: */
+
+       /* check here for addresses already given to other devices */
+
+       c = inb(iobase + ID_REG);
+       if (c & ID_REG_MASK != ID_REG_SIG)
+               return 0;
+
+       d = inb(iobase + ID_REG);
+       if (d & ID_REG_MASK != ID_REG_SIG)
+               return 0;
+
+       if (((d-c) & R_ROBIN_BITS) != 0x40)
+               return 0;
+               
+       d = inb(iobase + ID_REG);
+       if (d & ID_REG_MASK != ID_REG_SIG)
+               return 0;
+
+       if (((d-c) & R_ROBIN_BITS) != 0x80)
+               return 0;
+               
+       d = inb(iobase + ID_REG);
+       if (d & ID_REG_MASK != ID_REG_SIG)
+               return 0;
+
+       if (((d-c) & R_ROBIN_BITS) != 0xC0)
+               return 0;
+               
+       d = inb(iobase + ID_REG);
+       if (d & ID_REG_MASK != ID_REG_SIG)
+               return 0;
+
+       if (((d-c) & R_ROBIN_BITS) != 0x00)
+               return 0;
+               
+#ifdef IYDEBUG
+               printf("eepro_probe verified working ID reg.\n");
+#endif
+       
+       for (i=0; i<64; ++i) {
+               eepromtmp = eepromread(iobase, i);
+               checksum += eepromtmp;
+               if (i<(sizeof(eaddr)/sizeof(*eaddr)))
+                       eaddr[i] = eepromtmp;
+       }
+       if (checksum != EEPP_CHKSUM)
+               printf("wrong EEPROM checksum 0x%x should be 0x%x\n",
+                   checksum, EEPP_CHKSUM);
+               
+       
+       if ((eaddr[EEPPEther0] != eepromread(iobase, EEPPEther0a)) &&
+           (eaddr[EEPPEther1] != eepromread(iobase, EEPPEther1a)) &&
+           (eaddr[EEPPEther2] != eepromread(iobase, EEPPEther2a)))
+               printf("EEPROM Ethernet address differs from copy\n");
+       
+        sc->sc_arpcom.ac_enaddr[1] = eaddr[EEPPEther0] & 0xFF;
+        sc->sc_arpcom.ac_enaddr[0] = eaddr[EEPPEther0] >> 8;
+        sc->sc_arpcom.ac_enaddr[3] = eaddr[EEPPEther1] & 0xFF;
+        sc->sc_arpcom.ac_enaddr[2] = eaddr[EEPPEther1] >> 8;
+        sc->sc_arpcom.ac_enaddr[5] = eaddr[EEPPEther2] & 0xFF;
+        sc->sc_arpcom.ac_enaddr[4] = eaddr[EEPPEther2] >> 8;
+       
+       if (ia->ia_irq == IRQUNK)
+               ia->ia_irq = eepro_irqmap[eaddr[EEPPW1] & EEPP_Int];
+
+       if (ia->ia_irq >= sizeof(eepro_revirqmap))
+               return 0;
+
+       if ((sc->mappedirq = eepro_revirqmap[ia->ia_irq]) == -1)
+               return 0;
+
+       sc->hard_vers = eaddr[EEPW6] & EEPP_BoardRev;
+
+       /* now lets reset the chip */
+       
+       outb(iobase + COMMAND_REG, RESET_CMD);
+       delay(200);
+       
+               ia->ia_iobase = iobase;
+               ia->ia_iosize = 16;
+       return 1;               /* found */
+}
+
+void
+iyattach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct iy_softc *sc = (void *)self;
+       struct isa_attach_args *ia = aux;
+       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+
+       bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+       ifp->if_softc = sc;
+       ifp->if_start = iystart;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
+                                       /* XXX todo: | IFF_MULTICAST */
+       sc->sc_iobase = ia->ia_iobase;
+
+       iyprobemem(sc);
+
+       ifp->if_ioctl = iyioctl;
+       ifp->if_watchdog = iywatchdog;
+
+       /* Attach the interface. */
+       if_attach(ifp);
+       ether_ifattach(ifp);
+       printf(": address %s, chip rev. %d, %d kB SRAM\n",
+           ether_sprintf(sc->sc_arpcom.ac_enaddr),
+           sc->hard_vers, sc->sram/1024);
+#if NBPFILTER > 0
+       bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,
+           sizeof(struct ether_header));
+#endif
+
+       sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, 
+           IPL_NET, iyintr, sc);
+}
+
+void
+iystop(sc)
+struct iy_softc *sc;
+{
+       int iobase;
+#ifdef IYDEBUG
+       u_int p, v;
+#endif
+
+       iobase = sc->sc_iobase;
+       
+       outb(iobase + COMMAND_REG, RCV_DISABLE_CMD);
+
+       outb(iobase + INT_MASK_REG, ALL_INTS);
+       outb(iobase + STATUS_REG, ALL_INTS);
+
+       outb(iobase + COMMAND_REG, RESET_CMD);
+       delay(200);
+#ifdef IYDEBUG 
+       printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n", 
+                   sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
+       p = sc->tx_last;
+       if (!p)
+               p = sc->tx_start;
+       do {
+               outw(iobase + HOST_ADDR_REG, p);
+               v = inw(iobase + MEM_PORT_REG);
+               printf("0x%04x: %b ", p, v, "\020\006Ab\010Dn");
+               v = inw(iobase + MEM_PORT_REG);
+               printf("0x%b", v, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL");
+               p = inw(iobase + MEM_PORT_REG);
+               printf(" 0x%04x", p);
+               v = inw(iobase + MEM_PORT_REG);
+               printf(" 0x%b\n", v, "\020\020Ch");
+               
+       } while (v & 0x8000);
+#endif
+       sc->tx_start = sc->tx_end = sc->rx_size;
+       sc->tx_last = 0;
+       sc->sc_arpcom.ac_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
+
+       iymbufempty((void *)sc);
+}
+
+void
+iyreset(sc)
+struct iy_softc *sc;
+{
+       int s;
+       s = splimp();
+       iystop(sc);
+       iyinit(sc);
+       splx(s);
+}
+
+void
+iyinit(sc)
+struct iy_softc *sc;
+{
+       int i;
+       unsigned temp;
+       struct ifnet *ifp;
+       int iobase;
+
+       ifp = &sc->sc_arpcom.ac_if;
+#ifdef IYDEBUG
+       printf("ifp is %p\n", ifp);
+#endif
+       iobase = sc->sc_iobase;
+
+       outb(iobase, BANK_SEL(2));
+
+       temp = inb(iobase + EEPROM_REG);
+       if (temp & 0x10)
+               outb(iobase + EEPROM_REG, temp & ~0x10);
+       
+       for (i=0; i<6; ++i) {
+               outb(iobase + I_ADD(i), sc->sc_arpcom.ac_enaddr[i]);
+       }
+
+       temp = inb(iobase + REG1);
+       outb(iobase + REG1, temp | XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP |
+           RCV_DISCARD_BAD);
+       
+       temp = inb(iobase + RECV_MODES_REG);
+       outb(iobase + RECV_MODES_REG, temp | MATCH_BRDCST);
+#ifdef IYDEBUG
+       printf("%s: RECV_MODES were %b set to %b\n",
+           sc->sc_dev.dv_xname, 
+           temp, "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA",
+           temp|MATCH_BRDCST,
+           "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA");
+#endif
+
+
+       DELAY(500000); /* for the hardware to test for the connector */
+
+       temp = inb(iobase + MEDIA_SELECT);
+#ifdef IYDEBUG
+       printf("%s: media select was 0x%b", sc->sc_dev.dv_xname,
+           temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC");
+#endif
+       temp = (temp & TEST_MODE_MASK) /* | BNC_BIT XXX*/;
+       outb(iobase + MEDIA_SELECT, temp);
+#ifdef IYDEBUG
+       printf("changed to 0x%b\n", 
+           temp, "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC");
+#endif
+
+       outb(iobase, BANK_SEL(1));
+
+       temp = inb(iobase + INT_NO_REG);
+       outb(iobase + INT_NO_REG, (temp & 0xf8) | sc->mappedirq);
+
+#ifdef IYDEBUG
+       printf("%s: int no was %b\n", sc->sc_dev.dv_xname,
+           temp, "\020\4bad_irq\010flash/boot present");
+       temp = inb(iobase + INT_NO_REG);
+       printf("%s: int no now 0x%02x\n", sc->sc_dev.dv_xname,
+           temp, "\020\4BAD IRQ\010flash/boot present");
+#endif
+
+
+       outb(iobase + RCV_LOWER_LIMIT_REG, 0);
+       outb(iobase + RCV_UPPER_LIMIT_REG, (sc->rx_size - 2) >> 8);
+       outb(iobase + XMT_LOWER_LIMIT_REG, sc->rx_size >> 8);
+       outb(iobase + XMT_UPPER_LIMIT_REG, sc->sram >> 8);
+
+       temp = inb(iobase + REG1);
+#ifdef IYDEBUG
+       printf("%s: HW access is %b\n", sc->sc_dev.dv_xname, 
+           temp, "\020\2WORD_WIDTH\010INT_ENABLE");
+#endif
+       outb(iobase + REG1, temp | INT_ENABLE); /* XXX what about WORD_WIDTH? */
+
+#ifdef IYDEBUG
+       temp = inb(iobase + REG1);
+       printf("%s: HW access is %b\n", sc->sc_dev.dv_xname, 
+           temp, "\020\2WORD_WIDTH\010INT_ENABLE");
+#endif
+
+       outb(iobase, BANK_SEL(0));
+
+       outb(iobase + INT_MASK_REG, ALL_INTS & ~(RX_BIT|TX_BIT));
+       outb(iobase + STATUS_REG, ALL_INTS); /* clear ints */
+
+       outw(iobase + RCV_START_LOW, 0);
+       outw(iobase + RCV_STOP_LOW,  sc->rx_size - 2);
+       sc->rx_start = 0;
+
+       outb(iobase, SEL_RESET_CMD);
+       DELAY(200);
+
+       outw(iobase + XMT_ADDR_REG, sc->rx_size);
+
+       sc->tx_start = sc->tx_end = sc->rx_size;
+       sc->tx_last = 0;
+
+       outb(iobase, RCV_ENABLE_CMD);
+
+       ifp->if_flags |= IFF_RUNNING;
+       ifp->if_flags &= ~IFF_OACTIVE;
+}
+
+void
+iystart(ifp)
+struct ifnet *ifp;
+{
+       struct iy_softc *sc;
+       int iobase;
+
+       struct mbuf *m0, *m;
+       u_int len, pad, last, end;
+       u_int llen, residual;
+       int avail;
+       caddr_t data;
+       u_int16_t resval, stat;
+
+#ifdef IYDEBUG
+       printf("iystart called\n");
+#endif
+       if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
+                return;
+
+       sc = ifp->if_softc;
+       iobase = sc->sc_iobase;
+
+       while ((m0 = ifp->if_snd.ifq_head) != NULL) {
+#ifdef IYDEBUG
+               printf("%s: trying to write another packet to the hardware\n",
+                   sc->sc_dev.dv_xname);
+#endif
+
+               /* We need to use m->m_pkthdr.len, so require the header */
+               if ((m0->m_flags & M_PKTHDR) == 0)
+                       panic("iystart: no header mbuf");
+
+               len = m0->m_pkthdr.len;
+               pad = len & 1;
+
+#ifdef IYDEBUG
+               printf("%s: length is %d.\n", sc->sc_dev.dv_xname, len);
+#endif
+               if (len < ETHER_MIN_LEN) {
+                       pad = ETHER_MIN_LEN - len;
+               }
+
+               if (len + pad > ETHER_MAX_LEN) {
+                       /* packet is obviously too large: toss it */
+                       ++ifp->if_oerrors;
+                       IF_DEQUEUE(&ifp->if_snd, m0);
+                       m_freem(m0);
+                       continue;
+               }
+
+#if NBPFILTER > 0
+               if (ifp->if_bpf)
+                       bpf_mtap(ifp->if_bpf, m0);
+#endif
+
+               avail = sc->tx_start - sc->tx_end;
+               if (avail <= 0)
+                       avail += sc->tx_size;
+
+#ifdef IYDEBUG
+               printf("%s: avail is %d.\n", sc->sc_dev.dv_xname, avail);
+#endif
+               /* 
+                * we MUST RUN at splnet here  --- 
+                * XXX todo: or even turn off the boards ints ??? hm... 
+                */
+       
+                       /* See if there is room to put another packet in the buffer. */
+       
+               if ((len+pad+2*I595_XMT_HDRLEN) > avail) {
+                       printf("%s: len = %d, avail = %d, setting OACTIVE\n",
+                           sc->sc_dev.dv_xname, len, avail);
+                       ifp->if_flags |= IFF_OACTIVE;
+                       return;
+               }
+       
+               /* we know it fits in the hardware now, so dequeue it */
+               IF_DEQUEUE(&ifp->if_snd, m0);
+               
+               last = sc->tx_end;
+               end = last + pad + len + I595_XMT_HDRLEN; 
+               
+               if (end >= sc->sram) {
+                       if ((sc->sram - last) <= I595_XMT_HDRLEN) {
+                               /* keep header in one piece */
+                               last = sc->rx_size;
+                               end = last + pad + len + I595_XMT_HDRLEN;
+                       } else
+                               end -= sc->tx_size;
+               }
+
+               outw(iobase + HOST_ADDR_REG, last);
+               outw(iobase + MEM_PORT_REG, XMT_CMD);
+               outw(iobase + MEM_PORT_REG, 0);
+               outw(iobase + MEM_PORT_REG, 0);
+               outw(iobase + MEM_PORT_REG, len + pad);
+
+               residual = resval = 0;
+
+               while ((m = m0)!=0) {
+                       data = mtod(m, caddr_t);
+                       llen = m->m_len;
+                       if (residual) {
+#ifdef IYDEBUG
+                               printf("%s: merging residual with next mbuf.\n",
+                                   sc->sc_dev.dv_xname);
+#endif
+                               resval |= *data << 8;
+                               outw(iobase + MEM_PORT_REG, resval);
+                               --llen;
+                               ++data;
+                       }
+                       if (llen > 1)
+                               outsw(iobase + MEM_PORT_REG, data, llen>>1);
+                       residual = llen & 1;
+                       if (residual) {
+                               resval = *(data + llen - 1);
+#ifdef IYDEBUG
+                               printf("%s: got odd mbuf to send.\n",
+                                   sc->sc_dev.dv_xname);
+#endif
+                       }
+
+                       MFREE(m, m0);
+               }
+
+               if (residual)
+                       outw(iobase + MEM_PORT_REG, resval);
+
+               pad >>= 1;
+               while (pad-- > 0)
+                       outw(iobase + MEM_PORT_REG, 0);
+                       
+#ifdef IYDEBUG
+               printf("%s: new last = 0x%x, end = 0x%x.\n",
+                   sc->sc_dev.dv_xname, last, end);
+               printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n",
+                   sc->sc_dev.dv_xname, sc->tx_start, sc->tx_end, sc->tx_last);
+#endif
+
+               if (sc->tx_start != sc->tx_end) {
+                       outw(iobase + HOST_ADDR_REG, sc->tx_last + XMT_COUNT);
+                       stat = inw(iobase + MEM_PORT_REG);
+
+                       outw(iobase + HOST_ADDR_REG, sc->tx_last + XMT_CHAIN);
+                       outw(iobase + MEM_PORT_REG, last);
+                       outw(iobase + MEM_PORT_REG, stat | CHAIN);
+#ifdef IYDEBUG
+                       printf("%s: setting 0x%x to 0x%x\n",
+                           sc->sc_dev.dv_xname, sc->tx_last + XMT_COUNT, 
+                           stat | CHAIN);
+#endif
+               }
+               stat = inw(iobase + MEM_PORT_REG); /* dummy read */
+
+               /* XXX todo: enable ints here if disabled */
+               
+               ++ifp->if_opackets;
+
+               if (sc->tx_start == sc->tx_end) {
+                       outw(iobase + XMT_ADDR_REG, last);
+                       outb(iobase, XMT_CMD);
+                       sc->tx_start = last;
+#ifdef IYDEBUG
+                       printf("%s: writing 0x%x to XAR and giving XCMD\n",
+                           sc->sc_dev.dv_xname, last);
+#endif
+               } else {
+                       outb(iobase, RESUME_XMT_CMD);
+#ifdef IYDEBUG
+                       printf("%s: giving RESUME_XCMD\n",
+                           sc->sc_dev.dv_xname);
+#endif
+               }
+               sc->tx_last = last;
+               sc->tx_end = end;
+       }
+}
+
+
+static __inline void
+eepromwritebit(eio, what) 
+       int eio, what;
+{
+       outb(eio, what);
+       delay(1);
+       outb(eio, what|EESK);
+       delay(1);
+       outb(eio, what);
+       delay(1);
+}
+
+static __inline int
+eepromreadbit(eio) 
+       int eio;
+{
+       int b; 
+
+       outb(eio, EECS|EESK); 
+       delay(1);
+       b = inb(eio);
+       outb(eio, EECS);
+       delay(1);
+
+       return ((b & EEDO) != 0);
+}
+
+static u_int16_t
+eepromread(io, offset)
+       int io, offset;
+{
+       volatile int i;
+       volatile int j;
+       volatile u_int16_t readval;
+       int eio = io+EEPROM_REG;
+
+       outb(io, BANK_SEL(2));
+       delay(1);
+       outb(io, EECS);
+       delay(1);
+       
+       eepromwritebit(eio, EECS|EEDI);
+       eepromwritebit(eio, EECS|EEDI);
+       eepromwritebit(eio, EECS);
+       
+       for (j=5; j>=0; --j) {
+               if ((offset>>j) & 1) 
+                       eepromwritebit(eio, EECS|EEDI);
+               else
+                       eepromwritebit(eio, EECS);
+       }
+
+       for (readval=0, i=0; i<16; ++i) {
+               readval<<=1;
+               readval |= eepromreadbit(eio);
+       }
+
+       outb(eio, 0|EESK);
+       delay(1);
+       outb(eio, 0);
+
+       outb(eio, BANK_SEL(0));
+
+       return readval;
+}
+
+/*
+ * Device timeout/watchdog routine.  Entered if the device neglects to generate
+ * an interrupt after a transmit has been started on it.
+ */
+void
+iywatchdog(ifp)
+       struct ifnet *ifp
+{
+       struct iy_softc *sc = ifp->if_softc;
+
+       log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
+       ++sc->sc_arpcom.ac_if.if_oerrors;
+       iyreset(sc);
+}
+
+/*
+ * What to do upon receipt of an interrupt.
+ */
+int
+iyintr(arg)
+       void *arg;
+{
+       struct iy_softc *sc = arg;
+       int iobase;
+       register u_short status;
+
+       iobase = sc->sc_iobase;
+       status = inb(iobase + STATUS_REG);
+#ifdef IYDEBUG
+       if (status & ALL_INTS) {
+               printf("%s: got interupt %b", sc->sc_dev.dv_xname, status,
+                   "\020\1RX_STP\2RX\3TX\4EXEC");
+               if (status & EXEC_INT)
+                       printf(" event %b\n", inb(iobase),
+                           "\020\6ABORT");
+               else
+                       printf("\n");
+       }
+#endif
+       if ((status & (RX_INT | TX_INT) == 0))
+               return 0;
+
+       if (status & RX_INT) {
+               iy_intr_rx(sc);
+               outb(iobase + STATUS_REG, RX_INT);
+       } else if (status & TX_INT) {
+               iy_intr_tx(sc);
+               outb(iobase + STATUS_REG, TX_INT);
+       }
+       return 1;
+}
+
+void
+iyget(sc, iobase, rxlen)
+struct iy_softc *sc;
+int iobase, rxlen;
+{
+       struct mbuf *m, *top, **mp;
+       struct ether_header *eh;
+       struct ifnet *ifp;
+       int len;
+
+       ifp = &sc->sc_arpcom.ac_if;
+
+       m = sc->mb[sc->next_mb];
+       sc->mb[sc->next_mb] = 0;
+       if (m == 0) {
+               MGETHDR(m, M_DONTWAIT, MT_DATA);
+               if (m == 0)
+                       goto dropped;
+       } else {
+               if (sc->last_mb == sc->next_mb)
+                       timeout(iymbuffill, sc, 1);
+               sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
+               m->m_data = m->m_pktdat;
+               m->m_flags = M_PKTHDR;
+       }
+       m->m_pkthdr.rcvif = ifp;
+       m->m_pkthdr.len = rxlen;
+       len = MHLEN;
+       top = 0;
+       mp = &top;
+
+       while (rxlen > 0) {
+               if (top) {
+                       m = sc->mb[sc->next_mb];
+                       sc->mb[sc->next_mb] = 0;
+                       if (m == 0) {
+                               MGET(m, M_DONTWAIT, MT_DATA);
+                               if (m == 0) {
+                                       m_freem(top);
+                                       goto dropped;
+                               }
+                       } else {
+                               sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
+                       }
+                       len = MLEN;
+               }
+               if (rxlen >= MINCLSIZE) {
+                       MCLGET(m, M_DONTWAIT);
+                       if (m->m_flags & M_EXT)
+                               len = MCLBYTES;
+               }
+               len = min(rxlen, len);
+               if (len > 1) {
+                       len &= ~1;
+                       insw(iobase + MEM_PORT_REG, mtod(m, caddr_t), len/2);
+               } else {
+#ifdef IYDEBUG
+                       printf("%s: received odd mbuf\n", sc->sc_dev.dv_xname);
+#endif
+                       *(mtod(m, caddr_t)) = inw(iobase + MEM_PORT_REG);
+               }
+               m->m_len = len;
+               rxlen -= len;
+               *mp = m;
+               mp = &m->m_next;
+       }
+       /* XXX receive the top here */  
+       ++ifp->if_ipackets;
+       
+       eh = mtod(top, struct ether_header *);
+
+#if NBPFILTER > 0
+       if (ifp->if_bpf) {
+               bpf_mtap(ifp->if_bpf, top);
+               if ((ifp->if_flags & IFF_PROMISC) &&
+                   (eh->ether_dhost[0] & 1) == 0 &&
+                   bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, 
+                               sizeof(eh->ether_dhost)) != 0) {
+                       m_freem(top);
+                       return;
+               }
+       }
+#endif
+       m_adj(top, sizeof(struct ether_header));
+       ether_input(ifp, eh, top);
+       return;
+
+dropped:
+       ++ifp->if_ierrors;
+       return;
+}
+void
+iy_intr_rx(sc)
+struct iy_softc *sc;
+{
+       struct ifnet *ifp;
+       int iobase;
+       u_int rxadrs, rxevnt, rxstatus, rxnext, rxlen;
+
+       iobase = sc->sc_iobase;
+       ifp = &sc->sc_arpcom.ac_if;
+
+       rxadrs = sc->rx_start;
+       outw(iobase + HOST_ADDR_REG, rxadrs);
+       rxevnt = inw(iobase + MEM_PORT_REG);
+       rxnext = 0;
+       
+       while (rxevnt == RCV_DONE) {
+               rxstatus = inw(iobase + MEM_PORT_REG);
+               rxnext = inw(iobase + MEM_PORT_REG);
+               rxlen = inw(iobase + MEM_PORT_REG);
+#ifdef IYDEBUG
+               printf("%s: pck at 0x%04x stat %b next 0x%x len 0x%x\n",
+                   sc->sc_dev.dv_xname, rxadrs, rxstatus,
+                   "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR"
+                   "\014CRCERR\015LENERR\016RCVOK\020TYP",
+                   rxnext, rxlen);
+#endif
+               iyget(sc, iobase, rxlen);
+
+               /* move stop address */
+               outw(iobase + RCV_STOP_LOW,
+                           rxnext == 0 ? sc->rx_size - 2 : rxnext - 2);
+
+               outw(iobase + HOST_ADDR_REG, rxnext);
+               rxadrs = rxnext;
+               rxevnt = inw(iobase + MEM_PORT_REG);
+       }
+       sc->rx_start = rxnext;
+}
+
+void
+iy_intr_tx(sc)
+struct iy_softc *sc;
+{
+       int iobase;
+       struct ifnet *ifp;
+       u_int txstatus, txstat2, txlen, txnext;
+
+       ifp = &sc->sc_arpcom.ac_if;
+       iobase = sc->sc_iobase;
+       
+       while (sc->tx_start != sc->tx_end) {
+               outw(iobase + HOST_ADDR_REG, sc->tx_start);
+               txstatus = inw(iobase + MEM_PORT_REG);
+               if ((txstatus & (TX_DONE|CMD_MASK)) != (TX_DONE|XMT_CMD))
+                       break;
+
+               txstat2 = inw(iobase + MEM_PORT_REG);
+               txnext = inw(iobase + MEM_PORT_REG);
+               txlen = inw(iobase + MEM_PORT_REG);
+#ifdef IYDEBUG
+               printf("txstat 0x%x stat2 0x%b next 0x%x len 0x%x\n",
+                   txstatus, txstat2, "\020\6MAX_COL\7HRT_BEAT\010TX_DEF"
+                   "\011UND_RUN\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL",
+                       txnext, txlen);
+#endif
+               if (txlen & CHAIN)
+                       sc->tx_start = txnext;
+               else
+                       sc->tx_start = sc->tx_end;
+               ifp->if_flags &= ~IFF_OACTIVE;
+               
+               if ((txstat2 & 0x2000) == 0)
+                       ++ifp->if_oerrors;
+               if (txstat2 & 0x000f)
+                       ifp->if_oerrors += txstat2 & 0x000f;
+       }
+       ifp->if_flags &= ~IFF_OACTIVE;
+}
+
+#if 0
+/*
+ * Compare two Ether/802 addresses for equality, inlined and unrolled for
+ * speed.  I'd love to have an inline assembler version of this...
+ */
+static inline int
+ether_equal(one, two)
+       u_char *one, *two;
+{
+
+       if (one[0] != two[0] || one[1] != two[1] || one[2] != two[2] ||
+           one[3] != two[3] || one[4] != two[4] || one[5] != two[5])
+               return 0;
+       return 1;
+}
+
+/*
+ * Check for a valid address.  to_bpf is filled in with one of the following:
+ *   0 -> BPF doesn't get this packet
+ *   1 -> BPF does get this packet
+ *   2 -> BPF does get this packet, but we don't
+ * Return value is true if the packet is for us, and false otherwise.
+ *
+ * This routine is a mess, but it's also critical that it be as fast
+ * as possible.  It could be made cleaner if we can assume that the
+ * only client which will fiddle with IFF_PROMISC is BPF.  This is
+ * probably a good assumption, but we do not make it here.  (Yet.)
+ */
+static inline int
+check_eh(sc, eh, to_bpf)
+       struct iy_softc *sc;
+       struct ether_header *eh;
+       int *to_bpf;
+{
+       int i;
+
+       switch (sc->promisc) {
+       case IFF_ALLMULTI:
+               /*
+                * Receiving all multicasts, but no unicasts except those
+                * destined for us.
+                */
+#if NBPFILTER > 0
+               *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0); /* BPF gets this packet if anybody cares */
+#endif
+               if (eh->ether_dhost[0] & 1)
+                       return 1;
+               if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
+                       return 1;
+               return 0;
+
+       case IFF_PROMISC:
+               /*
+                * Receiving all packets.  These need to be passed on to BPF.
+                */
+#if NBPFILTER > 0
+               *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
+#endif
+               /* If for us, accept and hand up to BPF */
+               if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
+                       return 1;
+
+#if NBPFILTER > 0
+               if (*to_bpf)
+                       *to_bpf = 2; /* we don't need to see it */
+#endif
+
+               /*
+                * Not a multicast, so BPF wants to see it but we don't.
+                */
+               if (!(eh->ether_dhost[0] & 1))
+                       return 1;
+
+               /*
+                * If it's one of our multicast groups, accept it and pass it
+                * up.
+                */
+               for (i = 0; i < sc->mcast_count; i++) {
+                       if (ether_equal(eh->ether_dhost, (u_char *)&sc->mcast_addrs[i])) {
+#if NBPFILTER > 0
+                               if (*to_bpf)
+                                       *to_bpf = 1;
+#endif
+                               return 1;
+                       }
+               }
+               return 1;
+
+       case IFF_ALLMULTI | IFF_PROMISC:
+               /*
+                * Acting as a multicast router, and BPF running at the same
+                * time.  Whew!  (Hope this is a fast machine...)
+                */
+#if NBPFILTER > 0
+               *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
+#endif
+               /* We want to see multicasts. */
+               if (eh->ether_dhost[0] & 1)
+                       return 1;
+
+               /* We want to see our own packets */
+               if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
+                       return 1;
+
+               /* Anything else goes to BPF but nothing else. */
+#if NBPFILTER > 0
+               if (*to_bpf)
+                       *to_bpf = 2;
+#endif
+               return 1;
+
+       case 0:
+               /*
+                * Only accept unicast packets destined for us, or multicasts
+                * for groups that we belong to.  For now, we assume that the
+                * '586 will only return packets that we asked it for.  This
+                * isn't strictly true (it uses hashing for the multicast
+                * filter), but it will do in this case, and we want to get out
+                * of here as quickly as possible.
+                */
+#if NBPFILTER > 0
+               *to_bpf = (sc->sc_arpcom.ac_if.iy_bpf != 0);
+#endif
+               return 1;
+       }
+
+#ifdef DIAGNOSTIC
+       panic("check_eh: impossible");
+#endif
+}
+#endif
+
+int
+iyioctl(ifp, cmd, data)
+       register struct ifnet *ifp;
+       u_long cmd;
+       caddr_t data;
+{
+       struct iy_softc *sc;
+       struct ifaddr *ifa;
+       struct ifreq *ifr;
+       int s, error = 0;
+
+       sc = ifp->if_softc;
+       ifa = (struct ifaddr *)data;
+       ifr = (struct ifreq *)data;
+
+#ifdef IYDEBUG
+       printf("iyioctl called with ifp 0x%p (%s) cmd 0x%x data 0x%p\n", 
+           ifp, ifp->if_xname, cmd, data);
+#endif
+
+       s = splimp();
+
+       switch (cmd) {
+
+       case SIOCSIFADDR:
+               ifp->if_flags |= IFF_UP;
+
+               switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+               case AF_INET:
+                       iyinit(sc);
+                       arp_ifinit(&sc->sc_arpcom, ifa);
+                       break;
+#endif
+#ifdef NS
+               /* XXX - This code is probably wrong. */
+               case AF_NS:
+                   {
+                       struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+
+                       if (ns_nullhost(*ina))
+                               ina->x_host =
+                                   *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
+                       else
+                               bcopy(ina->x_host.c_host,
+                                   sc->sc_arpcom.ac_enaddr,
+                                   sizeof(sc->sc_arpcom.ac_enaddr));
+                       /* Set new address. */
+                       iyinit(sc);
+                       break;
+                   }
+#endif /* NS */
+               default:
+                       iyinit(sc);
+                       break;
+               }
+               break;
+
+       case SIOCSIFFLAGS:
+               sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
+               if ((ifp->if_flags & IFF_UP) == 0 &&
+                   (ifp->if_flags & IFF_RUNNING) != 0) {
+                       /*
+                        * If interface is marked down and it is running, then
+                        * stop it.
+                        */
+                       iystop(sc);
+                       ifp->if_flags &= ~IFF_RUNNING;
+               } else if ((ifp->if_flags & IFF_UP) != 0 &&
+                          (ifp->if_flags & IFF_RUNNING) == 0) {
+                       /*
+                        * If interface is marked up and it is stopped, then
+                        * start it.
+                        */
+                       iyinit(sc);
+               } else {
+                       /*
+                        * Reset the interface to pick up changes in any other
+                        * flags that affect hardware registers.
+                        */
+                       iystop(sc);
+                       iyinit(sc);
+               }
+#ifdef IYDEBUGX
+               if (ifp->if_flags & IFF_DEBUG)
+                       sc->sc_debug = IFY_ALL;
+               else
+                       sc->sc_debug = 0;
+#endif
+               break;
+
+#if 0 /* XXX */
+       case SIOCADDMULTI:
+       case SIOCDELMULTI:
+               error = (cmd == SIOCADDMULTI) ?
+                   ether_addmulti(ifr, &sc->sc_arpcom):
+                   ether_delmulti(ifr, &sc->sc_arpcom);
+
+               if (error == ENETRESET) {
+                       /*
+                        * Multicast list has changed; set the hardware filter
+                        * accordingly.
+                        */
+                       iy_mc_reset(sc); /* XXX */
+                       error = 0;
+               }
+               break;
+#endif
+       default:
+               error = EINVAL;
+       }
+       splx(s);
+       return error;
+}
+
+#if 0
+static void
+iy_mc_reset(sc)
+       struct iy_softc *sc;
+{
+       struct ether_multi *enm;
+       struct ether_multistep step;
+
+       /*
+        * Step through the list of addresses.
+        */
+       sc->mcast_count = 0;
+       ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
+       while (enm) {
+               if (sc->mcast_count >= MAXMCAST ||
+                   bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
+                       sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
+                       iyioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, (void *)0);
+                       goto setflag;
+               }
+
+               bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
+               sc->mcast_count++;
+               ETHER_NEXT_MULTI(step, enm);
+       }
+       setflag:
+       sc->want_mcsetup = 1;
+}
+
+#ifdef IYDEBUG
+void
+print_rbd(rbd)
+       volatile struct ie_recv_buf_desc *rbd;
+{
+
+       printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
+           "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
+           rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
+           rbd->mbz);
+}
+#endif
+#endif
+
+void
+iymbuffill(arg)
+       void *arg;
+{
+       struct iy_softc *sc = (struct iy_softc *)arg;
+       int s, i;
+
+       s = splimp();
+       i = sc->last_mb;
+       do {
+               if (sc->mb[i] == NULL)
+                       MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
+               if (sc->mb[i] == NULL)
+                       break;
+               i = (i + 1) % MAX_MBS;
+       } while (i != sc->next_mb);
+       sc->last_mb = i;
+       /* If the queue was not filled, try again. */
+       if (sc->last_mb != sc->next_mb)
+               timeout(iymbuffill, sc, 1);
+       splx(s); 
+}
+
+
+void
+iymbufempty(arg)
+       void *arg;
+{
+       struct iy_softc *sc = (struct iy_softc *)arg;
+       int s, i;
+
+       s = splimp();
+       for (i = 0; i<MAX_MBS; i++) {
+               if (sc->mb[i]) {
+                       m_freem(sc->mb[i]);
+                       sc->mb[i] = NULL;
+               }
+       }
+       sc->last_mb = sc->next_mb = 0;
+       untimeout(iymbuffill, sc);
+       splx(s);
+}
+
+void
+iyprobemem(sc)
+       struct iy_softc *sc;
+{
+       int iobase;
+       int testing;
+
+       iobase = sc->sc_iobase;
+
+       outw(iobase + HOST_ADDR_REG, 4096-2);
+       outw(iobase + MEM_PORT_REG, 0);
+
+       for (testing=65536; testing >= 4096; testing >>= 1) {
+               outw(iobase + HOST_ADDR_REG, testing-2);
+               outw(iobase + MEM_PORT_REG, 0xdead);
+               outw(iobase + HOST_ADDR_REG, testing-2);
+               if (inw(iobase + MEM_PORT_REG) != 0xdead) {
+#ifdef IYMEMDEBUG
+                       printf("%s: Didn't keep 0xdead at 0x%x\n",
+                           sc->sc_dev.dv_xname, testing-2);
+#endif
+                       continue;
+               }
+
+               outw(iobase + HOST_ADDR_REG, testing-2);
+               outw(iobase + MEM_PORT_REG, 0xbeef);
+               outw(iobase + HOST_ADDR_REG, testing-2);
+               if (inw(iobase + MEM_PORT_REG) != 0xbeef) {
+#ifdef IYMEMDEBUG
+                       printf("%s: Didn't keep 0xbeef at 0x%x\n",
+                           sc->sc_dev.dv_xname, testing-2);
+#endif
+                       continue;
+               }
+
+               outw(iobase + HOST_ADDR_REG, 0);
+               outw(iobase + MEM_PORT_REG, 0);
+               outw(iobase + HOST_ADDR_REG, testing >> 1);
+               outw(iobase + MEM_PORT_REG, testing >> 1);
+               outw(iobase + HOST_ADDR_REG, 0);
+               if (inw(iobase + MEM_PORT_REG) == (testing >> 1)) {
+#ifdef IYMEMDEBUG
+                       printf("%s: 0x%x alias of 0x0\n",
+                           sc->sc_dev.dv_xname, testing >> 1);
+#endif
+                       continue;
+               }
+
+               break;
+       }
+
+       sc->sram = testing;
+
+       switch(testing) {
+               case 65536:
+                       /* 4 NFS packets + overhead RX, 2 NFS + overhead TX  */
+                       sc->rx_size = 44*1024;
+                       break;
+
+               case 32768:
+                       /* 2 NFS packets + overhead RX, 1 NFS + overhead TX  */
+                       sc->rx_size = 22*1024;
+                       break;
+
+               case 16384:
+                       /* 1 NFS packet + overhead RX, 4 big packets TX */
+                       sc->rx_size = 10*1024;
+                       break;
+               default:        
+                       sc->rx_size = testing/2;
+                       break;
+       }
+       sc->tx_size = testing - sc->rx_size;
+}
index bc7a2e6..e69de29 100644 (file)
@@ -1,463 +0,0 @@
-/*    $OpenBSD: if_le.c,v 1.9 1996/05/02 13:51:53 deraadt Exp $       */
-/*     $NetBSD: if_le.c,v 1.43 1996/04/22 02:53:28 christos Exp $      */
-
-/*-
- * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
- * 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
- */
-
-#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 <net/if.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#endif
-
-#include <vm/vm.h>
-
-#include <machine/cpu.h>
-#include <machine/pio.h>
-
-#include "isa.h"
-#include "pci.h"
-
-#if NISA > 0
-#include <dev/isa/isareg.h>
-#include <dev/isa/isavar.h>
-#include <dev/isa/isadmavar.h>
-#include <i386/isa/isa_machdep.h>
-#endif
-
-#if NPCI > 0
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-#endif
-
-#include <dev/isa/if_levar.h>
-#include <dev/ic/am7990reg.h>
-#define LE_NEED_BUF_CONTIG
-#include <dev/ic/am7990var.h>
-
-char *card_type[] = {"unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA", "PCnet-PCI"};
-
-#define        LE_SOFTC(unit)  le_cd.cd_devs[unit]
-#define        LE_DELAY(x)     delay(x)
-
-int leprobe __P((struct device *, void *, void *));
-int depca_probe __P((struct le_softc *, struct isa_attach_args *));
-int ne2100_probe __P((struct le_softc *, struct isa_attach_args *));
-int bicc_probe __P((struct le_softc *, struct isa_attach_args *));
-int lance_probe __P((struct le_softc *));
-void leattach __P((struct device *, struct device *, void *));
-int leintr __P((void *));
-int leintredge __P((void *));
-void leshutdown __P((void *));
-
-/* XXX the following two structs should be different. */
-struct cfattach le_isa_ca = {
-       sizeof(struct le_softc), leprobe, leattach
-};
-
-struct cfattach le_pci_ca = {
-       sizeof(struct le_softc), leprobe, leattach
-};
-
-struct cfdriver le_cd = {
-       NULL, "le", DV_IFNET
-};
-
-integrate void
-lehwinit(sc)
-       struct le_softc *sc;
-{
-}
-
-integrate void
-lewrcsr(sc, port, val)
-       struct le_softc *sc;
-       u_int16_t port, val;
-{
-
-       outw(sc->sc_rap, port);
-       outw(sc->sc_rdp, val);
-}
-
-integrate u_int16_t
-lerdcsr(sc, port)
-       struct le_softc *sc;
-       u_int16_t port;
-{
-       u_int16_t val;
-
-       outw(sc->sc_rap, port);
-       val = inw(sc->sc_rdp);
-       return (val);
-}
-
-int
-leprobe(parent, match, aux)
-       struct device *parent;
-       void *match, *aux;
-{
-       struct le_softc *sc = match;
-       extern struct cfdriver isa_cd, pci_cd;
-
-#if NISA > 0
-       if (parent->dv_cfdata->cf_driver == &isa_cd) {
-               struct isa_attach_args *ia = aux;
-
-               if (bicc_probe(sc, ia))
-                       return (1);
-               if (ne2100_probe(sc, ia))
-                       return (1);
-               if (depca_probe(sc, ia))
-                       return (1);
-       }
-#endif
-
-#if NPCI > 0
-       if (parent->dv_cfdata->cf_driver == &pci_cd) {
-               struct pci_attach_args *pa = aux;
-
-               if (pa->pa_id == 0x20001022)
-                       return (1);
-       }
-#endif
-
-       return (0);
-}
-
-#if NISA > 0
-int
-depca_probe(sc, ia)
-       struct le_softc *sc;
-       struct isa_attach_args *ia;
-{
-       int iobase = ia->ia_iobase, port;
-       u_long sum, rom_sum;
-       u_char x;
-       int i;
-
-       sc->sc_rap = iobase + DEPCA_RAP;
-       sc->sc_rdp = iobase + DEPCA_RDP;
-       sc->sc_card = DEPCA;
-
-       if (lance_probe(sc) == 0)
-               return 0;
-
-       outb(iobase + DEPCA_CSR, DEPCA_CSR_DUM);
-
-       /*
-        * Extract the physical MAC address from the ROM.
-        *
-        * The address PROM is 32 bytes wide, and we access it through
-        * a single I/O port.  On each read, it rotates to the next
-        * position.  We find the ethernet address by looking for a
-        * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff,
-        * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the
-        * ethernet address and a checksum).
-        *
-        * It appears that the PROM can be at one of two locations, so
-        * we just try both.
-        */
-       port = iobase + DEPCA_ADP;
-       for (i = 0; i < 32; i++)
-               if (inb(port) == 0xff && inb(port) == 0x00 &&
-                   inb(port) == 0x55 && inb(port) == 0xaa &&
-                   inb(port) == 0xff && inb(port) == 0x00 &&
-                   inb(port) == 0x55 && inb(port) == 0xaa)
-                       goto found;
-       port = iobase + DEPCA_ADP + 1;
-       for (i = 0; i < 32; i++)
-               if (inb(port) == 0xff && inb(port) == 0x00 &&
-                   inb(port) == 0x55 && inb(port) == 0xaa &&
-                   inb(port) == 0xff && inb(port) == 0x00 &&
-                   inb(port) == 0x55 && inb(port) == 0xaa)
-                       goto found;
-       printf("%s: address not found\n", sc->sc_dev.dv_xname);
-       return 0;
-
-found:
-       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
-               sc->sc_arpcom.ac_enaddr[i] = inb(port);
-
-#if 0
-       sum =
-           (sc->sc_arpcom.ac_enaddr[0] <<  2) +
-           (sc->sc_arpcom.ac_enaddr[1] << 10) +
-           (sc->sc_arpcom.ac_enaddr[2] <<  1) +
-           (sc->sc_arpcom.ac_enaddr[3] <<  9) +
-           (sc->sc_arpcom.ac_enaddr[4] <<  0) +
-           (sc->sc_arpcom.ac_enaddr[5] <<  8);
-       sum = (sum & 0xffff) + (sum >> 16);
-       sum = (sum & 0xffff) + (sum >> 16);
-
-       rom_sum = inb(port);
-       rom_sum |= inb(port) << 8;
-
-       if (sum != rom_sum) {
-               printf("%s: checksum mismatch; calculated %04x != read %04x",
-                   sc->sc_dev.dv_xname, sum, rom_sum);
-               return 0;
-       }
-#endif
-
-       outb(iobase + DEPCA_CSR, DEPCA_CSR_NORMAL);
-
-       ia->ia_iosize = 16;
-       ia->ia_drq = DRQUNK;
-       return 1;
-}
-
-int
-ne2100_probe(sc, ia)
-       struct le_softc *sc;
-       struct isa_attach_args *ia;
-{
-       int iobase = ia->ia_iobase;
-       int i;
-
-       sc->sc_rap = iobase + NE2100_RAP;
-       sc->sc_rdp = iobase + NE2100_RDP;
-       sc->sc_card = NE2100;
-
-       if (lance_probe(sc) == 0)
-               return 0;
-
-       /*
-        * Extract the physical MAC address from the ROM.
-        */
-       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
-               sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i);
-
-       ia->ia_iosize = 24;
-       return 1;
-}
-
-int
-bicc_probe(sc, ia)
-       struct le_softc *sc;
-       struct isa_attach_args *ia;
-{
-       int iobase = ia->ia_iobase;
-       int i;
-
-       sc->sc_rap = iobase + BICC_RAP;
-       sc->sc_rdp = iobase + BICC_RDP;
-       sc->sc_card = BICC;
-
-       if (lance_probe(sc) == 0)
-               return 0;
-
-       /*
-        * Extract the physical MAC address from the ROM.
-        */
-       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
-               sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i * 2);
-
-       ia->ia_iosize = 16;
-       return 1;
-}
-
-/*
- * Determine which chip is present on the card.
- */
-int
-lance_probe(sc)
-       struct le_softc *sc;
-{
-
-       /* Stop the LANCE chip and put it in a known state. */
-       lewrcsr(sc, LE_CSR0, LE_C0_STOP);
-       LE_DELAY(100);
-
-       if (lerdcsr(sc, LE_CSR0) != LE_C0_STOP)
-               return 0;
-
-       lewrcsr(sc, LE_CSR3, sc->sc_conf3);
-       return 1;
-}
-#endif
-
-void
-leattach(parent, self, aux)
-       struct device *parent, *self;
-       void *aux;
-{
-       struct le_softc *sc = (void *)self;
-       extern struct cfdriver isa_cd, pci_cd;
-
-#if NPCI > 0
-       if (parent->dv_cfdata->cf_driver == &pci_cd) {
-               struct pci_attach_args *pa = aux;
-               int iobase;
-
-               if (pa->pa_id == 0x20001022) {
-                       int i;
-
-                       if (pci_map_io(pa->pa_tag, 0x10, &iobase))
-                               return;
-
-                       sc->sc_rap = iobase + NE2100_RAP;
-                       sc->sc_rdp = iobase + NE2100_RDP;
-                       sc->sc_card = PCnet_PCI;
-
-                       /*
-                        * Extract the physical MAC address from the ROM.
-                        */
-                       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
-                               sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i);
-               }
-       }
-#endif
-
-#if NISA > 0
-       if (sc->sc_card == DEPCA) {
-               struct isa_attach_args *ia = aux;
-               u_char *mem, val;
-               int i;
-
-               mem = sc->sc_mem = ISA_HOLE_VADDR(ia->ia_maddr);
-
-               val = 0xff;
-               for (;;) {
-                       for (i = 0; i < ia->ia_msize; i++)
-                               mem[i] = val;
-                       for (i = 0; i < ia->ia_msize; i++)
-                               if (mem[i] != val) {
-                                       printf("%s: failed to clear memory\n",
-                                           sc->sc_dev.dv_xname);
-                                       return;
-                               }
-                       if (val == 0x00)
-                               break;
-                       val -= 0x55;
-               }
-
-               sc->sc_conf3 = LE_C3_ACON;
-               sc->sc_addr = 0;
-               sc->sc_memsize = ia->ia_msize;
-       } else
-#endif
-       {
-               sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT);
-               if (sc->sc_mem == 0) {
-                       printf("%s: couldn't allocate memory for card\n",
-                           sc->sc_dev.dv_xname);
-                       return;
-               }
-
-               sc->sc_conf3 = 0;
-               sc->sc_addr = kvtop(sc->sc_mem);
-               sc->sc_memsize = 16384;
-       }
-
-       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_arpcom.ac_if.if_name = le_cd.cd_name;
-       leconfig(sc);
-
-       printf("%s: type %s\n", sc->sc_dev.dv_xname, card_type[sc->sc_card]);
-
-#if NISA > 0
-       if (parent->dv_cfdata->cf_driver == &isa_cd) {
-               struct isa_attach_args *ia = aux;
-
-               if (ia->ia_drq != DRQUNK)
-                       isa_dmacascade(ia->ia_drq);
-
-               sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
-                   IPL_NET, leintredge, sc, sc->sc_dev.dv_xname);
-       }
-#endif
-
-#if NPCI > 0
-       if (parent->dv_cfdata->cf_driver == &pci_cd) {
-               struct pci_attach_args *pa = aux;
-               pcireg_t csr;
-
-               csr = pci_conf_read(pa->pa_bc, pa->pa_tag,
-                   PCI_COMMAND_STATUS_REG);
-               pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
-                   csr | PCI_COMMAND_MASTER_ENABLE);
-
-               sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, leintr, sc);
-       }
-#endif
-
-       sc->sc_sh = shutdownhook_establish(leshutdown, sc);
-}
-
-void
-leshutdown(arg)
-       void *arg;
-{
-       struct le_softc *sc = arg;
-
-       lestop(sc);
-}
-
-#if NISA > 0
-/*
- * Controller interrupt.
- */
-leintredge(arg)
-       void *arg;
-{
-
-       if (leintr(arg) == 0)
-               return (0);
-       for (;;)
-               if (leintr(arg) == 0)
-                       return (1);
-}
-#endif
-
-#include <dev/ic/am7990.c>
diff --git a/sys/dev/isa/if_le_isa.c b/sys/dev/isa/if_le_isa.c
new file mode 100644 (file)
index 0000000..44aaf16
--- /dev/null
@@ -0,0 +1,367 @@
+/*     $NetBSD: if_le_isa.c,v 1.1 1996/05/07 01:50:05 thorpej Exp $    */
+
+/*-
+ * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
+ * 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
+ */
+
+#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 <net/if.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <vm/vm.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
+#include <i386/isa/isa_machdep.h>
+
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+#include <dev/isa/if_levar.h>
+
+static char *card_type[] =
+    { "unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA" };
+
+int le_isa_probe __P((struct device *, void *, void *));
+void le_isa_attach __P((struct device *, struct device *, void *));
+
+struct cfattach le_isa_ca = {
+       sizeof(struct le_softc), le_isa_probe, le_isa_attach
+};
+
+int depca_isa_probe __P((struct le_softc *, struct isa_attach_args *));
+int ne2100_isa_probe __P((struct le_softc *, struct isa_attach_args *));
+int bicc_isa_probe __P((struct le_softc *, struct isa_attach_args *));
+int lance_isa_probe __P((struct am7990_softc *));
+
+int le_isa_intredge __P((void *));
+
+hide void le_isa_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+hide u_int16_t le_isa_rdcsr __P((struct am7990_softc *, u_int16_t));  
+
+hide void
+le_isa_wrcsr(sc, port, val)
+       struct am7990_softc *sc;
+       u_int16_t port, val;
+{
+
+       outw(((struct le_softc *)sc)->sc_rap, port);
+       outw(((struct le_softc *)sc)->sc_rdp, val);
+}
+
+hide u_int16_t
+le_isa_rdcsr(sc, port)
+       struct am7990_softc *sc;
+       u_int16_t port;
+{
+       u_int16_t val;
+
+       outw(((struct le_softc *)sc)->sc_rap, port);
+       val = inw(((struct le_softc *)sc)->sc_rdp);
+       return (val);
+}
+
+int
+le_isa_probe(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct le_softc *lesc = match;
+       struct isa_attach_args *ia = aux;
+
+       if (bicc_isa_probe(lesc, ia))
+               return (1);
+       if (ne2100_isa_probe(lesc, ia))
+               return (1);
+       if (depca_isa_probe(lesc, ia))
+               return (1);
+
+       return (0);
+}
+
+int
+depca_isa_probe(lesc, ia)
+       struct le_softc *lesc;
+       struct isa_attach_args *ia;
+{
+       struct am7990_softc *sc = &lesc->sc_am7990;
+       int iobase = ia->ia_iobase, port;
+       u_long sum, rom_sum;
+       u_char x;
+       int i;
+
+       lesc->sc_rap = iobase + DEPCA_RAP;
+       lesc->sc_rdp = iobase + DEPCA_RDP;
+       lesc->sc_card = DEPCA;
+
+       if (lance_isa_probe(sc) == 0)
+               return 0;
+
+       outb(iobase + DEPCA_CSR, DEPCA_CSR_DUM);
+
+       /*
+        * Extract the physical MAC address from the ROM.
+        *
+        * The address PROM is 32 bytes wide, and we access it through
+        * a single I/O port.  On each read, it rotates to the next
+        * position.  We find the ethernet address by looking for a
+        * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff,
+        * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the
+        * ethernet address and a checksum).
+        *
+        * It appears that the PROM can be at one of two locations, so
+        * we just try both.
+        */
+       port = iobase + DEPCA_ADP;
+       for (i = 0; i < 32; i++)
+               if (inb(port) == 0xff && inb(port) == 0x00 &&
+                   inb(port) == 0x55 && inb(port) == 0xaa &&
+                   inb(port) == 0xff && inb(port) == 0x00 &&
+                   inb(port) == 0x55 && inb(port) == 0xaa)
+                       goto found;
+       port = iobase + DEPCA_ADP + 1;
+       for (i = 0; i < 32; i++)
+               if (inb(port) == 0xff && inb(port) == 0x00 &&
+                   inb(port) == 0x55 && inb(port) == 0xaa &&
+                   inb(port) == 0xff && inb(port) == 0x00 &&
+                   inb(port) == 0x55 && inb(port) == 0xaa)
+                       goto found;
+       printf("%s: address not found\n", sc->sc_dev.dv_xname);
+       return 0;
+
+found:
+       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
+               sc->sc_arpcom.ac_enaddr[i] = inb(port);
+
+#if 0
+       sum =
+           (sc->sc_arpcom.ac_enaddr[0] <<  2) +
+           (sc->sc_arpcom.ac_enaddr[1] << 10) +
+           (sc->sc_arpcom.ac_enaddr[2] <<  1) +
+           (sc->sc_arpcom.ac_enaddr[3] <<  9) +
+           (sc->sc_arpcom.ac_enaddr[4] <<  0) +
+           (sc->sc_arpcom.ac_enaddr[5] <<  8);
+       sum = (sum & 0xffff) + (sum >> 16);
+       sum = (sum & 0xffff) + (sum >> 16);
+
+       rom_sum = inb(port);
+       rom_sum |= inb(port) << 8;
+
+       if (sum != rom_sum) {
+               printf("%s: checksum mismatch; calculated %04x != read %04x",
+                   sc->sc_dev.dv_xname, sum, rom_sum);
+               return 0;
+       }
+#endif
+
+       outb(iobase + DEPCA_CSR, DEPCA_CSR_NORMAL);
+
+       ia->ia_iosize = 16;
+       ia->ia_drq = DRQUNK;
+       return 1;
+}
+
+int
+ne2100_isa_probe(lesc, ia)
+       struct le_softc *lesc;
+       struct isa_attach_args *ia;
+{
+       struct am7990_softc *sc = &lesc->sc_am7990;
+       int iobase = ia->ia_iobase;
+       int i;
+
+       lesc->sc_rap = iobase + NE2100_RAP;
+       lesc->sc_rdp = iobase + NE2100_RDP;
+       lesc->sc_card = NE2100;
+
+       if (lance_isa_probe(sc) == 0)
+               return 0;
+
+       /*
+        * Extract the physical MAC address from the ROM.
+        */
+       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
+               sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i);
+
+       ia->ia_iosize = 24;
+       return 1;
+}
+
+int
+bicc_isa_probe(lesc, ia)
+       struct le_softc *lesc;
+       struct isa_attach_args *ia;
+{
+       struct am7990_softc *sc = &lesc->sc_am7990;
+       int iobase = ia->ia_iobase;
+       int i;
+
+       lesc->sc_rap = iobase + BICC_RAP;
+       lesc->sc_rdp = iobase + BICC_RDP;
+       lesc->sc_card = BICC;
+
+       if (lance_isa_probe(sc) == 0)
+               return 0;
+
+       /*
+        * Extract the physical MAC address from the ROM.
+        */
+       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
+               sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i * 2);
+
+       ia->ia_iosize = 16;
+       return 1;
+}
+
+/*
+ * Determine which chip is present on the card.
+ */
+int
+lance_isa_probe(sc)
+       struct am7990_softc *sc;
+{
+
+       /* Stop the LANCE chip and put it in a known state. */
+       le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP);
+       delay(100);
+
+       if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP)
+               return 0;
+
+       le_isa_wrcsr(sc, LE_CSR3, sc->sc_conf3);
+       return 1;
+}
+
+void
+le_isa_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct le_softc *lesc = (void *)self;
+       struct am7990_softc *sc = &lesc->sc_am7990;
+       struct isa_attach_args *ia = aux;
+
+       printf(": %s Ethernet\n", sc->sc_dev.dv_xname,
+           card_type[lesc->sc_card]);
+
+       if (lesc->sc_card == DEPCA) {
+               u_char *mem, val;
+               int i;
+
+               mem = sc->sc_mem = ISA_HOLE_VADDR(ia->ia_maddr);
+
+               val = 0xff;
+               for (;;) {
+                       for (i = 0; i < ia->ia_msize; i++)
+                               mem[i] = val;
+                       for (i = 0; i < ia->ia_msize; i++)
+                               if (mem[i] != val) {
+                                       printf("%s: failed to clear memory\n",
+                                           sc->sc_dev.dv_xname);
+                                       return;
+                               }
+                       if (val == 0x00)
+                               break;
+                       val -= 0x55;
+               }
+
+               sc->sc_conf3 = LE_C3_ACON;
+               sc->sc_addr = 0;
+               sc->sc_memsize = ia->ia_msize;
+       } else {
+               sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT);
+               if (sc->sc_mem == 0) {
+                       printf("%s: couldn't allocate memory for card\n",
+                           sc->sc_dev.dv_xname);
+                       return;
+               }
+
+               sc->sc_conf3 = 0;
+               sc->sc_addr = kvtop(sc->sc_mem);
+               sc->sc_memsize = 16384;
+       }
+
+       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 = le_isa_rdcsr;
+       sc->sc_wrcsr = le_isa_wrcsr;
+       sc->sc_hwinit = NULL;
+
+       printf("%s", sc->sc_dev.dv_xname);
+       am7990_config(sc);
+
+       if (ia->ia_drq != DRQUNK)
+               isa_dmacascade(ia->ia_drq);
+
+       lesc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+           IPL_NET, le_isa_intredge, sc);
+}
+
+/*
+ * Controller interrupt.
+ */
+le_isa_intredge(arg)
+       void *arg;
+{
+
+       if (am7990_intr(arg) == 0)
+               return (0);
+       for (;;)
+               if (am7990_intr(arg) == 0)
+                       return (1);
+}
index e28b35a..57c8c3f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_levar.h,v 1.4 1996/04/29 20:03:23 christos Exp $    */
+/*     $NetBSD: if_levar.h,v 1.5 1996/05/07 01:50:07 thorpej Exp $     */
 
 /*
  * LANCE Ethernet driver header file
@@ -20,7 +20,6 @@
 
 #define        NE2100          2
 #define        PCnet_ISA       4
-#define        PCnet_PCI       5
 #define        NE2100_RDP      0x10
 #define        NE2100_RAP      0x12
 
  * This structure contains the output queue for the interface, its address, ...
  */
 struct le_softc {
-       struct  device sc_dev;          /* base structure */
-       struct  arpcom sc_arpcom;       /* Ethernet common part */
-
-       void    (*sc_copytodesc)        /* Copy to descriptor */
-                       __P((struct le_softc *, void *, int, int));
-       void    (*sc_copyfromdesc)      /* Copy from descriptor */
-                       __P((struct le_softc *, void *, int, int));
-       void    (*sc_copytobuf)         /* Copy to buffer */
-                       __P((struct le_softc *, void *, int, int));
-       void    (*sc_copyfrombuf)       /* Copy from buffer */
-                       __P((struct le_softc *, void *, int, int));
-       void    (*sc_zerobuf)           /* and Zero bytes in buffer */
-                       __P((struct le_softc *, int, int));
-
-       u_int16_t sc_conf3;             /* CSR3 value */
-
-       void    *sc_mem;                /* base address of RAM -- CPU's view */
-       u_long  sc_addr;                /* base address of RAM -- LANCE's view */
-       u_long  sc_memsize;             /* size of RAM */
-
-       int     sc_nrbuf;               /* number of receive buffers */
-       int     sc_ntbuf;               /* number of transmit buffers */
-       int     sc_last_rd;
-       int     sc_first_td, sc_last_td, sc_no_td;
-
-       int     sc_initaddr;
-       int     sc_rmdaddr;
-       int     sc_tmdaddr;
-       int     sc_rbufaddr;
-       int     sc_tbufaddr;
-
-#ifdef LEDEBUG
-       int     sc_debug;
-#endif
+       struct  am7990_softc sc_am7990; /* glue to MI code */
 
        void    *sc_ih;
        bus_io_handle_t sc_ioh;
-       void    *sc_sh;
        int     sc_card;
-       int     sc_rap, sc_rdp;         /* LANCE registers */
+       int     sc_rap, sc_rdp;         /* offsets to LANCE registers */
 };
index aefcf00..6c85de4 100644 (file)
@@ -1,5 +1,5 @@
-/*    $OpenBSD: if_de.c,v 1.8 1996/05/07 07:38:29 deraadt Exp $       */
-/*    $NetBSD: if_de.c,v 1.18 1996/05/03 17:32:20 christos Exp $       */
+/*    $OpenBSD: if_de.c,v 1.9 1996/05/10 12:41:24 deraadt Exp $       */
+/*    $NetBSD: if_de.c,v 1.19 1996/05/07 02:17:18 thorpej Exp $       */
 
 /*-
  * Copyright (c) 1994, 1995 Matt Thomas (matt@lkg.dec.com)
@@ -317,6 +317,7 @@ struct _tulip_softc_t {
     bus_io_handle_t tulip_memh;                /* memory region handle */
 #endif
 #endif
+    char tulip_xname[IFNAMSIZ];                /* name + unit number */
     struct arpcom tulip_ac;
     tulip_regfile_t tulip_csrs;
     unsigned tulip_flags;
@@ -366,6 +367,7 @@ typedef void ifnet_ret_t;
 typedef int ioctl_cmd_t;
 tulip_softc_t *tulips[NDE];
 #define        TULIP_UNIT_TO_SOFTC(unit)       (tulips[unit])
+#define        TULIP_IFP_TO_SOFTC(ifp)         (TULIP_UNIT_TO_SOFTC((ifp)->if_unit))
 #define        TULIP_BURSTSIZE(unit)           pci_max_burst_len
 #endif
 #if defined(__bsdi__)
@@ -373,6 +375,7 @@ typedef int ifnet_ret_t;
 typedef int ioctl_cmd_t;
 extern struct cfdriver decd;
 #define        TULIP_UNIT_TO_SOFTC(unit)       ((tulip_softc_t *) decd.cd_devs[unit])
+#define TULIP_IFP_TO_SOFTC(ifp)                (TULIP_UNIT_TO_SOFTC((ifp)->if_unit))
 #define        TULIP_BURSTSIZE(unit)           log2_burst_size
 #endif
 #if defined(__NetBSD__)
@@ -381,6 +384,7 @@ typedef u_long ioctl_cmd_t;
 extern struct cfattach de_ca;
 extern struct cfdriver de_cd;
 #define        TULIP_UNIT_TO_SOFTC(unit)       ((tulip_softc_t *) de_cd.cd_devs[unit])
+#define        TULIP_IFP_TO_SOFTC(ifp)         ((tulip_softc_t *)((ifp)->if_softc))
 #endif
 
 #ifndef TULIP_BURSTSIZE
@@ -388,8 +392,13 @@ extern struct cfdriver de_cd;
 #endif
 
 #define        tulip_if        tulip_ac.ac_if
+#ifdef __NetBSD__
+#define        tulip_unit      tulip_dev.dv_unit
+#define        tulip_name      tulip_dev.dv_cfdata->cf_driver->cd_name
+#else
 #define        tulip_unit      tulip_ac.ac_if.if_unit
 #define        tulip_name      tulip_ac.ac_if.if_name
+#endif
 #define        tulip_bpf       tulip_ac.ac_if.if_bpf
 #define        tulip_hwaddr    tulip_ac.ac_enaddr
 
@@ -440,14 +449,12 @@ tulip_dc21040_media_select(
     TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
     if (sc->tulip_if.if_flags & IFF_ALTPHYS) {
        if ((sc->tulip_flags & TULIP_ALTPHYS) == 0)
-           printf("%s%d: enabling Thinwire/AUI port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling Thinwire/AUI port\n", sc->tulip_xname);
        TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_AUI);
        sc->tulip_flags |= TULIP_ALTPHYS;
     } else {
        if (sc->tulip_flags & TULIP_ALTPHYS)
-           printf("%s%d: enabling 10baseT/UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 10baseT/UTP port\n", sc->tulip_xname);
        TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET);
        sc->tulip_flags &= ~TULIP_ALTPHYS;
        sc->tulip_media = TULIP_MEDIA_10BASET;
@@ -478,8 +485,7 @@ tulip_zx314_media_select(
        |TULIP_CMD_BACKOFFCTR;
     TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET);
     if (sc->tulip_flags & TULIP_ALTPHYS)
-       printf("%s%d: enabling 10baseT/UTP port\n",
-              sc->tulip_if.if_name, sc->tulip_if.if_unit);
+       printf("%s: enabling 10baseT/UTP port\n", sc->tulip_xname);
     TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET);
     sc->tulip_flags &= ~TULIP_ALTPHYS;
     sc->tulip_media = TULIP_MEDIA_10BASET;
@@ -525,8 +531,7 @@ tulip_dc21140_evalboard_media_select(
     TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_INIT);
     if (sc->tulip_if.if_flags & IFF_ALTPHYS) {
        if ((sc->tulip_flags & TULIP_ALTPHYS) == 0)
-           printf("%s%d: enabling 100baseTX UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname);
        sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT
            |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER;
        sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL;
@@ -534,8 +539,7 @@ tulip_dc21140_evalboard_media_select(
        sc->tulip_media = TULIP_MEDIA_100BASET;
     } else {
        if (sc->tulip_flags & TULIP_ALTPHYS)
-           printf("%s%d: enabling 10baseT UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 10baseT UTP port\n", sc->tulip_xname);
        sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT
                               |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER);
        sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL;
@@ -579,8 +583,7 @@ tulip_dc21140_cogent_em100_media_select(
     TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_PINS);
     TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_INIT);
     if ((sc->tulip_flags & TULIP_ALTPHYS) == 0)
-       printf("%s%d: enabling 100baseTX UTP port\n",
-              sc->tulip_if.if_name, sc->tulip_if.if_unit);
+       printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname);
     sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT
        |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER;
     sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL;
@@ -627,8 +630,7 @@ tulip_dc21140_znyx_zx34x_media_select(
     TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_ZX34X_INIT);
     if (sc->tulip_if.if_flags & IFF_ALTPHYS) {
        if ((sc->tulip_flags & TULIP_ALTPHYS) == 0)
-           printf("%s%d: enabling 100baseTX UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname);
        sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT
            |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER;
        sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL;
@@ -636,8 +638,7 @@ tulip_dc21140_znyx_zx34x_media_select(
        sc->tulip_media = TULIP_MEDIA_100BASET;
     } else {
        if (sc->tulip_flags & TULIP_ALTPHYS)
-           printf("%s%d: enabling 10baseT UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 10baseT UTP port\n", sc->tulip_xname);
        sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT
                               |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER);
        sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL;
@@ -689,8 +690,7 @@ tulip_dc21140_de500_media_select(
     TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_PINS);
     if (sc->tulip_if.if_flags & IFF_ALTPHYS) {
        if ((sc->tulip_flags & TULIP_ALTPHYS) == 0)
-           printf("%s%d: enabling 100baseTX UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 100baseTX UTP port\n", sc->tulip_xname);
        sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT
            |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER;
        sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL;
@@ -700,8 +700,7 @@ tulip_dc21140_de500_media_select(
            TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100);
     } else {
        if (sc->tulip_flags & TULIP_ALTPHYS)
-           printf("%s%d: enabling 10baseT UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 10baseT UTP port\n", sc->tulip_xname);
        sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT
                               |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER);
        sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL;
@@ -827,8 +826,7 @@ tulip_dc21041_media_select(
                         && sc->tulip_media != TULIP_MEDIA_AUI)
                        || (sc->tulip_probe_state == TULIP_PROBE_BNC
                            && sc->tulip_media != TULIP_MEDIA_AUI)) {
-                       printf("%s%d: enabling %s port\n",
-                              sc->tulip_if.if_name, sc->tulip_if.if_unit,
+                       printf("%s: enabling %s port\n", sc->tulip_xname,
                               sc->tulip_probe_state == TULIP_PROBE_BNC
                                   ? "Thinwire/BNC" : "AUI");
                        if (sc->tulip_probe_state == TULIP_PROBE_AUI)
@@ -888,8 +886,8 @@ tulip_dc21041_media_select(
                        sc->tulip_flags &= ~TULIP_WANTRXACT;
                        sc->tulip_gpticks = 4;
                    } else {
-                       printf("%s%d: autosense failed: cable problem?\n",
-                              sc->tulip_name, sc->tulip_unit);
+                       printf("%s: autosense failed: cable problem?\n",
+                              sc->tulip_xname);
                    }
                }
                /*
@@ -920,8 +918,7 @@ tulip_dc21041_media_select(
         * proper media to use.
         */
        if (sc->tulip_media != TULIP_MEDIA_10BASET)
-           printf("%s%d: enabling 10baseT/UTP port\n",
-                  sc->tulip_if.if_name, sc->tulip_if.if_unit);
+           printf("%s: enabling 10baseT/UTP port\n", sc->tulip_xname);
        if (sc->tulip_media != TULIP_MEDIA_10BASET
                || (sc->tulip_flags & TULIP_INRESET)) {
            sc->tulip_media = TULIP_MEDIA_10BASET;
@@ -1282,7 +1279,7 @@ static ifnet_ret_t
 tulip_start(
     struct ifnet * const ifp)
 {
-    tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit);
+    tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
     struct ifqueue * const ifq = &ifp->if_snd;
     tulip_ringinfo_t * const ri = &sc->tulip_txinfo;
     struct mbuf *m, *m0, *next_m0;
@@ -1514,8 +1511,8 @@ tulip_intr(
                }
            }
            if (csr & TULIP_STS_ABNRMLINTR) {
-               printf("%s%d: abnormal interrupt: 0x%05x [0x%05x]\n",
-                      sc->tulip_name, sc->tulip_unit, csr, csr & sc->tulip_intrmask);
+               printf("%s: abnormal interrupt: 0x%05x [0x%05x]\n",
+                      sc->tulip_xname, csr, csr & sc->tulip_intrmask);
                TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode);
            }
            if (csr & TULIP_STS_RXINTR)
@@ -1930,7 +1927,7 @@ tulip_ioctl(
     ioctl_cmd_t cmd,
     caddr_t data)
 {
-    tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit);
+    tulip_softc_t * const sc = TULIP_IFP_TO_SOFTC(ifp);
     struct ifaddr *ifa = (struct ifaddr *)data;
     struct ifreq *ifr = (struct ifreq *) data;
     int s, error = 0;
@@ -2048,15 +2045,22 @@ tulip_attach(
     ifp->if_start = tulip_start;
   
 #if defined(__FreeBSD__)
-    printf("%s%d", sc->tulip_name, sc->tulip_unit);
+    printf("%s", sc->tulip_xname);
 #elif defined(__bsdi__)
-    printf("\n%s%d", sc->tulip_name, sc->tulip_unit);
+    printf("\n%s", sc->tulip_xname);
 #endif
+#if defined(__NetBSD__)
+    printf(": %s%s pass %d.%d\n%s: Ethernet address %s\n",
+#else
     printf(": %s%s pass %d.%d Ethernet address %s\n", 
+#endif
           sc->tulip_boardsw->bd_description,
           tulip_chipdescs[sc->tulip_chipid],
           (sc->tulip_revinfo & 0xF0) >> 4,
           sc->tulip_revinfo & 0x0F,
+#if defined(__NetBSD__)
+          sc->tulip_dev.dv_xname,
+#endif
           ether_sprintf(sc->tulip_hwaddr));
 
     if ((*sc->tulip_boardsw->bd_media_probe)(sc)) {
@@ -2515,9 +2519,19 @@ tulip_pci_attach(
     }
 
     sc->tulip_chipid = chipid;
+#if defined(__NetBSD__)
+    bcopy(self->dv_xname, sc->tulip_if.if_xname, IFNAMSIZ);
+    sc->tulip_if.if_softc = sc;
+#else
     sc->tulip_unit = unit;
     sc->tulip_name = "de";
+#endif
     sc->tulip_revinfo = revinfo;
+
+    /* Set up human-readable name. */
+    bzero(sc->tulip_xname, sizeof(sc->tulip_xname));
+    sprintf(sc->tulip_xname, "%s%d", sc->tulip_name, sc->tulip_unit);
+
 #if defined(__FreeBSD__)
 #if defined(TULIP_IOMAPPED)
     retval = pci_map_port(config_id, PCI_CBIO, &csr_base);
@@ -2567,14 +2581,14 @@ tulip_pci_attach(
     tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS);
     if ((retval = tulip_read_macaddr(sc)) < 0) {
 #ifdef __FreeBSD__
-       printf("%s%d", sc->tulip_name, sc->tulip_unit);
+       printf("%s", sc->tulip_xname);
 #endif
        printf(": can't read ENET ROM (why=%d) (", retval);
        for (idx = 0; idx < 32; idx++)
            printf("%02x", sc->tulip_rombuf[idx]);
        printf("\n");
-       printf("%s%d: %s%s pass %d.%d Ethernet address %s\n",
-              sc->tulip_name, sc->tulip_unit,
+       printf("%s: %s%s pass %d.%d Ethernet address %s\n",
+              sc->tulip_xname,
               (sc->tulip_boardsw != NULL ? sc->tulip_boardsw->bd_description : ""),
               tulip_chipdescs[sc->tulip_chipid],
               (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F,
@@ -2609,14 +2623,13 @@ tulip_pci_attach(
        }
        sc->tulip_ats = shutdownhook_establish(tulip_pci_shutdown, sc);
        if (sc->tulip_ats == NULL)
-           printf("\n%s%d: warning: couldn't establish shutdown hook",
-                  sc->tulip_name, sc->tulip_unit);
+           printf("\n%s: warning: couldn't establish shutdown hook",
+                  sc->tulip_xname);
 #endif
 #if defined(__FreeBSD__)
        if (sc->tulip_boardsw->bd_type != TULIP_DC21040_ZX314_SLAVE) {
            if (!pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask)) {
-               printf("%s%d: couldn't map interrupt\n",
-                      sc->tulip_name, sc->tulip_unit);
+               printf("%s: couldn't map interrupt\n", sc->tulip_xname);
                return;
            }
        }
index eb6be35..7a53b6d 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: if_fpa.c,v 1.5 1996/04/21 22:25:19 deraadt Exp $      */
-/*     $NetBSD: if_fpa.c,v 1.7 1996/03/17 00:55:30 thorpej Exp $       */
+/*     $OpenBSD: if_fpa.c,v 1.6 1996/05/10 12:41:26 deraadt Exp $      */
+/*     $NetBSD: if_fpa.c,v 1.8 1996/05/07 02:17:23 thorpej Exp $       */
 
 /*-
  * Copyright (c) 1995 Matt Thomas (thomas@lkg.dec.com)
@@ -191,9 +191,24 @@ extern struct cfdriver fpa_cd;
 #define        PDQ_PCI_UNIT_TO_SOFTC(unit)     ((pdq_softc_t *)fpa_cd.cd_devs[unit])
 #endif
 
+#if defined(__NetBSD__)
 static ifnet_ret_t
 pdq_pci_ifinit(
-    int unit)
+    struct ifnet *ifp)
+{
+    pdq_ifinit((pdq_softc_t *)(ifp->if_softc));
+}
+
+static ifnet_ret_t
+pdq_pci_ifwatchdog(
+    struct ifnet *ifp)
+{
+    pdq_ifwatchdog((pdq_softc_t *)(ifp->if_softc));
+}
+#else
+static ifnet_ret_t 
+pdq_pci_ifinit(
+    int unit) 
 {
     pdq_ifinit(PDQ_PCI_UNIT_TO_SOFTC(unit));
 }
@@ -204,6 +219,7 @@ pdq_pci_ifwatchdog(
 {
     pdq_ifwatchdog(PDQ_PCI_UNIT_TO_SOFTC(unit));
 }
+#endif
 
 static int
 pdq_pci_ifintr(
@@ -428,39 +444,40 @@ pdq_pci_attach(
     pdq_uint32_t data;
     pdq_softc_t * const sc = (pdq_softc_t *) self;
     struct pci_attach_args * const pa = (struct pci_attach_args *) aux;
+    pci_chipset_tag_t pc = pa->pa_pc;
 
-    data = pci_conf_read(pa->pa_tag, PCI_CFLT);
+    data = pci_conf_read(pc, pa->pa_tag, PCI_CFLT);
     if ((data & 0xFF00) == 0) {
        data &= ~0xFF00;
        data |= DEFPA_LATENCY << 8;
-       pci_conf_write(pa->pa_tag, PCI_CFLT, data);
+       pci_conf_write(pc, pa->pa_tag, PCI_CFLT, data);
     }
 
     if (pci_map_mem(pa->pa_tag, PCI_CBMA, &va_csrs, &pa_csrs))
        return;
 
-    sc->sc_if.if_name = "fpa";
-    sc->sc_if.if_unit = sc->sc_dev.dv_unit;
+    bcopy(sc->sc_dev.dv_xname, sc->sc_if.if_xname, IFNAMSIZ);
+    sc->sc_if.if_softc = sc;
     sc->sc_if.if_flags = 0;
-    sc->sc_pdq = pdq_initialize((void *) va_csrs, sc->sc_if.if_name,
-                               sc->sc_if.if_unit, (void *) sc, PDQ_DEFPA);
+    sc->sc_pdq = pdq_initialize((void *) va_csrs,
+        sc->sc_dev.dv_cfdata->cf_driver->cd_name, sc->sc_dev.dv_unit,
+       (void *) sc, PDQ_DEFPA);
     if (sc->sc_pdq == NULL)
        return;
     bcopy((caddr_t) sc->sc_pdq->pdq_hwaddr.lanaddr_bytes, sc->sc_ac.ac_enaddr,
        6);
     pdq_ifattach(sc, pdq_pci_ifinit, pdq_pci_ifwatchdog);
 
-    sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, pdq_pci_ifintr, sc
-       sc->sc_dev.dv_xname);
+    sc->sc_ih = pci_map_int(pa->pa_tag, IPL_NET, pdq_pci_ifintr, sc);
     if (sc->sc_ih == NULL) {
-       printf("fpa%d: error: couldn't map interrupt\n",  sc->sc_if.if_unit);
+       printf("%s: error: couldn't map interrupt\n", sc->sc_dev.dv_xname);
        return;
     }
 #if 0
     sc->sc_ats = shutdownhook_establish(pdq_hwreset, sc);
     if (sc->sc_ats == NULL)
-       printf("fpa%d: warning: couldn't establish shutdown hook\n",
-              sc->sc_if.if_unit);
+       printf("%s: warning: couldn't establish shutdown hook\n",
+              sc->sc_dev.dv_xname);
 #endif
 }
 
diff --git a/sys/dev/pci/if_le_pci.c b/sys/dev/pci/if_le_pci.c
new file mode 100644 (file)
index 0000000..e08d890
--- /dev/null
@@ -0,0 +1,206 @@
+/*     $NetBSD: if_le_pci.c,v 1.1 1996/05/07 02:03:02 thorpej Exp $    */
+
+/*-
+ * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
+ * 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
+ */
+
+#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 <net/if.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <vm/vm.h>
+
+#include <machine/cpu.h>
+#include <machine/pio.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+#include <dev/pci/if_levar.h>
+
+int le_pci_match __P((struct device *, void *, void *));
+void le_pci_attach __P((struct device *, struct device *, void *));
+
+struct cfattach le_pci_ca = {
+       sizeof(struct le_softc), le_pci_match, le_pci_attach
+};
+
+hide void le_pci_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+hide u_int16_t le_pci_rdcsr __P((struct am7990_softc *, u_int16_t));
+
+hide void
+le_pci_wrcsr(sc, port, val)
+       struct am7990_softc *sc;
+       u_int16_t port, val;
+{
+
+       outw(((struct le_softc *)sc)->sc_rap, port);
+       outw(((struct le_softc *)sc)->sc_rdp, val);
+}
+
+hide u_int16_t
+le_pci_rdcsr(sc, port)
+       struct am7990_softc *sc;
+       u_int16_t port;
+{
+       u_int16_t val;
+
+       outw(((struct le_softc *)sc)->sc_rap, port);
+       val = inw(((struct le_softc *)sc)->sc_rdp);
+       return (val);
+}
+
+int
+le_pci_match(parent, match, aux)
+       struct device *parent;
+       void *match, *aux;
+{
+       struct pci_attach_args *pa = aux;
+
+       if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD)
+               return (0);
+
+       switch (PCI_PRODUCT(pa->pa_id)) {
+       case PCI_PRODUCT_AMD_PCNET_PCI:
+               return (1);
+       }
+
+       return (0);
+}
+
+void
+le_pci_attach(parent, self, aux)
+       struct device *parent, *self;
+       void *aux;
+{
+       struct le_softc *lesc = (void *)self;
+       struct am7990_softc *sc = &lesc->sc_am7990;
+       struct pci_attach_args *pa = aux;
+       pci_chipset_tag_t pc = pa->pa_pc;
+       pci_intr_handle_t ih;
+       pcireg_t csr;
+       int iobase, i;
+       const char *model, *intrstr;
+
+       switch (PCI_PRODUCT(pa->pa_id)) {
+       case PCI_PRODUCT_AMD_PCNET_PCI:
+               model = "PCnet-PCI Ethernet";
+               lesc->sc_rap = iobase + PCNET_PCI_RAP;
+               lesc->sc_rdp = iobase + PCNET_PCI_RDP;
+               break;
+
+       default:
+               model = "unknown model!";
+       }
+
+       printf(": %s\n", sc->sc_dev.dv_xname, model);
+
+       if (pci_map_io(pa->pa_tag, 0x10, &iobase))
+               return;
+
+       /*
+        * Extract the physical MAC address from the ROM.
+        */
+       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
+               sc->sc_arpcom.ac_enaddr[i] = inb(iobase + i);
+
+       sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT);
+       if (sc->sc_mem == 0) {
+               printf("%s: couldn't allocate memory for card\n",
+                   sc->sc_dev.dv_xname);
+               return;
+       }
+
+       sc->sc_conf3 = 0;
+       sc->sc_addr = kvtop(sc->sc_mem);        /* XXX XXX XXX */
+       sc->sc_memsize = 16384;
+
+       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 = le_pci_rdcsr;
+       sc->sc_wrcsr = le_pci_wrcsr;
+       sc->sc_hwinit = NULL;
+
+       printf("%s", sc->sc_dev.dv_xname);
+       am7990_config(sc);
+
+       /* Enable the card. */
+       csr = pci_conf_read(pa->pa_bc, pa->pa_tag,
+           PCI_COMMAND_STATUS_REG);
+       pci_conf_write(pa->pa_bc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+           csr | PCI_COMMAND_MASTER_ENABLE);
+
+       /* Map and establish the interrupt. */
+       if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
+           pa->pa_intrline, &ih)) {
+               printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
+               return;
+       }
+       intrstr = pci_intr_string(pc, ih);
+       lesc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, am7990_intr, sc,
+           sc->sc_dev.dv_xname);
+       if (lesc->sc_ih == NULL) {
+               printf("%s: couldn't establish interrupt",
+                   sc->sc_dev.dv_xname);
+               if (intrstr != NULL)
+                       printf(" at %s", intrstr);
+               printf("\n");
+               return;
+       }
+       printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
+}
diff --git a/sys/dev/pci/if_levar.h b/sys/dev/pci/if_levar.h
new file mode 100644 (file)
index 0000000..03f5e0c
--- /dev/null
@@ -0,0 +1,31 @@
+/*     $NetBSD: if_levar.h,v 1.1 1996/05/07 02:03:04 thorpej Exp $     */
+
+/*
+ * LANCE Ethernet driver header file
+ *
+ * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
+ *
+ * Copyright (C) 1993, Paul Richards. This software may be used, modified,
+ *   copied, distributed, and sold, in both source and binary form provided
+ *   that the above copyright and these terms are retained. Under no
+ *   circumstances is the author responsible for the proper functioning
+ *   of this software, nor does the author assume any responsibility
+ *   for damages incurred with its use.
+ */
+
+#define        PCNET_PCI_RDP   0x10
+#define        PCNET_PCI_RAP   0x12
+
+/*
+ * 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 */
+
+       void    *sc_ih;
+       int     sc_rap, sc_rdp;         /* offsets to LANCE registers */
+};
index 51415a9..67368f0 100644 (file)
@@ -1,170 +1 @@
-/*     $OpenBSD: if_le.c,v 1.4 1996/05/02 13:51:48 deraadt Exp $       */
-/*     $NetBSD: if_le.c,v 1.9 1996/04/22 02:54:10 christos Exp $       */
-
-/*-
- * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
- * 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
- */
-
-#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 <net/if.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#endif
-
-#include <dev/tc/if_levar.h>
-#include <dev/ic/am7990reg.h>
-#define        LE_NEED_BUF_CONTIG
-#define        LE_NEED_BUF_GAP2
-#define        LE_NEED_BUF_GAP16
-#include <dev/ic/am7990var.h>
-#include <dev/tc/tcvar.h>
-
-/* access LANCE registers */
-void lewritereg __P((volatile u_short *regptr, u_short val));
-#define        LERDWR(cntl, src, dst)  { (dst) = (src); tc_mb(); }
-#define        LEWREG(src, dst)        lewritereg(&(dst), (src))
-
-#define        LE_SOFTC(unit)  le_cd.cd_devs[unit]
-#define        LE_DELAY(x)     DELAY(x)
-
-struct cfdriver le_cd = {
-       NULL, "le", DV_IFNET
-};
-
-void
-dec_le_common_attach(sc, eap)
-       struct le_softc *sc;
-       u_char *eap;
-{
-       int i;
-
-       sc->sc_conf3 = 0;
-       sc->sc_addr = 0;
-       sc->sc_memsize = 65536;
-
-       /*
-        * Get the ethernet address out of rom
-        */
-       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) {
-               sc->sc_arpcom.ac_enaddr[i] = *eap;
-               eap += 4;
-       }
-
-       sc->sc_arpcom.ac_if.if_name = le_cd.cd_name;
-       leconfig(sc);
-}
-
-integrate void
-lehwinit(sc)
-       struct le_softc *sc;
-{
-}
-
-integrate void
-lewrcsr(sc, port, val)
-       struct le_softc *sc;
-       u_int16_t port, val;
-{
-       struct lereg1 *ler1 = sc->sc_r1;
-
-       LEWREG(port, ler1->ler1_rap);
-       LERDWR(port, val, ler1->ler1_rdp);
-}
-
-integrate u_int16_t
-lerdcsr(sc, port)
-       struct le_softc *sc;
-       u_int16_t port;
-{
-       struct lereg1 *ler1 = sc->sc_r1;
-       u_int16_t val;
-
-       LEWREG(port, ler1->ler1_rap);
-       LERDWR(0, ler1->ler1_rdp, val);
-       return (val);
-}
-
-/*
- * Write a lance register port, reading it back to ensure success. This seems
- * to be necessary during initialization, since the chip appears to be a bit
- * pokey sometimes.
- */
-void
-lewritereg(regptr, val)
-       register volatile u_short *regptr;
-       register u_short val;
-{
-       register int i = 0;
-
-       while (*regptr != val) {
-               *regptr = val;
-               tc_mb();
-               if (++i > 10000) {
-                       printf("le: Reg did not settle (to x%x): x%x\n", val,
-                           *regptr);
-                       return;
-               }
-               DELAY(100);
-       }
-}
-
-/*
- * Routines for accessing the transmit and receive buffers are provided
- * by am7990.c, because of the LE_NEED_BUF_* macros defined above.
- * Unfortunately, CPU addressing of these buffers is done in one of
- * 3 ways:
- * - contiguous (for the 3max and turbochannel option card)
- * - gap2, which means shorts (2 bytes) interspersed with short (2 byte)
- *   spaces (for the pmax)
- * - gap16, which means 16bytes interspersed with 16byte spaces
- *   for buffers which must begin on a 32byte boundary (for 3min, maxine,
- *   and alpha)
- * The buffer offset is the logical byte offset, assuming contiguous storage.
- */
-
-#include <dev/ic/am7990.c>
+/*     $OpenBSD: if_le.c,v 1.5 1996/05/10 12:41:28 deraadt Exp $       */
diff --git a/sys/dev/tc/if_le_dec.c b/sys/dev/tc/if_le_dec.c
new file mode 100644 (file)
index 0000000..5e20938
--- /dev/null
@@ -0,0 +1,158 @@
+/*     $NetBSD: if_le_dec.c,v 1.1 1996/05/07 02:24:55 thorpej Exp $    */
+
+/*-
+ * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
+ * 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
+ */
+
+#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 <net/if.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <dev/ic/am7990reg.h>
+#include <dev/ic/am7990var.h>
+
+#include <dev/tc/if_levar.h>
+#include <dev/tc/tcvar.h>
+
+/* access LANCE registers */
+void le_dec_writereg __P((volatile u_short *regptr, u_short val));
+#define        LERDWR(cntl, src, dst)  { (dst) = (src); tc_mb(); }
+#define        LEWREG(src, dst)        le_dec_writereg(&(dst), (src))
+
+hide void le_dec_wrcsr __P((struct am7990_softc *, u_int16_t, u_int16_t));
+hide u_int16_t le_dec_rdcsr __P((struct am7990_softc *, u_int16_t));  
+
+void
+dec_le_common_attach(sc, eap)
+       struct am7990_softc *sc;
+       u_char *eap;
+{
+       int i;
+
+       sc->sc_rdcsr = le_dec_rdcsr;
+       sc->sc_wrcsr = le_dec_wrcsr;
+       sc->sc_hwinit = NULL;
+
+       sc->sc_conf3 = 0;
+       sc->sc_addr = 0;
+       sc->sc_memsize = 65536;
+
+       /*
+        * Get the ethernet address out of rom
+        */
+       for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++) {
+               sc->sc_arpcom.ac_enaddr[i] = *eap;
+               eap += 4;
+       }
+
+       am7990_config(sc);
+}
+
+hide void
+le_dec_wrcsr(sc, port, val)
+       struct am7990_softc *sc;
+       u_int16_t port, val;
+{
+       struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
+
+       LEWREG(port, ler1->ler1_rap);
+       LERDWR(port, val, ler1->ler1_rdp);
+}
+
+hide u_int16_t
+le_dec_rdcsr(sc, port)
+       struct am7990_softc *sc;
+       u_int16_t port;
+{
+       struct lereg1 *ler1 = ((struct le_softc *)sc)->sc_r1;
+       u_int16_t val;
+
+       LEWREG(port, ler1->ler1_rap);
+       LERDWR(0, ler1->ler1_rdp, val);
+       return (val);
+}
+
+/*
+ * Write a lance register port, reading it back to ensure success. This seems
+ * to be necessary during initialization, since the chip appears to be a bit
+ * pokey sometimes.
+ */
+void
+le_dec_writereg(regptr, val)
+       register volatile u_short *regptr;
+       register u_short val;
+{
+       register int i = 0;
+
+       while (*regptr != val) {
+               *regptr = val;
+               tc_mb();
+               if (++i > 10000) {
+                       printf("le: Reg did not settle (to x%x): x%x\n", val,
+                           *regptr);
+                       return;
+               }
+               DELAY(100);
+       }
+}
+
+/*
+ * Routines for accessing the transmit and receive buffers are provided
+ * by am7990.c, because of the LE_NEED_BUF_* macros defined above.
+ * Unfortunately, CPU addressing of these buffers is done in one of
+ * 3 ways:
+ * - contiguous (for the 3max and turbochannel option card)
+ * - gap2, which means shorts (2 bytes) interspersed with short (2 byte)
+ *   spaces (for the pmax)
+ * - gap16, which means 16bytes interspersed with 16byte spaces
+ *   for buffers which must begin on a 32byte boundary (for 3min, maxine,
+ *   and alpha)
+ * The buffer offset is the logical byte offset, assuming contiguous storage.
+ */
index 2a1fea0..a0c2209 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_le_ioasic.c,v 1.1 1996/04/18 00:50:13 cgd Exp $     */
+/*     $NetBSD: if_le_ioasic.c,v 1.2 1996/05/07 02:24:56 thorpej Exp $ */
 
 /*
  * Copyright (c) 1996 Carnegie-Mellon University.
 #include <netinet/if_ether.h>
 #endif
 
-#include <dev/tc/if_levar.h>
 #include <dev/ic/am7990reg.h>
-#define LE_NEED_BUF_GAP2
-#define LE_NEED_BUF_GAP16
 #include <dev/ic/am7990var.h>
 
+#include <dev/tc/if_levar.h>
 #include <dev/tc/tcvar.h>
 #include <dev/tc/ioasicvar.h>
 
@@ -59,6 +57,17 @@ extern caddr_t le_iomem;
 int    le_ioasic_match __P((struct device *, void *, void *));
 void   le_ioasic_attach __P((struct device *, struct device *, void *));
 
+hide void le_ioasic_copytobuf_gap2 __P((struct am7990_softc *, void *,
+           int, int));
+hide void le_ioasic_copyfrombuf_gap2 __P((struct am7990_softc *, void *,
+           int, int));
+
+hide void le_ioasic_copytobuf_gap16 __P((struct am7990_softc *, void *,
+           int, int));
+hide void le_ioasic_copyfrombuf_gap16 __P((struct am7990_softc *, void *,
+           int, int));
+hide void le_ioasic_zerobuf_gap16 __P((struct am7990_softc *, int, int));
+
 struct cfattach le_ioasic_ca = {
        sizeof(struct le_softc), le_ioasic_match, le_ioasic_attach
 };
@@ -84,21 +93,170 @@ le_ioasic_attach(parent, self, aux)
        void *aux;
 {
        struct ioasicdev_attach_args *d = aux;
-       register struct le_softc *sc = (void *)self;
+       register struct le_softc *lesc = (void *)self;
+       register struct am7990_softc *sc = &lesc->sc_am7990;
 
-       sc->sc_r1 = (struct lereg1 *)
+       lesc->sc_r1 = (struct lereg1 *)
                TC_DENSE_TO_SPARSE(TC_PHYS_TO_UNCACHED(d->iada_addr));
        sc->sc_mem = (void *)TC_PHYS_TO_UNCACHED(le_iomem);
 
-       sc->sc_copytodesc = am7990_copytobuf_gap2;
-       sc->sc_copyfromdesc = am7990_copyfrombuf_gap2;
-       sc->sc_copytobuf = am7990_copytobuf_gap16;
-       sc->sc_copyfrombuf = am7990_copyfrombuf_gap16;
-       sc->sc_zerobuf = am7990_zerobuf_gap16;
+       sc->sc_copytodesc = le_ioasic_copytobuf_gap2;
+       sc->sc_copyfromdesc = le_ioasic_copyfrombuf_gap2;
+       sc->sc_copytobuf = le_ioasic_copytobuf_gap16;
+       sc->sc_copyfrombuf = le_ioasic_copyfrombuf_gap16;
+       sc->sc_zerobuf = le_ioasic_zerobuf_gap16;
 
        ioasic_lance_dma_setup(le_iomem);       /* XXX more thought */
 
        dec_le_common_attach(sc, ioasic_lance_ether_address());
 
-       ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_NET, leintr, sc);
+       ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_NET,
+           am7990_intr, sc);
+}
+
+/*
+ * Special memory access functions needed by ioasic-attached LANCE
+ * chips.
+ */
+
+/*
+ * gap2: two bytes of data followed by two bytes of pad.
+ *
+ * Buffers must be 4-byte aligned.  The code doesn't worry about
+ * doing an extra byte.
+ */
+
+void
+le_ioasic_copytobuf_gap2(sc, fromv, boff, len)
+       struct am7990_softc *sc;  
+       void *fromv;
+       int boff;
+       register int len;
+{
+       volatile caddr_t buf = sc->sc_mem;
+       register caddr_t from = fromv;
+       register volatile u_int16_t *bptr;  
+
+       if (boff & 0x1) {
+               /* handle unaligned first byte */
+               bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+               *bptr = (*from++ << 8) | (*bptr & 0xff);
+               bptr += 2;  
+               len--;
+       } else
+               bptr = ((volatile u_int16_t *)buf) + boff;
+       while (len > 1) {
+               *bptr = (from[1] << 8) | (from[0] & 0xff);
+               bptr += 2;
+               from += 2;
+               len -= 2;
+       }
+       if (len == 1)
+               *bptr = (u_int16_t)*from;
+}
+
+void
+le_ioasic_copyfrombuf_gap2(sc, tov, boff, len)
+       struct am7990_softc *sc;
+       void *tov;
+       int boff, len;
+{
+       volatile caddr_t buf = sc->sc_mem;
+       register caddr_t to = tov;
+       register volatile u_int16_t *bptr;
+       register u_int16_t tmp;
+
+       if (boff & 0x1) {
+               /* handle unaligned first byte */
+               bptr = ((volatile u_int16_t *)buf) + (boff - 1);
+               *to++ = (*bptr >> 8) & 0xff;
+               bptr += 2;
+               len--;
+       } else
+               bptr = ((volatile u_int16_t *)buf) + boff;
+       while (len > 1) {
+               tmp = *bptr;
+               *to++ = tmp & 0xff;
+               *to++ = (tmp >> 8) & 0xff;
+               bptr += 2;
+               len -= 2;
+       }
+       if (len == 1)
+               *to = *bptr & 0xff;
+}
+
+/*
+ * gap16: 16 bytes of data followed by 16 bytes of pad.
+ *
+ * Buffers must be 32-byte aligned.
+ */
+
+void
+le_ioasic_copytobuf_gap16(sc, fromv, boff, len)
+       struct am7990_softc *sc;
+       void *fromv;
+       int boff;
+       register int len;
+{
+       volatile caddr_t buf = sc->sc_mem;
+       register caddr_t from = fromv;
+       register caddr_t bptr;
+       register int xfer;
+
+       bptr = buf + ((boff << 1) & ~0x1f);
+       boff &= 0xf;
+       xfer = min(len, 16 - boff);
+       while (len > 0) {
+               bcopy(from, bptr + boff, xfer);
+               from += xfer;
+               bptr += 32;
+               boff = 0;
+               len -= xfer;
+               xfer = min(len, 16);
+       }
+}
+
+void
+le_ioasic_copyfrombuf_gap16(sc, tov, boff, len)
+       struct am7990_softc *sc;
+       void *tov;
+       int boff, len;
+{
+       volatile caddr_t buf = sc->sc_mem;
+       register caddr_t to = tov;
+       register caddr_t bptr;
+       register int xfer;
+
+       bptr = buf + ((boff << 1) & ~0x1f);
+       boff &= 0xf;
+       xfer = min(len, 16 - boff);
+       while (len > 0) {
+               bcopy(bptr + boff, to, xfer);
+               to += xfer;
+               bptr += 32;
+               boff = 0;
+               len -= xfer;
+               xfer = min(len, 16);
+       }
+}
+
+void
+le_ioasic_zerobuf_gap16(sc, boff, len)
+       struct am7990_softc *sc;
+       int boff, len;
+{
+       volatile caddr_t buf = sc->sc_mem;
+       register caddr_t bptr;
+       register int xfer;
+
+       bptr = buf + ((boff << 1) & ~0x1f);
+       boff &= 0xf;
+       xfer = min(len, 16 - boff);
+       while (len > 0) {
+               bzero(bptr + boff, xfer);
+               bptr += 32;
+               boff = 0;
+               len -= xfer;
+               xfer = min(len, 16);
+       }
 }
index 194a5e3..e329a3d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_le_tc.c,v 1.1 1996/04/18 00:50:14 cgd Exp $ */
+/*     $NetBSD: if_le_tc.c,v 1.2 1996/05/07 02:24:57 thorpej Exp $     */
 
 /*
  * Copyright (c) 1996 Carnegie-Mellon University.
 #include <netinet/if_ether.h>
 #endif
 
-#include <dev/tc/if_levar.h>
 #include <dev/ic/am7990reg.h>
-#define LE_NEED_BUF_CONTIG
 #include <dev/ic/am7990var.h>
 
+#include <dev/tc/if_levar.h>
 #include <dev/tc/tcvar.h>
 
 int    le_tc_match __P((struct device *, void *, void *));
@@ -82,14 +81,15 @@ le_tc_attach(parent, self, aux)
        struct device *parent, *self;
        void *aux;
 {
-       register struct le_softc *sc = (void *)self;
+       register struct le_softc *lesc = (void *)self;
+       register struct am7990_softc *sc = &lesc->sc_am7990;
        struct tc_attach_args *d = aux;
 
        /*
         * It's on the turbochannel proper, or a kn02
         * baseboard implementation of a TC option card.
         */
-       sc->sc_r1 = (struct lereg1 *)(d->ta_addr + LE_OFFSET_LANCE);
+       lesc->sc_r1 = (struct lereg1 *)(d->ta_addr + LE_OFFSET_LANCE);
        sc->sc_mem = (void *)(d->ta_addr + LE_OFFSET_RAM);
 
        sc->sc_copytodesc = am7990_copytobuf_contig;
@@ -106,5 +106,5 @@ le_tc_attach(parent, self, aux)
 
        dec_le_common_attach(sc, (u_char *)(d->ta_addr + LE_OFFSET_ROM + 2));
 
-       tc_intr_establish(parent, d->ta_cookie, TC_IPL_NET, leintr, sc);
+       tc_intr_establish(parent, d->ta_cookie, TC_IPL_NET, am7990_intr, sc);
 }
index 5d6f0c4..a818067 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_levar.h,v 1.2 1996/04/18 00:50:15 cgd Exp $ */
+/*     $NetBSD: if_levar.h,v 1.3 1996/05/07 02:24:58 thorpej Exp $     */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -60,44 +60,9 @@ struct lereg1 {
  * This structure contains the output queue for the interface, its address, ...
  */
 struct le_softc {
-       struct  device sc_dev;          /* base structure */
-       struct  arpcom sc_arpcom;       /* Ethernet common part */
-
-       void    (*sc_copytodesc)        /* Copy to descriptor */
-                   __P((struct le_softc *, void *, int, int));
-       void    (*sc_copyfromdesc)      /* Copy from descriptor */
-                   __P((struct le_softc *, void *, int, int));
-
-       void    (*sc_copytobuf)         /* Copy to buffer */
-                   __P((struct le_softc *, void *, int, int));
-       void    (*sc_copyfrombuf)       /* Copy from buffer */
-                   __P((struct le_softc *, void *, int, int));
-       void    (*sc_zerobuf)           /* and Zero bytes in buffer */
-                   __P((struct le_softc *, int, int));
-
-       u_int16_t sc_conf3;             /* CSR3 value */
-
-       void    *sc_mem;                /* base addr of RAM -- CPU's view */
-       u_long  sc_addr;                /* base addr of RAM -- LANCE's view */
-       u_long  sc_memsize;             /* size of RAM */
-
-       int     sc_nrbuf;               /* number of receive buffers */
-       int     sc_ntbuf;               /* number of transmit buffers */
-       int     sc_last_rd;
-       int     sc_first_td, sc_last_td, sc_no_td;
-
-       int     sc_initaddr;
-       int     sc_rmdaddr;
-       int     sc_tmdaddr;
-       int     sc_rbufaddr;
-       int     sc_tbufaddr;
-
-#ifdef LEDEBUG
-       int     sc_debug;
-#endif
+       struct  am7990_softc sc_am7990; /* glue to MI code */
 
        struct  lereg1 *sc_r1;          /* LANCE registers */
 };
 
-int    leintr __P((void *));
-void   dec_le_common_attach __P((struct le_softc *, u_char *));
+void   dec_le_common_attach __P((struct am7990_softc *, u_char *));