Latest fixes from Nesheim@cornell
[unix-history] / usr / src / sys / vax / if / if_de.c
index 48af351..28e6ced 100644 (file)
@@ -1,4 +1,10 @@
-/*     if_de.c 6.2     84/02/02        */
+/*
+ * Copyright (c) 1982 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ *     @(#)if_de.c     6.12 (Berkeley) %G%
+ */
 #include "de.h"
 #if NDE > 0
 
 #include "de.h"
 #if NDE > 0
 
  */
 #include "../machine/pte.h"
 
  */
 #include "../machine/pte.h"
 
-#include "../h/param.h"
-#include "../h/systm.h"
-#include "../h/mbuf.h"
-#include "../h/buf.h"
-#include "../h/protosw.h"
-#include "../h/socket.h"
-#include "../h/vmmac.h"
-#include "../h/ioctl.h"
-#include "../h/errno.h"
+#include "param.h"
+#include "systm.h"
+#include "mbuf.h"
+#include "buf.h"
+#include "protosw.h"
+#include "socket.h"
+#include "vmmac.h"
+#include "ioctl.h"
+#include "errno.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
 #include "../net/route.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
 #include "../net/route.h"
+
+#ifdef INET
 #include "../netinet/in.h"
 #include "../netinet/in_systm.h"
 #include "../netinet/in.h"
 #include "../netinet/in_systm.h"
+#include "../netinet/in_var.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
 #include "../netinet/if_ether.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
 #include "../netinet/if_ether.h"
+#endif
+
+#ifdef PUP
 #include "../netpup/pup.h"
 #include "../netpup/pup.h"
+#endif
+
+#ifdef NS
+#include "../netns/ns.h"
+#include "../netns/ns_if.h"
+#endif
 
 #include "../vax/cpu.h"
 #include "../vax/mtpr.h"
 
 #include "../vax/cpu.h"
 #include "../vax/mtpr.h"
-#include "../vaxif/if_dereg.h"
-#include "../vaxif/if_uba.h"
+#include "if_dereg.h"
+#include "if_uba.h"
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/ubavar.h"
 
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/ubavar.h"
 
-#define        NXMT    2       /* number of transmit buffers */
-#define        NRCV    4       /* number of receive buffers (must be > 1) */
+#define        NXMT    3       /* number of transmit buffers */
+#define        NRCV    7       /* number of receive buffers (must be > 1) */
 #define        NTOT    (NXMT + NRCV)
 
 int    dedebug = 0;
 #define        NTOT    (NXMT + NRCV)
 
 int    dedebug = 0;
@@ -51,23 +69,27 @@ struct      uba_device *deinfo[NDE];
 u_short destd[] = { 0 };
 struct uba_driver dedriver =
        { deprobe, 0, deattach, 0, destd, "de", deinfo };
 u_short destd[] = { 0 };
 struct uba_driver dedriver =
        { deprobe, 0, deattach, 0, destd, "de", deinfo };
-#define        DEUNIT(x)       minor(x)
 int    deinit(),deoutput(),deioctl(),dereset();
 struct mbuf *deget();
 
 
 /*
 int    deinit(),deoutput(),deioctl(),dereset();
 struct mbuf *deget();
 
 
 /*
- * The following generalizes the ifuba structure
- * to an arbitrary number of receive and transmit
- * buffers.
+ * The deuba structures generalizes the ifuba structure
+ * to an arbitrary number of receive and transmit buffers.
  */
  */
+struct ifxmt {
+       struct  ifrw x_ifrw;                    /* mapping information */
+       struct  pte x_map[IF_MAXNUBAMR];        /* output base pages */
+       short   x_xswapd;                       /* mask of clusters swapped */
+       struct  mbuf *x_xtofree;                /* pages being dma'ed out */
+};
+
 struct deuba {
        short   ifu_uban;               /* uba number */
        short   ifu_hlen;               /* local net header length */
        struct  uba_regs *ifu_uba;      /* uba regs, in vm */
        struct  ifrw ifu_r[NRCV];       /* receive information */
 struct deuba {
        short   ifu_uban;               /* uba number */
        short   ifu_hlen;               /* local net header length */
        struct  uba_regs *ifu_uba;      /* uba regs, in vm */
        struct  ifrw ifu_r[NRCV];       /* receive information */
-       struct  ifrw ifu_w[NXMT];       /* transmit information */
-                               /* these should only be pointers */
+       struct  ifxmt ifu_w[NXMT];      /* transmit information */
        short   ifu_flags;              /* used during uballoc's */
 };
 
        short   ifu_flags;              /* used during uballoc's */
 };
 
@@ -147,12 +169,12 @@ deattach(ui)
        register struct de_softc *ds = &de_softc[ui->ui_unit];
        register struct ifnet *ifp = &ds->ds_if;
        register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
        register struct de_softc *ds = &de_softc[ui->ui_unit];
        register struct ifnet *ifp = &ds->ds_if;
        register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
-       struct sockaddr_in *sin;
        int csr0;
 
        ifp->if_unit = ui->ui_unit;
        ifp->if_name = "de";
        ifp->if_mtu = ETHERMTU;
        int csr0;
 
        ifp->if_unit = ui->ui_unit;
        ifp->if_name = "de";
        ifp->if_mtu = ETHERMTU;
+       ifp->if_flags = IFF_BROADCAST;
 
        /*
         * Reset the board and temporarily map
 
        /*
         * Reset the board and temporarily map
@@ -193,11 +215,8 @@ deattach(ui)
                    ds->ds_pcbb.pcbb2&0xff, (ds->ds_pcbb.pcbb2>>8)&0xff,
                    ds->ds_pcbb.pcbb4&0xff, (ds->ds_pcbb.pcbb4>>8)&0xff,
                    ds->ds_pcbb.pcbb6&0xff, (ds->ds_pcbb.pcbb6>>8)&0xff);
                    ds->ds_pcbb.pcbb2&0xff, (ds->ds_pcbb.pcbb2>>8)&0xff,
                    ds->ds_pcbb.pcbb4&0xff, (ds->ds_pcbb.pcbb4>>8)&0xff,
                    ds->ds_pcbb.pcbb6&0xff, (ds->ds_pcbb.pcbb6>>8)&0xff);
-       bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
+       bcopy((caddr_t)&ds->ds_pcbb.pcbb2, (caddr_t)ds->ds_addr,
            sizeof (ds->ds_addr));
            sizeof (ds->ds_addr));
-       sin = (struct sockaddr_in *)&ifp->if_addr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr = arpmyaddr((struct arpcom *)0);
        ifp->if_init = deinit;
        ifp->if_output = deoutput;
        ifp->if_ioctl = deioctl;
        ifp->if_init = deinit;
        ifp->if_output = deoutput;
        ifp->if_ioctl = deioctl;
@@ -223,7 +242,7 @@ dereset(unit, uban)
            ui->ui_ubanum != uban)
                return;
        printf(" de%d", unit);
            ui->ui_ubanum != uban)
                return;
        printf(" de%d", unit);
-       /* NEED TO RESET IFF_RUNNING AND DSF_RUNNING? */
+       de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
        deinit(unit);
 }
 
        deinit(unit);
 }
 
@@ -238,19 +257,19 @@ deinit(unit)
        register struct uba_device *ui = deinfo[unit];
        register struct dedevice *addr;
        register struct ifrw *ifrw;
        register struct uba_device *ui = deinfo[unit];
        register struct dedevice *addr;
        register struct ifrw *ifrw;
+       register struct ifxmt *ifxp;
+       struct ifnet *ifp = &ds->ds_if;
        int s;
        int s;
-       register struct ifnet *ifp = &ds->ds_if;
-       register struct sockaddr_in *sin;
        struct de_ring *rp;
        int incaddr;
        int csr0;
 
        struct de_ring *rp;
        int incaddr;
        int csr0;
 
-       sin = (struct sockaddr_in *)&ifp->if_addr;
-       if (sin->sin_addr.s_addr == 0)  /* if address still unknown */
+       /* not yet, if address still unknown */
+       if (ifp->if_addrlist == (struct ifaddr *)0)
                return;
 
        if (ifp->if_flags & IFF_RUNNING)
                return;
 
        if (ifp->if_flags & IFF_RUNNING)
-               goto justarp;
+               return;
        if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum,
            sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 
                printf("de%d: can't initialize\n", unit);
        if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum,
            sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 
                printf("de%d: can't initialize\n", unit);
@@ -313,12 +332,12 @@ deinit(unit)
                    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
 
        /* set up the receive and transmit ring entries */
                    csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);
 
        /* set up the receive and transmit ring entries */
-       ifrw = &ds->ds_deuba.ifu_w[0];
+       ifxp = &ds->ds_deuba.ifu_w[0];
        for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
        for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {
-               rp->r_segbl = ifrw->ifrw_info & 0xffff;
-               rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;
+               rp->r_segbl = ifxp->x_ifrw.ifrw_info & 0xffff;
+               rp->r_segbh = (ifxp->x_ifrw.ifrw_info >> 16) & 0x3;
                rp->r_flags = 0;
                rp->r_flags = 0;
-               ifrw++;
+               ifxp++;
        }
        ifrw = &ds->ds_deuba.ifu_r[0];
        for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
        }
        ifrw = &ds->ds_deuba.ifu_r[0];
        for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {
@@ -332,16 +351,12 @@ deinit(unit)
        /* start up the board (rah rah) */
        s = splimp();
        ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = 0;
        /* start up the board (rah rah) */
        s = splimp();
        ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = 0;
-       ds->ds_if.if_flags |= IFF_UP|IFF_RUNNING;
+       ds->ds_if.if_flags |= IFF_RUNNING;
        destart(unit);                          /* queue output packets */
        addr->pclow = PCSR0_INTE;               /* avoid interlock */
        addr->pclow = CMD_START | PCSR0_INTE;
        ds->ds_flags |= DSF_RUNNING;
        splx(s);
        destart(unit);                          /* queue output packets */
        addr->pclow = PCSR0_INTE;               /* avoid interlock */
        addr->pclow = CMD_START | PCSR0_INTE;
        ds->ds_flags |= DSF_RUNNING;
        splx(s);
-justarp:
-       if_rtinit(&ds->ds_if, RTF_UP);
-       arpattach(&ds->ds_ac);
-       arpwhohas(&ds->ds_ac, &sin->sin_addr);
 }
 
 /*
 }
 
 /*
@@ -374,10 +389,10 @@ destart(unit)
                rp = &ds->ds_xrent[ds->ds_xfree];
                if (rp->r_flags & XFLG_OWN)
                        panic("deuna xmit in progress");
                rp = &ds->ds_xrent[ds->ds_xfree];
                if (rp->r_flags & XFLG_OWN)
                        panic("deuna xmit in progress");
-               len = deput(&ds->ds_deuba.ifu_w[ds->ds_xfree], m);
+               len = deput(&ds->ds_deuba, ds->ds_xfree, m);
                if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)
                        UBAPURGE(ds->ds_deuba.ifu_uba,
                if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)
                        UBAPURGE(ds->ds_deuba.ifu_uba,
-                       ds->ds_deuba.ifu_w[ds->ds_xfree].ifrw_bdp);
+                       ds->ds_deuba.ifu_w[ds->ds_xfree].x_ifrw.ifrw_bdp);
                rp->r_slen = len;
                rp->r_tdrerr = 0;
                rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
                rp->r_slen = len;
                rp->r_tdrerr = 0;
                rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
@@ -403,6 +418,7 @@ deintr(unit)
        register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
        register struct de_softc *ds = &de_softc[unit];
        register struct de_ring *rp;
        register struct dedevice *addr = (struct dedevice *)ui->ui_addr;
        register struct de_softc *ds = &de_softc[unit];
        register struct de_ring *rp;
+       register struct ifxmt *ifxp;
        short csr0;
 
        /* save flags right away - clear out interrupt bits */
        short csr0;
 
        /* save flags right away - clear out interrupt bits */
@@ -428,6 +444,7 @@ deintr(unit)
                if (rp->r_flags & XFLG_OWN)
                        break;
                ds->ds_if.if_opackets++;
                if (rp->r_flags & XFLG_OWN)
                        break;
                ds->ds_if.if_opackets++;
+               ifxp = &ds->ds_deuba.ifu_w[ds->ds_xindex];
                /* check for unusual conditions */
                if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
                        if (rp->r_flags & XFLG_ERRS) {
                /* check for unusual conditions */
                if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
                        if (rp->r_flags & XFLG_ERRS) {
@@ -446,10 +463,14 @@ deintr(unit)
                        } else if (rp->r_flags & XFLG_MTCH) {
                                /* received our own packet */
                                ds->ds_if.if_ipackets++;
                        } else if (rp->r_flags & XFLG_MTCH) {
                                /* received our own packet */
                                ds->ds_if.if_ipackets++;
-                               deread(ds, &ds->ds_deuba.ifu_w[ds->ds_xindex],
+                               deread(ds, &ifxp->x_ifrw,
                                    rp->r_slen - sizeof (struct ether_header));
                        }
                }
                                    rp->r_slen - sizeof (struct ether_header));
                        }
                }
+               if (ifxp->x_xtofree) {
+                       m_freem(ifxp->x_xtofree);
+                       ifxp->x_xtofree = 0;
+               }
                /* check if next transmit buffer also finished */
                ds->ds_xindex++;
                if (ds->ds_xindex == NXMT)
                /* check if next transmit buffer also finished */
                ds->ds_xindex++;
                if (ds->ds_xindex == NXMT)
@@ -525,19 +546,20 @@ deread(ds, ifrw, len)
        struct ether_header *eh;
        struct mbuf *m;
        int off, resid;
        struct ether_header *eh;
        struct mbuf *m;
        int off, resid;
+       int s;
        register struct ifqueue *inq;
 
        /*
        register struct ifqueue *inq;
 
        /*
-        * Deal with trailer protocol: if type is PUP trailer
+        * Deal with trailer protocol: if type is trailer type
         * get true type from first 16-bit word past data.
         * Remember that type was trailer by setting off.
         */
        eh = (struct ether_header *)ifrw->ifrw_addr;
        eh->ether_type = ntohs((u_short)eh->ether_type);
 #define        dedataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
         * get true type from first 16-bit word past data.
         * Remember that type was trailer by setting off.
         */
        eh = (struct ether_header *)ifrw->ifrw_addr;
        eh->ether_type = ntohs((u_short)eh->ether_type);
 #define        dedataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
-       if (eh->ether_type >= ETHERPUP_TRAIL &&
-           eh->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
-               off = (eh->ether_type - ETHERPUP_TRAIL) * 512;
+       if (eh->ether_type >= ETHERTYPE_TRAIL &&
+           eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
+               off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
                if (off >= ETHERMTU)
                        return;         /* sanity */
                eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *));
                if (off >= ETHERMTU)
                        return;         /* sanity */
                eh->ether_type = ntohs(*dedataaddr(eh, off, u_short *));
@@ -566,26 +588,36 @@ deread(ds, ifrw, len)
        switch (eh->ether_type) {
 
 #ifdef INET
        switch (eh->ether_type) {
 
 #ifdef INET
-       case ETHERPUP_IPTYPE:
+       case ETHERTYPE_IP:
                schednetisr(NETISR_IP);
                inq = &ipintrq;
                break;
 
                schednetisr(NETISR_IP);
                inq = &ipintrq;
                break;
 
-       case ETHERPUP_ARPTYPE:
+       case ETHERTYPE_ARP:
                arpinput(&ds->ds_ac, m);
                return;
                arpinput(&ds->ds_ac, m);
                return;
+#endif
+#ifdef NS
+       case ETHERTYPE_NS:
+               schednetisr(NETISR_NS);
+               inq = &nsintrq;
+               break;
+
 #endif
        default:
                m_freem(m);
                return;
        }
 
 #endif
        default:
                m_freem(m);
                return;
        }
 
+       s = splimp();
        if (IF_QFULL(inq)) {
                IF_DROP(inq);
        if (IF_QFULL(inq)) {
                IF_DROP(inq);
+               splx(s);
                m_freem(m);
                return;
        }
        IF_ENQUEUE(inq, m);
                m_freem(m);
                return;
        }
        IF_ENQUEUE(inq, m);
+       splx(s);
 }
 
 /*
 }
 
 /*
@@ -600,7 +632,7 @@ deoutput(ifp, m0, dst)
        struct sockaddr *dst;
 {
        int type, s, error;
        struct sockaddr *dst;
 {
        int type, s, error;
-       u_char edst[6];
+       u_char edst[6];
        struct in_addr idst;
        register struct de_softc *ds = &de_softc[ifp->if_unit];
        register struct mbuf *m = m0;
        struct in_addr idst;
        register struct de_softc *ds = &de_softc[ifp->if_unit];
        register struct mbuf *m = m0;
@@ -612,28 +644,36 @@ deoutput(ifp, m0, dst)
 #ifdef INET
        case AF_INET:
                idst = ((struct sockaddr_in *)dst)->sin_addr;
 #ifdef INET
        case AF_INET:
                idst = ((struct sockaddr_in *)dst)->sin_addr;
-               if (!arpresolve(&ds->ds_ac, m, &idst, edst))
+               if (!arpresolve(&ds->ds_ac, m, &idst, edst))
                        return (0);     /* if not yet resolved */
                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                /* need per host negotiation */
                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
                if (off > 0 && (off & 0x1ff) == 0 &&
                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
                        return (0);     /* if not yet resolved */
                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                /* need per host negotiation */
                if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
                if (off > 0 && (off & 0x1ff) == 0 &&
                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
-                       type = ETHERPUP_TRAIL + (off>>9);
+                       type = ETHERTYPE_TRAIL + (off>>9);
                        m->m_off -= 2 * sizeof (u_short);
                        m->m_len += 2 * sizeof (u_short);
                        m->m_off -= 2 * sizeof (u_short);
                        m->m_len += 2 * sizeof (u_short);
-                       *mtod(m, u_short *) = htons((u_short)ETHERPUP_IPTYPE);
+                       *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
                        goto gottrailertype;
                }
                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
                        goto gottrailertype;
                }
-               type = ETHERPUP_IPTYPE;
+               type = ETHERTYPE_IP;
+               off = 0;
+               goto gottype;
+#endif
+#ifdef NS
+       case AF_NS:
+               type = ETHERTYPE_NS;
+               bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
+               (caddr_t)edst, sizeof (edst));
                off = 0;
                goto gottype;
 #endif
 
        case AF_UNSPEC:
                eh = (struct ether_header *)dst->sa_data;
                off = 0;
                goto gottype;
 #endif
 
        case AF_UNSPEC:
                eh = (struct ether_header *)dst->sa_data;
-               bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
+               bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
                type = eh->ether_type;
                goto gottype;
 
                type = eh->ether_type;
                goto gottype;
 
@@ -677,7 +717,7 @@ gottype:
        }
        eh = mtod(m, struct ether_header *);
        eh->ether_type = htons((u_short)type);
        }
        eh = mtod(m, struct ether_header *);
        eh->ether_type = htons((u_short)type);
-       bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
+       bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
        /* DEUNA fills in source address */
 
        /*
        /* DEUNA fills in source address */
 
        /*
@@ -718,7 +758,8 @@ de_ubainit(ifu, uban, hlen, nmr)
 {
        register caddr_t cp, dp;
        register struct ifrw *ifrw;
 {
        register caddr_t cp, dp;
        register struct ifrw *ifrw;
-       int ncl;
+       register struct ifxmt *ifxp;
+       int i, ncl;
 
        ncl = clrnd(nmr + CLSIZE) / CLSIZE;
        if (ifu->ifu_r[0].ifrw_addr)
 
        ncl = clrnd(nmr + CLSIZE) / CLSIZE;
        if (ifu->ifu_r[0].ifrw_addr)
@@ -739,32 +780,36 @@ de_ubainit(ifu, uban, hlen, nmr)
                        ifrw->ifrw_addr = dp;
                        dp += ncl * CLBYTES;
                }
                        ifrw->ifrw_addr = dp;
                        dp += ncl * CLBYTES;
                }
-               for (ifrw = ifu->ifu_w; ifrw < &ifu->ifu_w[NXMT]; ifrw++) {
-                       ifrw->ifrw_addr = dp;
+               for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {
+                       ifxp->x_ifrw.ifrw_addr = dp;
                        dp += ncl * CLBYTES;
                }
        }
        /* allocate for receive ring */
        for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {
                if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
                        dp += ncl * CLBYTES;
                }
        }
        /* allocate for receive ring */
        for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {
                if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
-                       struct ifrw *if2;
+                       struct ifrw *rw;
 
 
-                       for (if2 = ifu->ifu_r; if2 < ifrw; if2++)
-                               ubarelse(ifu->ifu_uban, &if2->ifrw_info);
+                       for (rw = ifu->ifu_r; rw < ifrw; rw++)
+                               ubarelse(ifu->ifu_uban, &rw->ifrw_info);
                        goto bad;
                }
        }
        /* and now transmit ring */
                        goto bad;
                }
        }
        /* and now transmit ring */
-       for (ifrw = ifu->ifu_w; ifrw < &ifu->ifu_w[NXMT]; ifrw++) {
+       for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {
+               ifrw = &ifxp->x_ifrw;
                if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
                if (de_ubaalloc(ifu, ifrw, nmr) == 0) {
-                       struct ifrw *if2;
+                       struct ifxmt *xp;
 
 
-                       for (if2 = ifu->ifu_w; if2 < ifrw; if2++)
-                               ubarelse(ifu->ifu_uban, &if2->ifrw_info);
-                       for (if2 = ifu->ifu_r; if2 < &ifu->ifu_r[NRCV]; if2++)
-                               ubarelse(ifu->ifu_uban, &if2->ifrw_info);
+                       for (xp = ifu->ifu_w; xp < ifxp; xp++)
+                               ubarelse(ifu->ifu_uban, &xp->x_ifrw.ifrw_info);
+                       for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++)
+                               ubarelse(ifu->ifu_uban, &ifrw->ifrw_info);
                        goto bad;
                }
                        goto bad;
                }
+               for (i = 0; i < nmr; i++)
+                       ifxp->x_map[i] = ifrw->ifrw_mr[i];
+               ifxp->x_xswapd = 0;
        }
        return (1);
 bad:
        }
        return (1);
 bad:
@@ -894,55 +939,71 @@ bad:
  * The argument chain of mbufs includes the local network
  * header which is copied to be in the mapped, aligned
  * i/o space.
  * The argument chain of mbufs includes the local network
  * header which is copied to be in the mapped, aligned
  * i/o space.
- *
- * This routine is unlike if_wubaput in that pages are
- * actually switched, rather than the UNIBUS maps temporarily
- * remapped.
  */
  */
-deput(ifrw, m)
-       register struct ifrw *ifrw;
+deput(ifu, n, m)
+       struct deuba *ifu;
+       int n;
        register struct mbuf *m;
 {
        register struct mbuf *mp;
        register caddr_t cp;
        register struct mbuf *m;
 {
        register struct mbuf *mp;
        register caddr_t cp;
-       int cc;
-       register caddr_t dp;
+       register struct ifxmt *ifxp;
+       register struct ifrw *ifrw;
        register int i;
        register int i;
-       int x;
+       int xswapd = 0;
+       int x, cc, t;
+       caddr_t dp;
 
 
+       ifxp = &ifu->ifu_w[n];
+       ifrw = &ifxp->x_ifrw;
        cp = ifrw->ifrw_addr;
        while (m) {
                dp = mtod(m, char *);
                if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) {
        cp = ifrw->ifrw_addr;
        while (m) {
                dp = mtod(m, char *);
                if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) {
-                       struct pte *cpte, *ppte;
-                       int *ip;
-
-                       cpte = &Mbmap[mtocl(cp)*CLSIZE];
-                       ppte = &Mbmap[mtocl(dp)*CLSIZE];
+                       struct pte *pte; int *ip;
+                       pte = &Mbmap[mtocl(dp)*CLSIZE];
                        x = btop(cp - ifrw->ifrw_addr);
                        ip = (int *)&ifrw->ifrw_mr[x];
                        x = btop(cp - ifrw->ifrw_addr);
                        ip = (int *)&ifrw->ifrw_mr[x];
-                       for (i = 0; i < CLSIZE; i++) {
-                               struct pte t;
-                               t = *ppte; *ppte++ = *cpte; *cpte = t;
+                       for (i = 0; i < CLSIZE; i++)
                                *ip++ =
                                *ip++ =
-                                   cpte++->pg_pfnum|ifrw->ifrw_proto;
-                               mtpr(TBIS, cp);
-                               cp += NBPG;
-                               mtpr(TBIS, dp);
-                               dp += NBPG;
-                       }
+                                   ifrw->ifrw_proto | pte++->pg_pfnum;
+                       xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT));
+                       mp = m->m_next;
+                       m->m_next = ifxp->x_xtofree;
+                       ifxp->x_xtofree = m;
+                       cp += m->m_len;
                } else {
                        bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
                        cp += m->m_len;
                } else {
                        bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);
                        cp += m->m_len;
+                       MFREE(m, mp);
                }
                }
-               MFREE(m, mp);
                m = mp;
        }
 
                m = mp;
        }
 
+       /*
+        * Xswapd is the set of clusters we just mapped out.  Ifxp->x_xswapd
+        * is the set of clusters mapped out from before.  We compute
+        * the number of clusters involved in this operation in x.
+        * Clusters mapped out before and involved in this operation
+        * should be unmapped so original pages will be accessed by the device.
+        */
        cc = cp - ifrw->ifrw_addr;
        cc = cp - ifrw->ifrw_addr;
+       x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT;
+       ifxp->x_xswapd &= ~xswapd;
+       while (i = ffs(ifxp->x_xswapd)) {
+               i--;
+               if (i >= x)
+                       break;
+               ifxp->x_xswapd &= ~(1<<i);
+               i *= CLSIZE;
+               for (t = 0; t < CLSIZE; t++) {
+                       ifrw->ifrw_mr[i] = ifxp->x_map[i];
+                       i++;
+               }
+       }
+       ifxp->x_xswapd |= xswapd;
        return (cc);
 }
        return (cc);
 }
-#endif
 
 /*
  * Process an ioctl request.
 
 /*
  * Process an ioctl request.
@@ -952,16 +1013,38 @@ deioctl(ifp, cmd, data)
        int cmd;
        caddr_t data;
 {
        int cmd;
        caddr_t data;
 {
-       register struct ifreq *ifr = (struct ifreq *)data;
+       register struct ifaddr *ifa = (struct ifaddr *)data;
        int s = splimp(), error = 0;
 
        switch (cmd) {
 
        case SIOCSIFADDR:
        int s = splimp(), error = 0;
 
        switch (cmd) {
 
        case SIOCSIFADDR:
-               if (ifp->if_flags & IFF_RUNNING)
-                       if_rtinit(ifp, -1);     /* delete previous route */
-               desetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
+               ifp->if_flags |= IFF_UP;
                deinit(ifp->if_unit);
                deinit(ifp->if_unit);
+
+               switch (ifa->ifa_addr.sa_family) {
+#ifdef INET
+               case AF_INET:
+                       ((struct arpcom *)ifp)->ac_ipaddr =
+                               IA_SIN(ifa)->sin_addr;
+                       arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
+                       break;
+#endif
+#ifdef NS
+               case AF_NS:
+                   {
+                       register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
+                       
+                       if (ns_nullhost(*ina)) {
+                               ina->x_host = * (union ns_host *) 
+                                    (de_softc[ifp->if_unit].ds_addr);
+                       } else {
+                               de_setaddr(ina->x_host.c_host,ifp->if_unit);
+                       }
+                       break;
+                   }
+#endif
+               }
                break;
 
        default:
                break;
 
        default:
@@ -971,16 +1054,31 @@ deioctl(ifp, cmd, data)
        return (error);
 }
 
        return (error);
 }
 
-desetaddr(ifp, sin)
-       register struct ifnet *ifp;
-       register struct sockaddr_in *sin;
+/*
+ * set ethernet address for unit
+ */
+de_setaddr(physaddr, unit)
+u_char *physaddr;
+int unit;
 {
 {
-
-       ifp->if_addr = *(struct sockaddr *)sin;
-       ifp->if_net = in_netof(sin->sin_addr);
-       ifp->if_host[0] = in_lnaof(sin->sin_addr);
-       sin = (struct sockaddr_in *)&ifp->if_broadaddr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
-       ifp->if_flags |= IFF_BROADCAST;
+       register struct de_softc *ds = &de_softc[unit];
+       register struct uba_device *ui = deinfo[unit];
+       register struct dedevice *addr= (struct dedevice *)ui->ui_addr;
+       int csr0;
+       
+       if (! (ds->ds_flags & DSF_RUNNING))
+               return;
+               
+       bcopy(physaddr, &ds->ds_pcbb.pcbb2, 6);
+       ds->ds_pcbb.pcbb0 = FC_WTPHYAD;
+       addr->pclow = PCSR0_INTE|CMD_PDMD;
+       csr0 = addr->pcsr0;
+       addr->pchigh = csr0 >> 8;
+       if (csr0 & PCSR0_PCEI)
+               printf("de%d: wtphyad failed, csr0=%b csr1=%b\n", 
+                   ui->ui_unit, csr0, PCSR0_BITS, 
+                   addr->pcsr1, PCSR1_BITS);
 }
 }
+
+#endif
+