new mbufs (enp tested, ace not)
[unix-history] / usr / src / sys / tahoe / if / if_ace.c
index 7ac02fb..6305aec 100644 (file)
@@ -1,4 +1,24 @@
-/*     if_ace.c        1.4     86/01/20        */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Computer Consoles Inc.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)if_ace.c    7.3 (Berkeley) %G%
+ */
 
 /*
  * ACC VERSAbus Ethernet controller
 
 /*
  * ACC VERSAbus Ethernet controller
@@ -6,10 +26,9 @@
 #include "ace.h"
 #if NACE > 0
 
 #include "ace.h"
 #if NACE > 0
 
-#include "../machine/pte.h"
-
 #include "param.h"
 #include "systm.h"
 #include "param.h"
 #include "systm.h"
+#include "malloc.h"
 #include "mbuf.h"
 #include "buf.h"
 #include "protosw.h"
 #include "mbuf.h"
 #include "buf.h"
 #include "protosw.h"
 #include "../netns/ns_if.h"
 #endif
 
 #include "../netns/ns_if.h"
 #endif
 
+#include "../machine/cpu.h"
+#include "../machine/pte.h"
+
 #include "../tahoe/mtpr.h"
 #include "../tahoeif/if_acereg.h"
 #include "../tahoevba/vbavar.h"
 
 #include "../tahoe/mtpr.h"
 #include "../tahoeif/if_acereg.h"
 #include "../tahoevba/vbavar.h"
 
-/* station address */
-char   ace_station[6] = { ~0x8, ~0x0, ~0x3, ~0x0, ~0x0, ~0x1 };
-/* multicast hash table initializer */
-char   ace_hash[8] = { ~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF,~0xF };
-/* backoff table masks */
-short random_mask_tbl[16] = {
-       0x0040, 0x00C0, 0x01C0, 0x03C0, 0x07C0, 0x0FC0, 0x1FC0, 0x3FC0,
-       0x7FC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0, 0xFFC0
-};
-
-int    aceprobe(), aceattach(), acerint(), acecint();
+int    aceprobe(), aceattach(), acerint(), acecint(), acestart();
 struct vba_device *aceinfo[NACE];
 struct vba_device *aceinfo[NACE];
-long   acestd[] = { 0x0ff0000, 0xff0100, 0 };
+long   acestd[] = { 0 };
 struct vba_driver acedriver =
     { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };
 
 struct vba_driver acedriver =
     { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };
 
@@ -97,6 +109,7 @@ aceprobe(reg, vi)
        struct ace_softc *is = &ace_softc[vi->ui_unit];
 
 #ifdef lint
        struct ace_softc *is = &ace_softc[vi->ui_unit];
 
 #ifdef lint
+       br = 0; cvec = br; br = cvec;
        acerint(0); acecint(0);
 #endif
        if (badaddr(reg, 2))
        acerint(0); acecint(0);
 #endif
        if (badaddr(reg, 2))
@@ -133,53 +146,41 @@ aceattach(ui)
        register struct ifnet *ifp = &is->is_if;
        register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        register short *wp, i;
        register struct ifnet *ifp = &is->is_if;
        register struct acedevice *addr = (struct acedevice *)ui->ui_addr;
        register short *wp, i;
+       extern enoutput();
 
        ifp->if_unit = unit;
        ifp->if_name = "ace";
        ifp->if_mtu = ETHERMTU;
        /*
 
        ifp->if_unit = unit;
        ifp->if_name = "ace";
        ifp->if_mtu = ETHERMTU;
        /*
-        * Set station's addresses and multicast hash table.
+        * Get station's addresses and set multicast hash table.
         */
         */
-       ace_station[5] = ~(unit + 1);
-       acesetetaddr(unit, addr, ace_station);
+       for (wp = (short *)addr->station, i = 0; i < 6; i++)
+               is->is_addr[i] = ~*wp++;
+       printf("ace%d: hardware address %s\n", unit,
+           ether_sprintf(is->is_addr));
        is->is_promiscuous = 0;
        is->is_promiscuous = 0;
-       wp = (short *)addr->hash;
-       for (i =  0; i < 8; i++)
-               movow(wp++, ace_hash[i]); 
+       for (wp = (short *)addr->hash, i =  0; i < 8; i++)
+               movow(wp++, ~0xf); 
        movow(&addr->bcastena[0], ~0xffff); 
        movow(&addr->bcastena[1], ~0xffff);
        /*
         * Allocate and map dual ported VERSAbus memory.
         */
        movow(&addr->bcastena[0], ~0xffff); 
        movow(&addr->bcastena[1], ~0xffff);
        /*
         * Allocate and map dual ported VERSAbus memory.
         */
-       vbmemalloc(32, (caddr_t)ui->ui_flags, &is->is_map, &is->is_dpm);
+       if (vbmemalloc(32, (caddr_t)ui->ui_flags,
+           &is->is_map, &is->is_dpm) == 0) {
+               printf("ace%d: can't allocate VERSAbus memory map\n", unit);
+               return;
+       }
 
        ifp->if_init = aceinit;
 
        ifp->if_init = aceinit;
-       ifp->if_output = aceoutput;
+       ifp->if_output = enoutput;
+       ifp->if_start = acestart;
        ifp->if_ioctl = aceioctl;
        ifp->if_reset = acereset;
        ifp->if_ioctl = aceioctl;
        ifp->if_reset = acereset;
-       ifp->if_flags = IFF_BROADCAST;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
        if_attach(ifp);
 }
 
        if_attach(ifp);
 }
 
-acesetetaddr(unit, addr, station_addr)
-       short unit;
-       struct acedevice *addr;
-       char *station_addr;
-{
-       register short *wp, i;
-       register char *cp;
-       struct ace_softc *is = &ace_softc[unit];
-
-       wp = (short *)addr->station;
-       cp = station_addr;
-       for (i = 0; i < 6; i++)
-               movow(wp++, *cp++); 
-       wp = (short *)addr->station;
-       cp = (char *)is->is_addr;
-       for (i = 0; i < 6; i++)
-               *cp++ = ~(*wp++);
-}
-
 /*
  * Reset of interface after "system" reset.
  */
 /*
  * Reset of interface after "system" reset.
  */
@@ -204,13 +205,12 @@ aceinit(unit)
        register struct ace_softc *is = &ace_softc[unit];
        register struct vba_device *ui = aceinfo[unit];
        register struct acedevice *addr;
        register struct ace_softc *is = &ace_softc[unit];
        register struct vba_device *ui = aceinfo[unit];
        register struct acedevice *addr;
-       register struct ifnet *ifp = &is->is_if;
        register short Csr;
        register int s;
 
        register short Csr;
        register int s;
 
-       if (ifp->if_addrlist == (struct ifaddr *)0)
+       if (is->is_if.if_addrlist == (struct ifaddr *)0)
                return;
                return;
-       if ((ifp->if_flags & IFF_RUNNING) == 0) {
+       if ((is->is_if.if_flags & IFF_RUNNING) == 0) {
                /*
                 * Reset the controller, initialize the recieve buffers,
                 * and turn the controller on again and set board online.
                /*
                 * Reset the controller, initialize the recieve buffers,
                 * and turn the controller on again and set board online.
@@ -238,43 +238,39 @@ aceinit(unit)
                splx(s);
        }
        if (is->is_if.if_snd.ifq_head)
                splx(s);
        }
        if (is->is_if.if_snd.ifq_head)
-               acestart(unit);
+               acestart(&is->is_if);
 }
 
 /*
  * Start output on interface.
  * Get another datagram to send off of the interface queue,
  * and map it to the interface before starting the output.
 }
 
 /*
  * Start output on interface.
  * Get another datagram to send off of the interface queue,
  * and map it to the interface before starting the output.
- *
  */
  */
-acestart(unit)
-       int unit;
+acestart(ifp)
+       register struct ifnet *ifp;
 {
        register struct tx_segment *txs;
        register long len;
        register int s;
 {
        register struct tx_segment *txs;
        register long len;
        register int s;
-       register struct ace_softc *is = &ace_softc[unit];
        struct mbuf *m;
        short retries;
        struct mbuf *m;
        short retries;
+#define        is ((struct ace_softc *)ifp)
 
 
-       if (is->is_flags & ACEF_OACTIVE)
-               return;
-       is->is_flags |= ACEF_OACTIVE;
 again:
        txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
        if (txs->tx_csr & TCS_TBFULL) {
                is->is_stats.tx_busy++;
 again:
        txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));
        if (txs->tx_csr & TCS_TBFULL) {
                is->is_stats.tx_busy++;
-               is->is_flags &= ~ACEF_OACTIVE;
-               return;
+               ifp->if_flags |= IFF_OACTIVE;
+               return (0);
        }
        s = splimp();
        }
        s = splimp();
-       IF_DEQUEUE(&is->is_if.if_snd, m);
+       IF_DEQUEUE(&ifp->if_snd, m);
        splx(s);
        if (m == 0) {
        splx(s);
        if (m == 0) {
-               is->is_flags &= ~ACEF_OACTIVE;
-               return;
+               ifp->if_flags &= ~IFF_OACTIVE;
+               return (0);
        }
        }
-       len = aceput(unit, txs->tx_data, m);
+       len = aceput(txs->tx_data, m);
        retries = txs->tx_csr & TCS_RTC;
        if (retries > 0)
                acebakoff(is, txs, retries);
        retries = txs->tx_csr & TCS_RTC;
        if (retries > 0)
                acebakoff(is, txs, retries);
@@ -286,20 +282,16 @@ again:
         * For security, it might be wise to zero out the added bytes,
         * but we're mainly interested in speed at the moment.
         */
         * For security, it might be wise to zero out the added bytes,
         * but we're mainly interested in speed at the moment.
         */
-#ifdef notdef
        if (len - sizeof (struct ether_header) < ETHERMIN)
                len = ETHERMIN + sizeof (struct ether_header);
        if (len - sizeof (struct ether_header) < ETHERMIN)
                len = ETHERMIN + sizeof (struct ether_header);
-#else
-       if (len - 14 < ETHERMIN)
-               len = ETHERMIN + 14;
-#endif
        if (++is->is_txnext > SEG_MAX) 
                is->is_txnext = is->is_segboundry;
        if (++is->is_txnext > SEG_MAX) 
                is->is_txnext = is->is_segboundry;
-       is->is_if.if_opackets++;
+       ifp->if_opackets++;
        is->is_xcnt++;
        len = (len & 0x7fff) | TCS_TBFULL;
        movow(txs, len);
        goto again;
        is->is_xcnt++;
        len = (len & 0x7fff) | TCS_TBFULL;
        movow(txs, len);
        goto again;
+#undef is
 }
 
 /*
 }
 
 /*
@@ -317,7 +309,7 @@ acecint(unit)
                    unit, is->is_xcnt);
                is->is_xcnt = 0;
                if (is->is_if.if_snd.ifq_head)
                    unit, is->is_xcnt);
                is->is_xcnt = 0;
                if (is->is_if.if_snd.ifq_head)
-                       acestart(unit);
+                       acestart(&is->is_if);
                return;
        }
        is->is_xcnt--;
                return;
        }
        is->is_xcnt--;
@@ -334,7 +326,7 @@ acecint(unit)
                        is->is_eoctr = is->is_segboundry; 
        } 
        if (is->is_if.if_snd.ifq_head)
                        is->is_eoctr = is->is_segboundry; 
        } 
        if (is->is_if.if_snd.ifq_head)
-               acestart(unit);
+               acestart(&is->is_if);
 }
 
 /*
 }
 
 /*
@@ -386,24 +378,15 @@ again:
        } else
                is->is_stats.rx_datagrams++;
        ace = (struct ether_header *)rxseg->rx_data;
        } else
                is->is_stats.rx_datagrams++;
        ace = (struct ether_header *)rxseg->rx_data;
-#ifdef notdef
        len -= sizeof (struct ether_header);
        len -= sizeof (struct ether_header);
-#else
-       len -= 14;
-#endif
        /*
         * Deal with trailer protocol: if type is trailer
         * get true type from first 16-bit word past data.
         * Remember that type was trailer by setting off.
         */
        ace->ether_type = ntohs((u_short)ace->ether_type);
        /*
         * Deal with trailer protocol: if type is trailer
         * get true type from first 16-bit word past data.
         * Remember that type was trailer by setting off.
         */
        ace->ether_type = ntohs((u_short)ace->ether_type);
-#ifdef notdef
 #define        acedataaddr(ace, off, type) \
     ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off))))
 #define        acedataaddr(ace, off, type) \
     ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off))))
-#else
-#define        acedataaddr(ace, off, type) \
-    ((type)(((caddr_t)(((char *)ace)+14)+(off))))
-#endif
        if (ace->ether_type >= ETHERTYPE_TRAIL &&
            ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                off = (ace->ether_type - ETHERTYPE_TRAIL) * 512;
        if (ace->ether_type >= ETHERTYPE_TRAIL &&
            ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                off = (ace->ether_type - ETHERTYPE_TRAIL) * 512;
@@ -422,20 +405,11 @@ again:
        /*
         * Pull packet off interface.  Off is nonzero if packet
         * has trailing header; aceget will then force this header
        /*
         * Pull packet off interface.  Off is nonzero if packet
         * has trailing header; aceget 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.
         */
        m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if);
        if (m == 0)
                goto setup;
         */
        m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if);
        if (m == 0)
                goto setup;
-       if (off) {
-               struct ifnet *ifp;
-
-               ifp = *(mtod(m, struct ifnet **));
-               m->m_off += 2 * sizeof (u_short);
-               m->m_len -= 2 * sizeof (u_short);
-               *(mtod(m, struct ifnet **)) = ifp;
-       }
        switch (ace->ether_type) {
 
 #ifdef INET
        switch (ace->ether_type) {
 
 #ifdef INET
@@ -472,165 +446,13 @@ setup:
        goto again;
 }
 
        goto again;
 }
 
-/*
- * Ethernet output routine.
- * Encapsulate a packet of type family for the local net.
- * Use trailer local net encapsulation if enough data in first
- * packet leaves a multiple of 512 bytes of data in remainder.
- */
-aceoutput(ifp, m0, dst)
-       struct ifnet *ifp;
-       struct mbuf *m0;
-       struct sockaddr *dst;
-{
-       register struct ace_softc *is = &ace_softc[ifp->if_unit];
-       register struct mbuf *m = m0;
-       register struct ether_header *ace;
-       register int off;
-       struct mbuf *mcopy = (struct mbuf *)0;
-       int type, s, error;
-       u_char edst[6];
-       struct in_addr idst;
-
-       if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
-               error = ENETDOWN;
-               goto bad;
-       }
-       switch (dst->sa_family) {
-
-#ifdef INET
-       case AF_INET:
-               idst = ((struct sockaddr_in *)dst)->sin_addr;
-               if (!arpresolve(&is->is_ac, m, &idst, edst))
-                       return (0);     /* if not yet resolved */
-               if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
-                   sizeof(edst)))
-                       mcopy = m_copy(m, 0, (int)M_COPYALL);
-               off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
-               /* need per host negotiation */
-               if ((ifp->if_flags & IFF_NOTRAILERS) == 0 && off > 0 &&
-                   (off & 0x1ff) == 0 &&
-                   m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
-                       type = ETHERTYPE_TRAIL + (off>>9);
-                       m->m_off -= 2 * sizeof (u_short);
-                       m->m_len += 2 * sizeof (u_short);
-                       *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
-                       *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
-                       goto gottrailertype;
-               }
-               type = ETHERTYPE_IP;
-               off = 0;
-               goto gottype;
-#endif
-#ifdef NS
-       case AF_NS:
-               bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
-                   (caddr_t)edst, sizeof (edst));
-               if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost,sizeof(edst)))
-                       mcopy = m_copy(m, 0, (int)M_COPYALL);
-               else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
-                   sizeof(edst)))
-                       return(looutput(&loif, m, dst));
-               type = ETHERTYPE_NS;
-               off = 0;
-               goto gottype;
-#endif
-       case AF_UNSPEC:
-               ace = (struct ether_header *)dst->sa_data;
-               bcopy((caddr_t)ace->ether_dhost, (caddr_t)edst, sizeof (edst));
-               type = ace->ether_type;
-               goto gottype;
-
-       default:
-               log(LOG_ERR, "ace%d: can't handle af%d\n",
-                   ifp->if_unit, dst->sa_family);
-               error = EAFNOSUPPORT;
-               goto bad;
-       }
-
-gottrailertype:
-       /*
-        * Packet to be sent as trailer: move first packet
-        * (control information) to end of chain.
-        */
-       while (m->m_next)
-               m = m->m_next;
-       m->m_next = m0;
-       m = m0->m_next;
-       m0->m_next = 0;
-       m0 = m;
-
-gottype:
-       /*
-        * Add local net header.  If no space in first mbuf,
-        * allocate another.
-        */
-       if (m->m_off > MMAXOFF ||
-#ifdef notdef
-           MMINOFF + sizeof (struct ether_header) > m->m_off) { 
-#else
-           MMINOFF + 14 > m->m_off) { 
-#endif
-               m = m_get(M_DONTWAIT, MT_HEADER);
-               if (m == 0) {
-                       error = ENOBUFS;
-                       goto bad;
-               }
-               m->m_next = m0;
-               m->m_off = MMINOFF;
-#ifdef notdef
-               m->m_len = sizeof (struct ether_header);
-#else
-               m->m_len = 14;
-#endif
-       } else {
-#ifdef notdef
-               m->m_off -= sizeof (struct ether_header);
-               m->m_len += sizeof (struct ether_header);
-#else
-               m->m_off -= 14;
-               m->m_len += 14;
-#endif
-       }
-       ace = mtod(m, struct ether_header *);
-       bcopy((caddr_t)edst, (caddr_t)ace->ether_dhost, sizeof (edst));
-       bcopy((caddr_t)is->is_addr, (caddr_t)ace->ether_shost,
-           sizeof (is->is_addr));
-       ace->ether_type = htons((u_short)type);
-
-       /*
-        * Queue message on interface, and start output if interface
-        * not yet active.
-        */
-       s = splimp();
-       if (IF_QFULL(&ifp->if_snd)) {
-               IF_DROP(&ifp->if_snd);
-               error = ENOBUFS;
-               goto qfull;
-       }
-       IF_ENQUEUE(&ifp->if_snd, m);
-       splx(s);
-       acestart(ifp->if_unit);
-       return (mcopy ? looutput(&loif, mcopy, dst) : 0);
-qfull:
-       m0 = m;
-       splx(s);
-bad:
-       m_freem(m0);
-       if (mcopy)
-               m_freem(mcopy);
-       return (error);
-}
-
 /*
  * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
  * If packet size is less than the minimum legal size,
  * the buffer is expanded.  We probably should zero out the extra
  * bytes for security, but that would slow things down.
  */
 /*
  * Routine to copy from mbuf chain to transmit buffer on the VERSAbus
  * If packet size is less than the minimum legal size,
  * the buffer is expanded.  We probably should zero out the extra
  * bytes for security, but that would slow things down.
  */
-/*ARGSUSED*/
-aceput(unit, txbuf, m)
-       int unit;
+aceput(txbuf, m)
        char *txbuf;
        struct mbuf *m;
 {
        char *txbuf;
        struct mbuf *m;
 {
@@ -640,13 +462,12 @@ aceput(unit, txbuf, m)
        register struct mbuf *mp;
        int total;
 
        register struct mbuf *mp;
        int total;
 
-       total = 0;
+       total = mp->m_pkthdr.len;
        bp = (u_char *)txbuf;
        for (mp = m; (mp); mp = mp->m_next) {
                len = mp->m_len;
                if (len == 0)
                        continue;
        bp = (u_char *)txbuf;
        for (mp = m; (mp); mp = mp->m_next) {
                len = mp->m_len;
                if (len == 0)
                        continue;
-               total += len;
                mcp = mtod(mp, u_char *);
                if (((int)mcp & 01) && ((int)bp & 01)) {
                        /* source & destination at odd addresses */
                mcp = mtod(mp, u_char *);
                if (((int)mcp & 01) && ((int)bp & 01)) {
                        /* source & destination at odd addresses */
@@ -654,14 +475,14 @@ aceput(unit, txbuf, m)
                        --len;
                }
                if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
                        --len;
                }
                if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) {
-                       register u_int l;
+                       int l = len;
 
                        s1 = (short *)bp;
                        s2 = (short *)mcp;
 
                        s1 = (short *)bp;
                        s2 = (short *)mcp;
-                       l = len >> 1;           /* count # of shorts */
-                       while (l-- != 0)
+                       len >>= 1;              /* count # of shorts */
+                       while (len-- != 0)
                                movow(s1++, *s2++);
                                movow(s1++, *s2++);
-                       len &= 1;               /* # remaining bytes */
+                       len = l & 1;            /* # remaining bytes */
                        bp = (u_char *)s1;
                        mcp = (u_char *)s2;
                }
                        bp = (u_char *)s1;
                        mcp = (u_char *)s2;
                }
@@ -680,62 +501,62 @@ aceput(unit, txbuf, m)
  */
 /*ARGSUSED*/
 struct mbuf *
  */
 /*ARGSUSED*/
 struct mbuf *
-aceget(rxbuf, totlen, off0, ifp)
+aceget(rxbuf, totlen, off, ifp)
        u_char *rxbuf;
        u_char *rxbuf;
-       int totlen, off0;
+       int totlen, off;
        struct ifnet *ifp;
 {
        register u_char *cp, *mcp;
        struct ifnet *ifp;
 {
        register u_char *cp, *mcp;
-       register int tlen;
        register struct mbuf *m;
        register struct mbuf *m;
+       register int tlen;
        struct mbuf *top = 0, **mp = &top;
        struct mbuf *top = 0, **mp = &top;
-       int len, off = off0;
+       int len;
+       u_char *packet_end;
+
+       rxbuf += sizeof (struct ether_header);
+       cp = rxbuf;
+       packet_end = cp + totlen;
+       if (off) {
+               off += 2 * sizeof(u_short);
+               totlen -= 2 *sizeof(u_short);
+               cp = rxbuf + off;
+       }
+
+       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;
 
 
-#ifdef notdef
-       cp = rxbuf + sizeof (struct ether_header);
-#else
-       cp = rxbuf + 14;
-#endif
        while (totlen > 0) {
        while (totlen > 0) {
-               MGET(m, M_DONTWAIT, MT_DATA);
-               if (m == 0)
-                       goto bad;
-               if (off) {
-                       len = totlen - off;
-#ifdef notdef
-                       cp = rxbuf + sizeof (struct ether_header) + off;
-#else
-                       cp = rxbuf + 14 + off;
-#endif
-               } else
-                       len = totlen;
-               if (ifp)
-                       len += sizeof(ifp);
-               if (len >= CLBYTES) {
-                       struct mbuf *p;
-
-                       MCLGET(p, 1);
-                       if (p != 0) {
-                               m->m_len = len = CLBYTES;
-                               m->m_off = (int)p - (int)m;
-                       } else {
-                               m->m_len = len = MIN(MLEN, len);
-                               m->m_off = MMINOFF;
+               if (top) {
+                       MGET(m, M_DONTWAIT, MT_DATA);
+                       if (m == 0) {
+                               m_freem(top);
+                               return (0);
                        }
                        }
-               } else {
-                       m->m_len = len = MIN(MLEN, len);
-                       m->m_off = MMINOFF;
+                       m->m_len = MLEN;
                }
                }
-               mcp = mtod(m, u_char *);
-               if (ifp) {
+               len = min(totlen, (packet_end - 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 {
                        /*
                        /*
-                        * Prepend interface pointer to first mbuf.
+                        * Place initial small packet/header at end of mbuf.
                         */
                         */
-                       *(mtod(m, struct ifnet **)) = ifp;
-                       mcp += sizeof(ifp);
-                       len -= sizeof(ifp);
-                       ifp = (struct ifnet *)0;
+                       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;
                }
                }
+               mcp = mtod(m, u_char *);
                /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
                /*cp += len; mcp += len;*/
                tlen = len;
                /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/
                /*cp += len; mcp += len;*/
                tlen = len;
@@ -761,27 +582,19 @@ aceget(rxbuf, totlen, off0, ifp)
                        *mcp++ = *cp++;
                *mp = m;
                mp = &m->m_next;
                        *mcp++ = *cp++;
                *mp = m;
                mp = &m->m_next;
-               if (off == 0) {
-                       totlen -= len;
-                       continue;
-               }
-               off += len;
-               if (off == totlen) {
-#ifdef notdef
-                       cp = rxbuf + sizeof (struct ether_header);
-#else
-                       cp = rxbuf + 14;
-#endif
-                       off = 0;
-                       totlen = off0;
-               }
+               totlen -= len;
+               if (cp == packet_end)
+                       cp = rxbuf;
        }
        return (top);
        }
        return (top);
-bad:
-       m_freem(top);
-       return (0);
 }
 
 }
 
+/* backoff table masks */
+short  random_mask_tbl[16] = {
+       0x0040, 0x00c0, 0x01c0, 0x03c0, 0x07c0, 0x0fc0, 0x1fc0, 0x3fc0,
+       0x7fc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0
+};
+
 acebakoff(is, txseg, retries)
        struct ace_softc *is;
        struct tx_segment *txseg;
 acebakoff(is, txseg, retries)
        struct ace_softc *is;
        struct tx_segment *txseg;
@@ -795,7 +608,7 @@ acebakoff(is, txseg, retries)
        while (--retries >= 0) {
                random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
                random_num &= *pMask++;
        while (--retries >= 0) {
                random_num = (is->is_currnd = (is->is_currnd * 18741)-13849);
                random_num &= *pMask++;
-               *pBakNum++ = random_num ^ (short)(0xFF00 | 0x00FC);
+               *pBakNum++ = random_num ^ (short)(0xff00 | 0x00fc);
        }
 }
 
        }
 }
 
@@ -826,20 +639,20 @@ aceioctl(ifp, cmd, data)
 #endif
 #ifdef NS
                case AF_NS: {
 #endif
 #ifdef NS
                case AF_NS: {
-                       struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
+                       struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+                       struct ace_softc *is = &ace_softc[ifp->if_unit];
 
                        if (!ns_nullhost(*ina)) {
                                ifp->if_flags &= ~IFF_RUNNING;
 
                        if (!ns_nullhost(*ina)) {
                                ifp->if_flags &= ~IFF_RUNNING;
-                               sin = (struct sockaddr_in *)&ifr->ifr_addr;
                                addr = (struct acedevice *)
                                addr = (struct acedevice *)
-                                   (aceinfo[ifp->if_unit]->ui_addr);
+                                   aceinfo[ifp->if_unit]->ui_addr;
                                movow(&addr->csr, CSR_RESET);
                                DELAY(10000);
                                /* set station address & copy addr to arp */
                                movow(&addr->csr, CSR_RESET);
                                DELAY(10000);
                                /* set station address & copy addr to arp */
-                               acesetetaddr(ifp->if_unit, addr, 
+                               acesetaddr(ifp->if_unit, addr, 
                                    ina->x_host.c_host);
                        } else
                                    ina->x_host.c_host);
                        } else
-                               ina->x_host = *(union ns_host *)(es->es_addr);
+                               ina->x_host = *(union ns_host *)is->is_addr;
                        aceinit(ifp->if_unit);
                        break;
                }
                        aceinit(ifp->if_unit);
                        break;
                }
@@ -868,6 +681,30 @@ aceioctl(ifp, cmd, data)
        return (error);
 }
 
        return (error);
 }
 
+/*
+ * Set the on-board station address, then read it back
+ * to initialize the address used by ARP (among others).
+ */
+acesetaddr(unit, addr, station)
+       short unit;
+       struct acedevice *addr;
+       u_char *station;
+{
+       struct ace_softc *is = &ace_softc[unit];
+       register short *wp, i;
+
+       for (wp = (short *)addr->station, i = 0; i < 6; i++)
+               movow(wp++, ~*station++); 
+       for (wp = (short *)addr->station, i = 0; i < 6; i++)
+               is->is_addr[i] = ~*wp++;
+       printf("ace%d: hardware address %s\n", unit,
+           ether_sprintf(is->is_addr));
+}
+
+/*
+ * Setup the device for use.  Initialize dual-ported memory,
+ * backoff parameters, and various other software state.
+ */
 acesetup(unit)
        int unit;
 {
 acesetup(unit)
        int unit;
 {