ioctls
[unix-history] / usr / src / sys / vax / if / if_ec.c
index e13e91f..50d094e 100644 (file)
@@ -1,20 +1,21 @@
-/*     if_ec.c 4.24    82/10/10        */
+/*     if_ec.c 4.35    83/06/12        */
 
 #include "ec.h"
 
 /*
  * 3Com Ethernet Controller interface
  */
 
 #include "ec.h"
 
 /*
  * 3Com Ethernet Controller interface
  */
+#include "../machine/pte.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/mbuf.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "../h/mbuf.h"
-#include "../h/pte.h"
 #include "../h/buf.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/vmmac.h"
 #include "../h/buf.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/vmmac.h"
-#include <errno.h>
+#include "../h/ioctl.h"
+#include "../h/errno.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
 #include "../netinet/in_systm.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
 #include "../netinet/in_systm.h"
 #include "../netinet/ip.h"
 #include "../netinet/ip_var.h"
+#include "../netinet/if_ether.h"
 #include "../netpup/pup.h"
 
 #include "../vax/cpu.h"
 #include "../vax/mtpr.h"
 #include "../netpup/pup.h"
 
 #include "../vax/cpu.h"
 #include "../vax/mtpr.h"
-#include "../vaxif/if_ec.h"
 #include "../vaxif/if_ecreg.h"
 #include "../vaxif/if_uba.h"
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/ubavar.h"
 
 #include "../vaxif/if_ecreg.h"
 #include "../vaxif/if_uba.h"
 #include "../vaxuba/ubareg.h"
 #include "../vaxuba/ubavar.h"
 
-#define        ECMTU   1500
 #define        ECMEM   0000000
 
 int    ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
 #define        ECMEM   0000000
 
 int    ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
@@ -41,11 +41,10 @@ struct      uba_device *ecinfo[NEC];
 u_short ecstd[] = { 0 };
 struct uba_driver ecdriver =
        { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo };
 u_short ecstd[] = { 0 };
 struct uba_driver ecdriver =
        { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo };
-u_char ec_iltop[3] = { 0x02, 0x07, 0x01 };
 #define        ECUNIT(x)       minor(x)
 
 #define        ECUNIT(x)       minor(x)
 
-int    ecinit(),ecoutput(),ecreset();
-struct mbuf *ecget();
+int    ecinit(),ecioctl(),ecoutput(),ecreset();
+struct mbuf *ecget();
 
 extern struct ifnet loif;
 
 
 extern struct ifnet loif;
 
@@ -62,12 +61,13 @@ extern struct ifnet loif;
  * efficiently.
  */
 struct ec_softc {
  * efficiently.
  */
 struct ec_softc {
-       struct  ifnet es_if;            /* network-visible interface */
+       struct  arpcom es_ac;           /* common Ethernet structures */
+#define        es_if   es_ac.ac_if             /* network-visible interface */
+#define        es_addr es_ac.ac_enaddr         /* hardware Ethernet address */
        struct  ifuba es_ifuba;         /* UNIBUS resources */
        short   es_mask;                /* mask for current output delay */
        short   es_oactive;             /* is output active? */
        struct  ifuba es_ifuba;         /* UNIBUS resources */
        short   es_mask;                /* mask for current output delay */
        short   es_oactive;             /* is output active? */
-       caddr_t es_buf[16];             /* virtual addresses of buffers */
-       u_char  es_enaddr[6];           /* board's ethernet address */
+       u_char  *es_buf[16];            /* virtual addresses of buffers */
 } ec_softc[NEC];
 
 /*
 } ec_softc[NEC];
 
 /*
@@ -93,15 +93,15 @@ ecprobe(reg)
         * Disable map registers for ec unibus space,
         * but don't allocate yet.
         */
         * Disable map registers for ec unibus space,
         * but don't allocate yet.
         */
-       ubamem(numuba, ECMEM, 32*2, 0);
+       (void) ubamem(numuba, ECMEM, 32*2, 0);
        /*
         * Check for existence of buffers on Unibus.
         */
        /*
         * Check for existence of buffers on Unibus.
         */
-       if (badaddr((caddr_t) ecbuf, 2)) {
+       if (badaddr((caddr_t)ecbuf, 2)) {
        bad1:
                printf("ec: buffer mem not found\n");
        bad2:
        bad1:
                printf("ec: buffer mem not found\n");
        bad2:
-               ubamem(numuba, 0, 0, 0);        /* reenable map (780 only) */
+               (void) ubamem(numuba, 0, 0, 0); /* reenable map (780 only) */
                addr->ec_rcr = EC_MDISAB;       /* disable memory */
                return (0);
        }
                addr->ec_rcr = EC_MDISAB;       /* disable memory */
                return (0);
        }
@@ -161,15 +161,14 @@ ecattach(ui)
 
        ifp->if_unit = ui->ui_unit;
        ifp->if_name = "ec";
 
        ifp->if_unit = ui->ui_unit;
        ifp->if_name = "ec";
-       ifp->if_mtu = ECMTU;
-       ifp->if_net = ui->ui_flags;
+       ifp->if_mtu = ETHERMTU;
 
        /*
         * Read the ethernet address off the board, one nibble at a time.
         */
        addr->ec_xcr = EC_UECLR;
        addr->ec_rcr = EC_AROM;
 
        /*
         * Read the ethernet address off the board, one nibble at a time.
         */
        addr->ec_xcr = EC_UECLR;
        addr->ec_rcr = EC_AROM;
-       cp = es->es_enaddr;
+       cp = es->es_addr;
 #define        NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
        for (i=0; i<6; i++) {
                *cp = 0;
 #define        NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
        for (i=0; i<6; i++) {
                *cp = 0;
@@ -179,28 +178,15 @@ ecattach(ui)
                }
                cp++;
        }
                }
                cp++;
        }
-#ifdef notdef
-       printf("ec%d: addr=%x:%x:%x:%x:%x:%x\n", ui->ui_unit,
-               es->es_enaddr[0]&0xff, es->es_enaddr[1]&0xff,
-               es->es_enaddr[2]&0xff, es->es_enaddr[3]&0xff,
-               es->es_enaddr[4]&0xff, es->es_enaddr[5]&0xff);
-#endif
-       ifp->if_host[0] = ((es->es_enaddr[3]&0xff)<<16) |
-           ((es->es_enaddr[4]&0xff)<<8) | (es->es_enaddr[5]&0xff);
        sin = (struct sockaddr_in *)&es->es_if.if_addr;
        sin->sin_family = AF_INET;
        sin = (struct sockaddr_in *)&es->es_if.if_addr;
        sin->sin_family = AF_INET;
-       sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]);
-
-       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;
-
+       sin->sin_addr = arpmyaddr((struct arpcom *)0);
        ifp->if_init = ecinit;
        ifp->if_init = ecinit;
+       ifp->if_ioctl = ecioctl;
        ifp->if_output = ecoutput;
        ifp->if_output = ecoutput;
-       ifp->if_ubareset = ecreset;
+       ifp->if_reset = ecreset;
        for (i=0; i<16; i++)
        for (i=0; i<16; i++)
-               es->es_buf[i] = &umem[ui->ui_ubanum][ECMEM+2048*i];
+               es->es_buf[i] = (u_char *)&umem[ui->ui_ubanum][ECMEM+2048*i];
        if_attach(ifp);
 }
 
        if_attach(ifp);
 }
 
@@ -217,7 +203,7 @@ ecreset(unit, uban)
            ui->ui_ubanum != uban)
                return;
        printf(" ec%d", unit);
            ui->ui_ubanum != uban)
                return;
        printf(" ec%d", unit);
-       ubamem(uban, ECMEM, 32*2, 0);   /* map register disable (no alloc) */
+       (void) ubamem(uban, ECMEM, 32*2, 0);    /* mr disable (no alloc) */
        ecinit(unit);
 }
 
        ecinit(unit);
 }
 
@@ -230,24 +216,34 @@ ecinit(unit)
 {
        struct ec_softc *es = &ec_softc[unit];
        struct ecdevice *addr;
 {
        struct ec_softc *es = &ec_softc[unit];
        struct ecdevice *addr;
+       register struct ifnet *ifp = &es->es_if;
+       register struct sockaddr_in *sin, *sinb;
        int i, s;
 
        int i, s;
 
+       sin = (struct sockaddr_in *)&ifp->if_addr;
+       if (sin->sin_addr.s_addr == 0)          /* address still unknown */
+               return;
+
        /*
         * Hang receive buffers and start any pending writes.
         * Writing into the rcr also makes sure the memory
         * is turned on.
         */
        /*
         * Hang receive buffers and start any pending writes.
         * Writing into the rcr also makes sure the memory
         * is turned on.
         */
-       addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
-       s = splimp();
-       for (i=ECRHBF; i>=ECRLBF; i--)
-               addr->ec_rcr = EC_READ|i;
-       es->es_oactive = 0;
-       es->es_mask = ~0;
-       es->es_if.if_flags |= IFF_UP;
-       if (es->es_if.if_snd.ifq_head)
-               ecstart(unit);
-       splx(s);
+       if ((es->es_if.if_flags & IFF_RUNNING) == 0) {
+               addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
+               s = splimp();
+               for (i = ECRHBF; i >= ECRLBF; i--)
+                       addr->ec_rcr = EC_READ | i;
+               es->es_oactive = 0;
+               es->es_mask = ~0;
+               es->es_if.if_flags |= IFF_UP|IFF_RUNNING;
+               if (es->es_if.if_snd.ifq_head)
+                       ecstart(unit);
+               splx(s);
+       }
        if_rtinit(&es->es_if, RTF_UP);
        if_rtinit(&es->es_if, RTF_UP);
+       arpattach(&es->es_ac);
+       arpwhohas(&es->es_ac, &sin->sin_addr);
 }
 
 /*
 }
 
 /*
@@ -261,11 +257,10 @@ ecinit(unit)
 ecstart(dev)
        dev_t dev;
 {
 ecstart(dev)
        dev_t dev;
 {
-        int unit = ECUNIT(dev), dest;
+        int unit = ECUNIT(dev);
        struct ec_softc *es = &ec_softc[unit];
        struct ecdevice *addr;
        struct mbuf *m;
        struct ec_softc *es = &ec_softc[unit];
        struct ecdevice *addr;
        struct mbuf *m;
-       caddr_t ecbuf;
 
        if (es->es_oactive)
                goto restart;
 
        if (es->es_oactive)
                goto restart;
@@ -399,17 +394,17 @@ ecread(unit)
 {
        register struct ec_softc *es = &ec_softc[unit];
        struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
 {
        register struct ec_softc *es = &ec_softc[unit];
        struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
-       register struct ec_header *ec;
+       register struct ether_header *ec;
        struct mbuf *m;
        struct mbuf *m;
-       int len, off, resid, ecoff, buf;
+       int len, off, resid, ecoff, rbuf;
        register struct ifqueue *inq;
        register struct ifqueue *inq;
-       caddr_t ecbuf;
+       u_char *ecbuf;
 
        es->es_if.if_ipackets++;
 
        es->es_if.if_ipackets++;
-       buf = addr->ec_rcr & EC_RBN;
-       if (buf < ECRLBF || buf > ECRHBF)
+       rbuf = addr->ec_rcr & EC_RBN;
+       if (rbuf < ECRLBF || rbuf > ECRHBF)
                panic("ecrint");
                panic("ecrint");
-       ecbuf = es->es_buf[buf];
+       ecbuf = es->es_buf[rbuf];
        ecoff = *(short *)ecbuf;
        if (ecoff <= ECRDOFF || ecoff > 2046) {
                es->es_if.if_ierrors++;
        ecoff = *(short *)ecbuf;
        if (ecoff <= ECRDOFF || ecoff > 2046) {
                es->es_if.if_ierrors++;
@@ -427,16 +422,17 @@ ecread(unit)
         * get true type from first 16-bit word past data.
         * Remember that type was trailer by setting off.
         */
         * get true type from first 16-bit word past data.
         * Remember that type was trailer by setting off.
         */
-       len = ecoff - ECRDOFF - sizeof (struct ec_header);
-       ec = (struct ec_header *)(ecbuf + ECRDOFF);
+       len = ecoff - ECRDOFF - sizeof (struct ether_header);
+       ec = (struct ether_header *)(ecbuf + ECRDOFF);
+       ec->ether_type = ntohs((u_short)ec->ether_type);
 #define        ecdataaddr(ec, off, type)       ((type)(((caddr_t)((ec)+1)+(off))))
 #define        ecdataaddr(ec, off, type)       ((type)(((caddr_t)((ec)+1)+(off))))
-       if (ec->ec_type >= ECPUP_TRAIL &&
-           ec->ec_type < ECPUP_TRAIL+ECPUP_NTRAILER) {
-               off = (ec->ec_type - ECPUP_TRAIL) * 512;
-               if (off >= ECMTU)
+       if (ec->ether_type >= ETHERPUP_TRAIL &&
+           ec->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) {
+               off = (ec->ether_type - ETHERPUP_TRAIL) * 512;
+               if (off >= ETHERMTU)
                        goto setup;             /* sanity */
                        goto setup;             /* sanity */
-               ec->ec_type = *ecdataaddr(ec, off, u_short *);
-               resid = *(ecdataaddr(ec, off+2, u_short *));
+               ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *));
+               resid = ntohs(*(ecdataaddr(ec, off+2, u_short *)));
                if (off + resid > len)
                        goto setup;             /* sanity */
                len = off + resid;
                if (off + resid > len)
                        goto setup;             /* sanity */
                len = off + resid;
@@ -458,13 +454,17 @@ ecread(unit)
                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);
        }
-       switch (ec->ec_type) {
+       switch (ec->ether_type) {
 
 #ifdef INET
 
 #ifdef INET
-       case ECPUP_IPTYPE:
+       case ETHERPUP_IPTYPE:
                schednetisr(NETISR_IP);
                inq = &ipintrq;
                break;
                schednetisr(NETISR_IP);
                inq = &ipintrq;
                break;
+
+       case ETHERPUP_ARPTYPE:
+               arpinput(&es->es_ac, m);
+               return;
 #endif
        default:
                m_freem(m);
 #endif
        default:
                m_freem(m);
@@ -482,7 +482,7 @@ setup:
        /*
         * Reset for next packet.
         */
        /*
         * Reset for next packet.
         */
-       addr->ec_rcr = EC_READ|EC_RCLR|buf;
+       addr->ec_rcr = EC_READ|EC_RCLR|rbuf;
 }
 
 /*
 }
 
 /*
@@ -499,40 +499,47 @@ ecoutput(ifp, m0, dst)
        struct mbuf *m0;
        struct sockaddr *dst;
 {
        struct mbuf *m0;
        struct sockaddr *dst;
 {
-       int type, dest, s, error;
+       int type, s, error;
+       u_char edst[6];
+       struct in_addr idst;
        register struct ec_softc *es = &ec_softc[ifp->if_unit];
        register struct mbuf *m = m0;
        register struct ec_softc *es = &ec_softc[ifp->if_unit];
        register struct mbuf *m = m0;
-       register struct ec_header *ec;
-       register int off, i;
-       struct mbuf *mcopy = (struct mbuf *) 0;         /* Null */
+       register struct ether_header *ec;
+       register int off;
+       struct mbuf *mcopy = (struct mbuf *)0;
 
        switch (dst->sa_family) {
 
 #ifdef INET
        case AF_INET:
 
        switch (dst->sa_family) {
 
 #ifdef INET
        case AF_INET:
-               dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
-               if ((dest &~ 0xff) == 0)
-                       mcopy = m_copy(m, 0, M_COPYALL);
-               else if (dest == ((struct sockaddr_in *)&es->es_if.if_addr)->
-                   sin_addr.s_addr) {
-                       mcopy = m;
-                       goto gotlocal;
-               }
+               idst = ((struct sockaddr_in *)dst)->sin_addr;
+               if (!arpresolve(&es->es_ac, m, &idst, edst))
+                       return (0);     /* if not yet resolved */
+               if (in_lnaof(idst) == INADDR_ANY)
+                       mcopy = m_copy(m, 0, (int)M_COPYALL);
                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                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)) {
                if (off > 0 && (off & 0x1ff) == 0 &&
                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
-                       type = ECPUP_TRAIL + (off>>9);
+                       type = ETHERPUP_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 *) = ECPUP_IPTYPE;
-                       *(mtod(m, u_short *) + 1) = m->m_len;
+                       *mtod(m, u_short *) = ntohs((u_short)ETHERPUP_IPTYPE);
+                       *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len);
                        goto gottrailertype;
                }
                        goto gottrailertype;
                }
-               type = ECPUP_IPTYPE;
+               type = ETHERPUP_IPTYPE;
                off = 0;
                goto gottype;
 #endif
 
                off = 0;
                goto gottype;
 #endif
 
+       case AF_UNSPEC:
+               ec = (struct ether_header *)dst->sa_data;
+               bcopy((caddr_t)ec->ether_dhost, (caddr_t)edst, sizeof (edst));
+               type = ec->ether_type;
+               goto gottype;
+
        default:
                printf("ec%d: can't handle af%d\n", ifp->if_unit,
                        dst->sa_family);
        default:
                printf("ec%d: can't handle af%d\n", ifp->if_unit,
                        dst->sa_family);
@@ -558,41 +565,23 @@ gottype:
         * allocate another.
         */
        if (m->m_off > MMAXOFF ||
         * allocate another.
         */
        if (m->m_off > MMAXOFF ||
-           MMINOFF + sizeof (struct ec_header) > m->m_off) {
-               m = m_get(M_DONTWAIT);
+           MMINOFF + sizeof (struct ether_header) > m->m_off) {
+               m = m_get(M_DONTWAIT, MT_HEADER);
                if (m == 0) {
                        error = ENOBUFS;
                        goto bad;
                }
                m->m_next = m0;
                m->m_off = MMINOFF;
                if (m == 0) {
                        error = ENOBUFS;
                        goto bad;
                }
                m->m_next = m0;
                m->m_off = MMINOFF;
-               m->m_len = sizeof (struct ec_header);
+               m->m_len = sizeof (struct ether_header);
        } else {
        } else {
-               m->m_off -= sizeof (struct ec_header);
-               m->m_len += sizeof (struct ec_header);
+               m->m_off -= sizeof (struct ether_header);
+               m->m_len += sizeof (struct ether_header);
        }
        }
-       ec = mtod(m, struct ec_header *);
-       for (i=0; i<6; i++)
-               ec->ec_shost[i] = es->es_enaddr[i];
-       if ((dest &~ 0xff) == 0)
-               /* broadcast address */
-               for (i=0; i<6; i++)
-                       ec->ec_dhost[i] = 0xff;
-       else {
-               if (dest & 0x8000) {
-                       ec->ec_dhost[0] = ec_iltop[0];
-                       ec->ec_dhost[1] = ec_iltop[1];
-                       ec->ec_dhost[2] = ec_iltop[2];
-               } else {
-                       ec->ec_dhost[0] = es->es_enaddr[0];
-                       ec->ec_dhost[1] = es->es_enaddr[1];
-                       ec->ec_dhost[2] = es->es_enaddr[2];
-               }
-               ec->ec_dhost[3] = (dest>>8) & 0x7f;
-               ec->ec_dhost[4] = (dest>>16) & 0xff;
-               ec->ec_dhost[5] = (dest>>24) & 0xff;
-       }
-       ec->ec_type = type;
+       ec = mtod(m, struct ether_header *);
+       bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst));
+       ec->ether_type = htons((u_short)type);
+       bcopy((caddr_t)es->es_addr, (caddr_t)ec->ether_shost, 6);
 
        /*
         * Queue message on interface, and start output if interface
 
        /*
         * Queue message on interface, and start output if interface
@@ -608,21 +597,22 @@ gottype:
        if (es->es_oactive == 0)
                ecstart(ifp->if_unit);
        splx(s);
        if (es->es_oactive == 0)
                ecstart(ifp->if_unit);
        splx(s);
-
-gotlocal:
-       return(mcopy ? looutput(&loif, mcopy, dst) : 0);
+       return (mcopy ? looutput(&loif, mcopy, dst) : 0);
 
 qfull:
        m0 = m;
        splx(s);
 bad:
        m_freem(m0);
 
 qfull:
        m0 = m;
        splx(s);
 bad:
        m_freem(m0);
-       return(error);
+       return (error);
 }
 
 /*
 }
 
 /*
- * Routine to copy from mbuf chain to transmitter
+ * Routine to copy from mbuf chain to transmit
  * buffer in UNIBUS memory.
  * buffer in UNIBUS memory.
+ * 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.
  */
 ecput(ecbuf, m)
        u_char *ecbuf;
  */
 ecput(ecbuf, m)
        u_char *ecbuf;
@@ -634,6 +624,8 @@ ecput(ecbuf, m)
 
        for (off = 2048, mp = m; mp; mp = mp->m_next)
                off -= mp->m_len;
 
        for (off = 2048, mp = m; mp; mp = mp->m_next)
                off -= mp->m_len;
+       if (2048 - off < ETHERMIN + sizeof (struct ether_header))
+               off = 2048 - ETHERMIN - sizeof (struct ether_header);
        *(u_short *)ecbuf = off;
        bp = (u_char *)(ecbuf + off);
        for (mp = m; mp; mp = mp->m_next) {
        *(u_short *)ecbuf = off;
        bp = (u_char *)(ecbuf + off);
        for (mp = m; mp; mp = mp->m_next) {
@@ -661,10 +653,6 @@ ecput(ecbuf, m)
                if (len & 01)
                        *bp++ = *mcp++;
        }
                if (len & 01)
                        *bp++ = *mcp++;
        }
-#ifdef notdef
-       if (bp - ecbuf != 2048)
-               printf("ec: bad ecput, diff=%d\n", bp-ecbuf);
-#endif
        m_freem(m);
 }
 
        m_freem(m);
 }
 
@@ -685,17 +673,18 @@ ecget(ecbuf, totlen, off0)
        register int off = off0, len;
        u_char *cp;
 
        register int off = off0, len;
        u_char *cp;
 
-       cp = ecbuf + ECRDOFF + sizeof (struct ec_header);
+       cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
        while (totlen > 0) {
                register int words;
                u_char *mcp;
 
        while (totlen > 0) {
                register int words;
                u_char *mcp;
 
-               MGET(m, 0);
+               MGET(m, M_DONTWAIT, MT_DATA);
                if (m == 0)
                        goto bad;
                if (off) {
                        len = totlen - off;
                if (m == 0)
                        goto bad;
                if (off) {
                        len = totlen - off;
-                       cp = ecbuf + ECRDOFF + sizeof (struct ec_header) + off;
+                       cp = ecbuf + ECRDOFF +
+                               sizeof (struct ether_header) + off;
                } else
                        len = totlen;
                if (len >= CLBYTES) {
                } else
                        len = totlen;
                if (len >= CLBYTES) {
@@ -735,7 +724,7 @@ ecget(ecbuf, totlen, off0)
                }
                off += len;
                if (off == totlen) {
                }
                off += len;
                if (off == totlen) {
-                       cp = ecbuf + ECRDOFF + sizeof (struct ec_header);
+                       cp = ecbuf + ECRDOFF + sizeof (struct ether_header);
                        off = 0;
                        totlen = off0;
                }
                        off = 0;
                        totlen = off0;
                }
@@ -745,3 +734,37 @@ bad:
        m_freem(top);
        return (0);
 }
        m_freem(top);
        return (0);
 }
+
+/*
+ * Process an ioctl request.
+ */
+ecioctl(ifp, cmd, data)
+       register struct ifnet *ifp;
+       int cmd;
+       caddr_t data;
+{
+       register struct ifreq *ifr = (struct ifreq *)data;
+       register struct sockaddr_in *sin;
+       int s = splimp(), error = 0;
+
+       switch (cmd) {
+
+       case SIOCSIFADDR:
+               if (ifp->if_flags & IFF_RUNNING)
+                       if_rtinit(ifp, -1);     /* delete previous route */
+               ifp->if_addr = ifr->ifr_addr;
+               ifp->if_net = in_netof(ifr->ifr_addr);
+               ifp->if_host[0] = in_lnaof(ifr->ifr_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;
+               ecinit(ifp->if_unit);
+               break;
+
+       default:
+               error = EINVAL;
+       }
+       splx(s);
+       return (error);
+}