merge latest Utah hp300 code including 68040 support
[unix-history] / usr / src / sys / hp300 / dev / if_le.c
index e03705e..fc168a4 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)if_le.c     7.5 (Berkeley) %G%
+ *     @(#)if_le.c     7.11 (Berkeley) %G%
  */
 
 #include "le.h"
  */
 
 #include "le.h"
@@ -21,6 +21,7 @@
  * This reasoning is dubious.
  */
 #include "sys/param.h"
  * This reasoning is dubious.
  */
 #include "sys/param.h"
+#include "sys/proc.h"
 #include "sys/systm.h"
 #include "sys/mbuf.h"
 #include "sys/buf.h"
 #include "sys/systm.h"
 #include "sys/mbuf.h"
 #include "sys/buf.h"
 #include "netns/ns_if.h"
 #endif
 
 #include "netns/ns_if.h"
 #endif
 
-#ifdef RMP
-#include "netrmp/rmp.h"
-#include "netrmp/rmp_var.h"
+#ifdef ISO
+extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];
 #endif
 
 #include "../include/cpu.h"
 #include "../hp300/isr.h"
 #include "../include/mtpr.h"
 #endif
 
 #include "../include/cpu.h"
 #include "../hp300/isr.h"
 #include "../include/mtpr.h"
-#include "device.h"
+#include "hp/dev/device.h"
 #include "if_lereg.h"
 
 #if NBPFILTER > 0
 #include "../net/bpf.h"
 #include "../net/bpfdesc.h"
 #include "if_lereg.h"
 
 #if NBPFILTER > 0
 #include "../net/bpf.h"
 #include "../net/bpfdesc.h"
+char hprmp_multi[] = { 9, 0, 9, 0, 0, 4};
 #endif
 
 /* offsets for:           ID,   REGS,    MEM,  NVRAM */
 #endif
 
 /* offsets for:           ID,   REGS,    MEM,  NVRAM */
@@ -75,7 +76,7 @@ struct        isr le_isr[NLE];
 int    ledebug = 0;            /* console error messages */
 
 int    leintr(), leinit(), leioctl(), lestart(), ether_output();
 int    ledebug = 0;            /* console error messages */
 
 int    leintr(), leinit(), leioctl(), lestart(), ether_output();
-struct mbuf *leget();
+struct mbuf *m_devget();
 extern struct ifnet loif;
 
 /*
 extern struct ifnet loif;
 
 /*
@@ -93,23 +94,25 @@ struct      le_softc {
        struct  lereg1 *sc_r1;  /* LANCE registers */
        struct  lereg2 *sc_r2;  /* dual-port RAM */
        int     sc_rmd;         /* predicted next rmd to process */
        struct  lereg1 *sc_r1;  /* LANCE registers */
        struct  lereg2 *sc_r2;  /* dual-port RAM */
        int     sc_rmd;         /* predicted next rmd to process */
+       int     sc_tmd;         /* next available tmd */
+       int     sc_txcnt;       /* # of transmit buffers in use */
+       /* stats */
        int     sc_runt;
        int     sc_jab;
        int     sc_merr;
        int     sc_babl;
        int     sc_cerr;
        int     sc_miss;
        int     sc_runt;
        int     sc_jab;
        int     sc_merr;
        int     sc_babl;
        int     sc_cerr;
        int     sc_miss;
-       int     sc_xint;
+       int     sc_rown;
        int     sc_xown;
        int     sc_xown;
+       int     sc_xown2;
        int     sc_uflo;
        int     sc_rxlen;
        int     sc_rxoff;
        int     sc_txoff;
        int     sc_busy;
        short   sc_iflags;
        int     sc_uflo;
        int     sc_rxlen;
        int     sc_rxoff;
        int     sc_txoff;
        int     sc_busy;
        short   sc_iflags;
-#if NBPFILTER > 0
        caddr_t sc_bpf;
        caddr_t sc_bpf;
-#endif
 } le_softc[NLE];
 
 /* access LANCE registers */
 } le_softc[NLE];
 
 /* access LANCE registers */
@@ -162,19 +165,9 @@ leattach(hd)
         * Setup for transmit/receive
         */
        ler2->ler2_mode = LE_MODE;
         * Setup for transmit/receive
         */
        ler2->ler2_mode = LE_MODE;
-       ler2->ler2_padr[0] = le->sc_addr[1];
-       ler2->ler2_padr[1] = le->sc_addr[0];
-       ler2->ler2_padr[2] = le->sc_addr[3];
-       ler2->ler2_padr[3] = le->sc_addr[2];
-       ler2->ler2_padr[4] = le->sc_addr[5];
-       ler2->ler2_padr[5] = le->sc_addr[4];
-#ifdef RMP
-       /*
-        * Set up logical addr filter to accept multicast 9:0:9:0:0:4
-        * This should be an ioctl() to the driver.  (XXX)
-        */
-       ler2->ler2_ladrf0 = 0x00100000;
-       ler2->ler2_ladrf1 = 0x0;
+#if defined(ISO) || NBPFILTER > 0
+       ler2->ler2_ladrf0 = 0xffffffff;
+       ler2->ler2_ladrf1 = 0xffffffff;
 #else
        ler2->ler2_ladrf0 = 0;
        ler2->ler2_ladrf1 = 0;
 #else
        ler2->ler2_ladrf0 = 0;
        ler2->ler2_ladrf1 = 0;
@@ -195,23 +188,25 @@ leattach(hd)
        ifp->if_start = lestart;
        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
 #if NBPFILTER > 0
        ifp->if_start = lestart;
        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
 #if NBPFILTER > 0
-       {
-               static struct bpf_devp dev =
-                       { DLT_EN10MB, sizeof(struct ether_header) };
-
-               bpfattach(&le->sc_bpf, ifp, &dev);
-        }
+       bpfattach(&le->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
 #endif
        if_attach(ifp);
        return (1);
 }
 
 #endif
        if_attach(ifp);
        return (1);
 }
 
-ledrinit(ler2)
+ledrinit(ler2, le)
        register struct lereg2 *ler2;
        register struct lereg2 *ler2;
+       register struct le_softc *le;
 {
        register struct lereg2 *lemem = 0;
        register int i;
 
 {
        register struct lereg2 *lemem = 0;
        register int i;
 
+       ler2->ler2_padr[0] = le->sc_addr[1];
+       ler2->ler2_padr[1] = le->sc_addr[0];
+       ler2->ler2_padr[2] = le->sc_addr[3];
+       ler2->ler2_padr[3] = le->sc_addr[2];
+       ler2->ler2_padr[4] = le->sc_addr[5];
+       ler2->ler2_padr[5] = le->sc_addr[4];
        for (i = 0; i < LERBUF; i++) {
                ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
                ler2->ler2_rmd[i].rmd1 = LE_OWN;
        for (i = 0; i < LERBUF; i++) {
                ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
                ler2->ler2_rmd[i].rmd1 = LE_OWN;
@@ -248,8 +243,8 @@ lereset(unit)
 #endif
        LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
        LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
 #endif
        LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
        LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
-       ledrinit(le->sc_r2);
-       le->sc_rmd = 0;
+       ledrinit(le->sc_r2, le);
+       le->sc_rmd = le->sc_tmd = 0;
        LERDWR(ler0, LE_CSR1, ler1->ler1_rap);
        LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);
        LERDWR(ler0, LE_CSR2, ler1->ler1_rap);
        LERDWR(ler0, LE_CSR1, ler1->ler1_rap);
        LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);
        LERDWR(ler0, LE_CSR2, ler1->ler1_rap);
@@ -270,6 +265,7 @@ lereset(unit)
        LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
        LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);
        le->sc_if.if_flags &= ~IFF_OACTIVE;
        LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
        LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);
        le->sc_if.if_flags &= ~IFF_OACTIVE;
+       le->sc_txcnt = 0;
 }
 
 /*
 }
 
 /*
@@ -278,13 +274,16 @@ lereset(unit)
 leinit(unit)
        int unit;
 {
 leinit(unit)
        int unit;
 {
-       struct le_softc *le = &le_softc[unit];
-       register struct ifnet *ifp = &le->sc_if;
+       register struct ifnet *ifp = &le_softc[unit].sc_if;
+       register struct ifaddr *ifa;
        int s;
 
        /* not yet, if address still unknown */
        int s;
 
        /* not yet, if address still unknown */
-       if (ifp->if_addrlist == (struct ifaddr *)0)
-               return;
+       for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next)
+               if (ifa == 0)
+                       return;
+               else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK)
+                       break;
        if ((ifp->if_flags & IFF_RUNNING) == 0) {
                s = splimp();
                ifp->if_flags |= IFF_RUNNING;
        if ((ifp->if_flags & IFF_RUNNING) == 0) {
                s = splimp();
                ifp->if_flags |= IFF_RUNNING;
@@ -309,22 +308,35 @@ lestart(ifp)
 
        if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
                return (0);
 
        if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
                return (0);
-       IF_DEQUEUE(&le->sc_if.if_snd, m);
-       if (m == 0)
-               return (0);
-       len = leput(le->sc_r2->ler2_tbuf[0], m);
+       tmd = &le->sc_r2->ler2_tmd[le->sc_tmd];
+       do {
+               if (tmd->tmd1 & LE_OWN) {
+                       le->sc_xown2++;
+                       return (0);
+               }
+               IF_DEQUEUE(&le->sc_if.if_snd, m);
+               if (m == 0)
+                       return (0);
+               len = leput(le->sc_r2->ler2_tbuf[le->sc_tmd], m);
 #if NBPFILTER > 0
 #if NBPFILTER > 0
-       /*
-        * If bpf is listening on this interface, let it
-        * see the packet before we commit it to the wire.
-        */
-       if (le->sc_bpf)
-                bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[0], len);
+               /* 
+                * If bpf is listening on this interface, let it 
+                * see the packet before we commit it to the wire.
+                */
+               if (le->sc_bpf)
+                       bpf_tap(le->sc_bpf, le->sc_r2->ler2_tbuf[le->sc_tmd],
+                               len);
 #endif
 #endif
-       tmd = le->sc_r2->ler2_tmd;
-       tmd->tmd3 = 0;
-       tmd->tmd2 = -len;
-       tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
+
+               tmd->tmd3 = 0;
+               tmd->tmd2 = -len;
+               tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
+               if (++le->sc_tmd == LETBUF) {
+                       le->sc_tmd = 0;
+                       tmd = le->sc_r2->ler2_tmd;
+               } else
+                       tmd++;
+       } while (++le->sc_txcnt < LETBUF);
        le->sc_if.if_flags |= IFF_OACTIVE;
        return (0);
 }
        le->sc_if.if_flags |= IFF_OACTIVE;
        return (0);
 }
@@ -371,14 +383,10 @@ leintr(unit)
                lereset(unit);
                return(1);
        }
                lereset(unit);
                return(1);
        }
-       if (stat & LE_RINT) {
-               /* interrupt is cleared in lerint */
+       if (stat & LE_RINT)
                lerint(unit);
                lerint(unit);
-       }
-       if (stat & LE_TINT) {
-               LERDWR(ler0, LE_TINT|LE_INEA, ler1->ler1_rdp);
+       if (stat & LE_TINT)
                lexint(unit);
                lexint(unit);
-       }
        return(1);
 }
 
        return(1);
 }
 
@@ -390,39 +398,43 @@ lexint(unit)
        register int unit;
 {
        register struct le_softc *le = &le_softc[unit];
        register int unit;
 {
        register struct le_softc *le = &le_softc[unit];
-       register struct letmd *tmd = le->sc_r2->ler2_tmd;
+       register struct letmd *tmd;
+       int i, gotone = 0;
 
 
-       if ((le->sc_if.if_flags & IFF_OACTIVE) == 0) {
-               le->sc_xint++;
-               return;
-       }
-       if (tmd->tmd1 & LE_OWN) {
-               le->sc_xown++;
-               return;
-       }
-       if (tmd->tmd1 & LE_ERR) {
-err:
-               lexerror(unit);
-               le->sc_if.if_oerrors++;
-               if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
-                       le->sc_uflo++;
-                       lereset(unit);
+       do {
+               if ((i = le->sc_tmd - le->sc_txcnt) < 0)
+                       i += LETBUF;
+               tmd = &le->sc_r2->ler2_tmd[i];
+               if (tmd->tmd1 & LE_OWN) {
+                       if (gotone)
+                               break;
+                       le->sc_xown++;
+                       return;
                }
                }
-               else if (tmd->tmd3 & LE_LCOL)
-                       le->sc_if.if_collisions++;
-               else if (tmd->tmd3 & LE_RTRY)
-                       le->sc_if.if_collisions += 16;
-       }
-       else if (tmd->tmd3 & LE_TBUFF)
+
+               /* clear interrupt */
+               LERDWR(le->sc_r0, LE_TINT|LE_INEA, le->sc_r1->ler1_rdp);
+
                /* XXX documentation says BUFF not included in ERR */
                /* XXX documentation says BUFF not included in ERR */
-               goto err;
-       else if (tmd->tmd1 & LE_ONE)
-               le->sc_if.if_collisions++;
-       else if (tmd->tmd1 & LE_MORE)
-               /* what is the real number? */
-               le->sc_if.if_collisions += 2;
-       else
-               le->sc_if.if_opackets++;
+               if ((tmd->tmd1 & LE_ERR) || (tmd->tmd3 & LE_TBUFF)) {
+                       lexerror(unit);
+                       le->sc_if.if_oerrors++;
+                       if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
+                               le->sc_uflo++;
+                               lereset(unit);
+                       } else if (tmd->tmd3 & LE_LCOL)
+                               le->sc_if.if_collisions++;
+                       else if (tmd->tmd3 & LE_RTRY)
+                               le->sc_if.if_collisions += 16;
+               } else if (tmd->tmd1 & LE_ONE)
+                       le->sc_if.if_collisions++;
+               else if (tmd->tmd1 & LE_MORE)
+                       /* what is the real number? */
+                       le->sc_if.if_collisions += 2;
+               else
+                       le->sc_if.if_opackets++;
+               gotone++;
+       } while (--le->sc_txcnt > 0);
        le->sc_if.if_flags &= ~IFF_OACTIVE;
        (void) lestart(&le->sc_if);
 }
        le->sc_if.if_flags &= ~IFF_OACTIVE;
        (void) lestart(&le->sc_if);
 }
@@ -447,6 +459,7 @@ lerint(unit)
         * Out of sync with hardware, should never happen?
         */
        if (rmd->rmd1 & LE_OWN) {
         * Out of sync with hardware, should never happen?
         */
        if (rmd->rmd1 & LE_OWN) {
+               le->sc_rown++;
                LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
                return;
        }
                LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
                return;
        }
@@ -513,26 +526,6 @@ leread(unit, buf, len)
        /* adjust input length to account for header and CRC */
        len = len - sizeof(struct ether_header) - 4;
 
        /* adjust input length to account for header and CRC */
        len = len - sizeof(struct ether_header) - 4;
 
-#ifdef RMP
-       /*  (XXX)
-        *
-        *  If Ethernet Type field is < MaxPacketSize, we probably have
-        *  a IEEE802 packet here.  Make sure that the size is at least
-        *  that of the HP LLC.  Also do sanity checks on length of LLC
-        *  (old Ethernet Type field) and packet length.
-        *
-        *  Provided the above checks succeed, change `len' to reflect
-        *  the length of the LLC (i.e. et->ether_type) and change the
-        *  type field to ETHERTYPE_IEEE so we can switch() on it later.
-        *  Yes, this is a hack and will eventually be done "right".
-        */
-       if (et->ether_type <= IEEE802LEN_MAX && len >= sizeof(struct hp_llc) &&
-           len >= et->ether_type && len >= IEEE802LEN_MIN) {
-               len = et->ether_type;
-               et->ether_type = ETHERTYPE_IEEE;        /* hack! */
-       }
-#endif
-
 #define        ledataaddr(et, off, type)       ((type)(((caddr_t)((et)+1)+(off))))
        if (et->ether_type >= ETHERTYPE_TRAIL &&
            et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
 #define        ledataaddr(et, off, type)       ((type)(((caddr_t)((et)+1)+(off))))
        if (et->ether_type >= ETHERTYPE_TRAIL &&
            et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
@@ -562,63 +555,36 @@ leread(unit, buf, len)
         * If so, hand off the raw packet to bpf, which must deal with
         * trailers in its own way.
         */
         * If so, hand off the raw packet to bpf, which must deal with
         * trailers in its own way.
         */
-       if (le->sc_bpf) {
+       if (le->sc_bpf)
                bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
                bpf_tap(le->sc_bpf, buf, len + sizeof(struct ether_header));
-
-               /*
-                * Note that the interface cannot be in promiscuous mode if
-                * there are no bpf listeners.  And if we are in promiscuous
-                * mode, we have to check if this packet is really ours.
-                *
-                * XXX This test does not support multicasts.
-                */
-               if ((le->sc_if.if_flags & IFF_PROMISC)
-                   && bcmp(et->ether_dhost, le->sc_addr, 
-                           sizeof(et->ether_dhost)) != 0
-                   && bcmp(et->ether_dhost, etherbroadcastaddr, 
-                           sizeof(et->ether_dhost)) != 0)
-                       return;
-       }
+#endif
+#if defined(ISO) || NBPFILTER > 0
+       /*
+        * Note that the interface cannot be in promiscuous mode if
+        * there are no bpf listeners.  If we are in promiscuous
+        * mode, we have to check if this packet is really ours.
+        * However, there may be appropriate multicate addresses involved
+        */
+#define NOT_TO(p) (bcmp(et->ether_dhost, p, sizeof(et->ether_dhost)) != 0)
+       if (et->ether_dhost[0] & 1) {
+               if (NOT_TO(etherbroadcastaddr) && NOT_TO(hprmp_multi)
+#ifdef ISO
+                   && NOT_TO(all_es_snpa) && NOT_TO(all_is_snpa)
+                   && NOT_TO(all_l1is_snpa) && NOT_TO(all_l2is_snpa)
+#endif
+                    ) return;
+       } else if ((le->sc_if.if_flags & IFF_PROMISC) && NOT_TO(le->sc_addr))
+               return;
 #endif
        /*
         * Pull packet off interface.  Off is nonzero if packet
 #endif
        /*
         * Pull packet off interface.  Off is nonzero if packet
-        * has trailing header; leget will then force this header
+        * has trailing header; m_devget will then force this header
         * information to be at the front, but we still have to drop
         * the type and length which are at the front of any trailer data.
         */
         * information to be at the front, but we still have to drop
         * the type and length which are at the front of any trailer data.
         */
-       m = leget(buf, len, off, &le->sc_if);
+       m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0);
        if (m == 0)
                return;
        if (m == 0)
                return;
-#ifdef RMP
-       /*
-        * (XXX)
-        * This needs to be integrated with the ISO stuff in ether_input()
-        */
-       if (et->ether_type == ETHERTYPE_IEEE) {
-               /*
-                *  Snag the Logical Link Control header (IEEE 802.2).
-                */
-               struct hp_llc *llc = &(mtod(m, struct rmp_packet *)->hp_llc);
-
-               /*
-                *  If the DSAP (and HP's extended DXSAP) indicate this
-                *  is an RMP packet, hand it to the raw input routine.
-                */
-               if (llc->dsap == IEEE_DSAP_HP && llc->dxsap == HPEXT_DXSAP) {
-                       static struct sockproto rmp_sp = {AF_RMP,RMPPROTO_BOOT};
-                       static struct sockaddr rmp_src = {AF_RMP};
-                       static struct sockaddr rmp_dst = {AF_RMP};
-
-                       bcopy(et->ether_shost, rmp_src.sa_data,
-                             sizeof(et->ether_shost));
-                       bcopy(et->ether_dhost, rmp_dst.sa_data,
-                             sizeof(et->ether_dhost));
-
-                       raw_input(m, &rmp_sp, &rmp_src, &rmp_dst);
-                       return;
-               }
-       }
-#endif
        ether_input(&le->sc_if, et, m);
 }
 
        ether_input(&le->sc_if, et, m);
 }
 
@@ -649,74 +615,6 @@ leput(lebuf, m)
        return(tlen);
 }
 
        return(tlen);
 }
 
-/*
- * Routine to copy from board local memory into mbufs.
- */
-struct mbuf *
-leget(lebuf, totlen, off0, ifp)
-       char *lebuf;
-       int totlen, off0;
-       struct ifnet *ifp;
-{
-       register struct mbuf *m;
-       struct mbuf *top = 0, **mp = &top;
-       register int off = off0, len;
-       register char *cp;
-       char *epkt;
-
-       lebuf += sizeof (struct ether_header);
-       cp = lebuf;
-       epkt = cp + totlen;
-       if (off) {
-               cp += off + 2 * sizeof(u_short);
-               totlen -= 2 * sizeof(u_short);
-       }
-
-       MGETHDR(m, M_DONTWAIT, MT_DATA);
-       if (m == 0)
-               return (0);
-       m->m_pkthdr.rcvif = ifp;
-       m->m_pkthdr.len = totlen;
-       m->m_len = MHLEN;
-
-       while (totlen > 0) {
-               if (top) {
-                       MGET(m, M_DONTWAIT, MT_DATA);
-                       if (m == 0) {
-                               m_freem(top);
-                               return (0);
-                       }
-                       m->m_len = MLEN;
-               }
-               len = min(totlen, epkt - cp);
-               if (len >= MINCLSIZE) {
-                       MCLGET(m, M_DONTWAIT);
-                       if (m->m_flags & M_EXT)
-                               m->m_len = len = min(len, MCLBYTES);
-                       else
-                               len = m->m_len;
-               } else {
-                       /*
-                        * Place initial small packet/header at end of mbuf.
-                        */
-                       if (len < m->m_len) {
-                               if (top == 0 && len + max_linkhdr <= m->m_len)
-                                       m->m_data += max_linkhdr;
-                               m->m_len = len;
-                       } else
-                               len = m->m_len;
-               }
-               bcopy(cp, mtod(m, caddr_t), (unsigned)len);
-               cp += len;
-               *mp = m;
-               mp = &m->m_next;
-               totlen -= len;
-               if (cp == epkt)
-                       cp = lebuf;
-       }
-       return (top);
-}
-
 /*
  * Process an ioctl request.
  */
 /*
  * Process an ioctl request.
  */
@@ -757,6 +655,7 @@ leioctl(ifp, cmd, data)
                                 * so reset everything
                                 */
                                ifp->if_flags &= ~IFF_RUNNING; 
                                 * so reset everything
                                 */
                                ifp->if_flags &= ~IFF_RUNNING; 
+                               LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
                                bcopy((caddr_t)ina->x_host.c_host,
                                    (caddr_t)le->sc_addr, sizeof(le->sc_addr));
                        }
                                bcopy((caddr_t)ina->x_host.c_host,
                                    (caddr_t)le->sc_addr, sizeof(le->sc_addr));
                        }
@@ -832,7 +731,9 @@ lererror(unit, msg)
        log(LOG_WARNING,
            "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
            unit, msg,
        log(LOG_WARNING,
            "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
            unit, msg,
-           len > 11 ? ether_sprintf(&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : "unknown",
+           len > 11 ?
+               ether_sprintf((u_char *)&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) :
+               "unknown",
            le->sc_rmd, len,
            rmd->rmd1,
            "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
            le->sc_rmd, len,
            rmd->rmd1,
            "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
@@ -853,7 +754,9 @@ lexerror(unit)
        log(LOG_WARNING,
            "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
            unit,
        log(LOG_WARNING,
            "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
            unit,
-           len > 5 ? ether_sprintf(&le->sc_r2->ler2_tbuf[0][0]) : "unknown",
+           len > 5 ?
+               ether_sprintf((u_char *)&le->sc_r2->ler2_tbuf[0][0]) :
+               "unknown",
            0, len,
            tmd->tmd1,
            "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
            0, len,
            tmd->tmd1,
            "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",