merge 4.1b with 4.1c
[unix-history] / usr / src / sys / vax / if / if_ec.c
index 7c3794e..97526b4 100644 (file)
@@ -1,8 +1,6 @@
-/*     if_ec.c 4.5     82/04/14        */
+/*     if_ec.c 4.29    82/11/13        */
 
 #include "ec.h"
 
 #include "ec.h"
-#include "imp.h"
-#include "loop.h"
 
 /*
  * 3Com Ethernet Controller interface
 
 /*
  * 3Com Ethernet Controller interface
 #include "../h/buf.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/buf.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
-#include "../h/ubareg.h"
-#include "../h/ubavar.h"
-#include "../h/ecreg.h"
-#include "../h/cpu.h"
-#include "../h/mtpr.h"
 #include "../h/vmmac.h"
 #include "../h/vmmac.h"
-#include "../net/in.h"
-#include "../net/in_systm.h"
+#include <errno.h>
+
 #include "../net/if.h"
 #include "../net/if.h"
-#include "../net/if_ec.h"
-#include "../net/if_uba.h"
-#include "../net/ip.h"
-#include "../net/ip_var.h"
-#include "../net/pup.h"
+#include "../net/netisr.h"
 #include "../net/route.h"
 #include "../net/route.h"
-#include <errno.h>
+#include "../netinet/in.h"
+#include "../netinet/in_systm.h"
+#include "../netinet/ip.h"
+#include "../netinet/ip_var.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"
 
 #define        ECMTU   1500
 
 #define        ECMTU   1500
+#define        ECMIN   (60-14)
+#define        ECMEM   0000000
 
 int    ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
 struct uba_device *ecinfo[NEC];
 u_short ecstd[] = { 0 };
 struct uba_driver ecdriver =
        { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo };
 
 int    ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();
 struct uba_device *ecinfo[NEC];
 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)
 
 int    ecinit(),ecoutput(),ecreset();
 #define        ECUNIT(x)       minor(x)
 
 int    ecinit(),ecoutput(),ecreset();
-struct mbuf *ecget();
+struct mbuf *ecget();
 
 extern struct ifnet loif;
 
 
 extern struct ifnet loif;
 
@@ -62,12 +66,8 @@ struct       ec_softc {
        struct  ifnet es_if;            /* network-visible interface */
        struct  ifuba es_ifuba;         /* UNIBUS resources */
        short   es_mask;                /* mask for current output delay */
        struct  ifnet es_if;            /* network-visible interface */
        struct  ifuba es_ifuba;         /* UNIBUS resources */
        short   es_mask;                /* mask for current output delay */
-#ifdef notdef
-       short   es_delay;               /* current output delay */
-       long    es_lastx;               /* host last transmitted to */
-#endif
        short   es_oactive;             /* is output active? */
        short   es_oactive;             /* is output active? */
-       caddr_t es_buf[16];             /* virtual addresses of buffers */
+       u_char  *es_buf[16];            /* virtual addresses of buffers */
        u_char  es_enaddr[6];           /* board's ethernet address */
 } ec_softc[NEC];
 
        u_char  es_enaddr[6];           /* board's ethernet address */
 } ec_softc[NEC];
 
@@ -80,27 +80,47 @@ ecprobe(reg)
 {
        register int br, cvec;          /* r11, r10 value-result */
        register struct ecdevice *addr = (struct ecdevice *)reg;
 {
        register int br, cvec;          /* r11, r10 value-result */
        register struct ecdevice *addr = (struct ecdevice *)reg;
-       register caddr_t ecbuf = (caddr_t) &umem[0][0600000];
+       register caddr_t ecbuf = (caddr_t) &umem[numuba][ECMEM];
 
 
-COUNT(ECPROBE);
 #ifdef lint
        br = 0; cvec = br; br = cvec;
        ecrint(0); ecxint(0); eccollide(0);
 #endif
 #ifdef lint
        br = 0; cvec = br; br = cvec;
        ecrint(0); ecxint(0); eccollide(0);
 #endif
+       /*
+        * Make sure memory is turned on
+        */
+       addr->ec_rcr = EC_AROM;
+       /*
+        * Disable map registers for ec unibus space,
+        * but don't allocate yet.
+        */
+       (void) ubamem(numuba, ECMEM, 32*2, 0);
        /*
         * Check for existence of buffers on Unibus.
        /*
         * Check for existence of buffers on Unibus.
-        * This won't work on a 780 until more work is done.
         */
         */
-       if (badaddr((caddr_t) ecbuf, 2)) {
-               printf("ec: buffer mem not found");
+       if (badaddr((caddr_t)ecbuf, 2)) {
+       bad1:
+               printf("ec: buffer mem not found\n");
+       bad2:
+               (void) ubamem(numuba, 0, 0, 0); /* reenable map (780 only) */
+               addr->ec_rcr = EC_MDISAB;       /* disable memory */
                return (0);
        }
                return (0);
        }
+#if VAX780
+       if (cpu == VAX_780 && uba_hd[numuba].uh_uba->uba_sr) {
+               uba_hd[numuba].uh_uba->uba_sr = uba_hd[numuba].uh_uba->uba_sr;
+               goto bad1;
+       }
+#endif
 
        /*
         * Tell the system that the board has memory here, so it won't
         * attempt to allocate the addresses later.
         */
 
        /*
         * Tell the system that the board has memory here, so it won't
         * attempt to allocate the addresses later.
         */
-       ubamem(0, 0600000, 32*2);
+       if (ubamem(numuba, ECMEM, 32*2, 1) == 0) {
+               printf("ecprobe: cannot reserve uba addresses\n");
+               goto bad2;
+       }
 
        /*
         * Make a one byte packet in what should be buffer #0.
 
        /*
         * Make a one byte packet in what should be buffer #0.
@@ -113,9 +133,15 @@ COUNT(ECPROBE);
        addr->ec_xcr = EC_XINTEN|EC_XWBN;
        DELAY(100000);
        addr->ec_xcr = EC_XCLR;
        addr->ec_xcr = EC_XINTEN|EC_XWBN;
        DELAY(100000);
        addr->ec_xcr = EC_XCLR;
-       if (cvec > 0 && cvec != 0x200)
-               cvec -= 010;
-               br += 2;
+       if (cvec > 0 && cvec != 0x200) {
+               if (cvec & 04) {        /* collision interrupt */
+                       cvec -= 04;
+                       br += 1;                /* rcv is collision + 1 */
+               } else {                /* xmit interrupt */
+                       cvec -= 010;
+                       br += 2;                /* rcv is xmit + 2 */
+               }
+       }
        return (1);
 }
 
        return (1);
 }
 
@@ -127,66 +153,56 @@ COUNT(ECPROBE);
 ecattach(ui)
        struct uba_device *ui;
 {
 ecattach(ui)
        struct uba_device *ui;
 {
-       register struct ec_softc *es = &ec_softc[ui->ui_unit];
-       register struct sockaddr_in *sin;
+       struct ec_softc *es = &ec_softc[ui->ui_unit];
+       register struct ifnet *ifp = &es->es_if;
        register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
        register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
-       register int i, j;
-       register u_char *cp;
-COUNT(ECATTACH);
+       struct sockaddr_in *sin;
+       int i, j;
+       u_char *cp;
 
 
-       es->es_if.if_unit = ui->ui_unit;
-       es->es_if.if_name = "ec";
-       es->es_if.if_mtu = ECMTU;
-       es->es_if.if_net = ui->ui_flags & 0xff;
+       ifp->if_unit = ui->ui_unit;
+       ifp->if_name = "ec";
+       ifp->if_mtu = ECMTU;
+       ifp->if_net = ui->ui_flags;
 
        /*
 
        /*
-        * Read the ethernet address off the board,
-        * one nibble at a time!
+        * 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;
         */
        addr->ec_xcr = EC_UECLR;
        addr->ec_rcr = EC_AROM;
        cp = es->es_enaddr;
+#define        NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM
        for (i=0; i<6; i++) {
                *cp = 0;
                for (j=0; j<=4; j+=4) {
                        *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
        for (i=0; i<6; i++) {
                *cp = 0;
                for (j=0; j<=4; j+=4) {
                        *cp |= ((addr->ec_rcr >> 8) & 0xf) << j;
-                       addr->ec_rcr = EC_AROM|EC_ASTEP;
-                       addr->ec_rcr = EC_AROM;
-                       addr->ec_rcr = EC_AROM|EC_ASTEP;
-                       addr->ec_rcr = EC_AROM;
-                       addr->ec_rcr = EC_AROM|EC_ASTEP;
-                       addr->ec_rcr = EC_AROM;
-                       addr->ec_rcr = EC_AROM|EC_ASTEP;
-                       addr->ec_rcr = EC_AROM;
+                       NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;
                }
                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);
        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);
-       es->es_if.if_host[0] = ((es->es_enaddr[3]&0xff)<<16) |
+#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;
            ((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->sin_addr = if_makeaddr(es->es_if.if_net, es->es_if.if_host[0]);
+       sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]);
 
 
-       sin = (struct sockaddr_in *)&es->es_if.if_broadaddr;
+       sin = (struct sockaddr_in *)&ifp->if_broadaddr;
        sin->sin_family = AF_INET;
        sin->sin_family = AF_INET;
-       sin->sin_addr = if_makeaddr(es->es_if.if_net, 0);
-       es->es_if.if_flags = IFF_BROADCAST;
+       sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY);
+       ifp->if_flags = IFF_BROADCAST;
 
 
-       es->es_if.if_init = ecinit;
-       es->es_if.if_output = ecoutput;
-       es->es_if.if_ubareset = ecreset;
+       ifp->if_init = ecinit;
+       ifp->if_output = ecoutput;
+       ifp->if_reset = ecreset;
        for (i=0; i<16; i++)
        for (i=0; i<16; i++)
-               es->es_buf[i] = &umem[ui->ui_ubanum][0600000+2048*i];
-       if_attach(&es->es_if);
-#if NIMP == 0
-       /* here's one for you john baby.... */
-       if (ui->ui_flags &~ 0xff)
-               eclhinit((ui->ui_flags &~ 0xff) | 0x0a);
-#endif
+               es->es_buf[i] = (u_char *)&umem[ui->ui_ubanum][ECMEM+2048*i];
+       if_attach(ifp);
 }
 
 /*
 }
 
 /*
@@ -197,12 +213,12 @@ ecreset(unit, uban)
        int unit, uban;
 {
        register struct uba_device *ui;
        int unit, uban;
 {
        register struct uba_device *ui;
-COUNT(ECRESET);
 
        if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||
            ui->ui_ubanum != uban)
                return;
        printf(" ec%d", unit);
 
        if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||
            ui->ui_ubanum != uban)
                return;
        printf(" ec%d", unit);
+       (void) ubamem(uban, ECMEM, 32*2, 0);    /* mr disable (no alloc) */
        ecinit(unit);
 }
 
        ecinit(unit);
 }
 
@@ -213,42 +229,28 @@ COUNT(ECRESET);
 ecinit(unit)
        int unit;
 {
 ecinit(unit)
        int unit;
 {
-       register struct ec_softc *es = &ec_softc[unit];
-       register struct uba_device *ui = ecinfo[unit];
-       register struct ecdevice *addr;
-       register i;
-       int s;
-
-#ifdef notdef
-       if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
-           sizeof (struct ec_header), (int)btoc(ECMTU)) == 0) { 
-               printf("ec%d: can't initialize\n", unit);
-               es->es_if.if_flags &= ~IFF_UP;
-               return;
-       }
-#endif
-       addr = (struct ecdevice *)ui->ui_addr;
+       struct ec_softc *es = &ec_softc[unit];
+       struct ecdevice *addr;
+       int i, s;
 
        /*
 
        /*
-        * Hang receive buffers and start any pending
-        * writes by faking a transmit complete.
+        * 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;
        s = splimp();
        for (i=ECRHBF; i>=ECRLBF; i--)
                addr->ec_rcr = EC_READ|i;
-       es->es_oactive = 1;
+       es->es_oactive = 0;
+       es->es_mask = ~0;
        es->es_if.if_flags |= IFF_UP;
        es->es_if.if_flags |= IFF_UP;
-       ecxint(unit);
+       if (es->es_if.if_snd.ifq_head)
+               ecstart(unit);
        splx(s);
        splx(s);
-       if_rtinit(&es->es_if, RTF_DIRECT|RTF_UP);
+       if_rtinit(&es->es_if, RTF_UP);
 }
 
 }
 
-#ifdef notdef
-int    enalldelay = 0;
-int    eclastdel = 25;
-int    enlastmask = (~0) << 5;
-#endif
-
 /*
  * Start or restart output on interface.
  * If interface is already active, then this is a retransmit
 /*
  * Start or restart output on interface.
  * If interface is already active, then this is a retransmit
@@ -261,53 +263,22 @@ ecstart(dev)
        dev_t dev;
 {
         int unit = ECUNIT(dev);
        dev_t dev;
 {
         int unit = ECUNIT(dev);
-       struct uba_device *ui = ecinfo[unit];
-       register struct ec_softc *es = &ec_softc[unit];
-       register struct ecdevice *addr;
+       struct ec_softc *es = &ec_softc[unit];
+       struct ecdevice *addr;
        struct mbuf *m;
        struct mbuf *m;
-       caddr_t ecbuf;
-       int dest;
-COUNT(ECSTART);
 
        if (es->es_oactive)
                goto restart;
 
 
        if (es->es_oactive)
                goto restart;
 
-       /*
-        * Not already active: dequeue another request
-        * and copy it into the buffer.  If no more requests,
-        * just return.
-        */
        IF_DEQUEUE(&es->es_if.if_snd, m);
        if (m == 0) {
                es->es_oactive = 0;
                return;
        }
        IF_DEQUEUE(&es->es_if.if_snd, m);
        if (m == 0) {
                es->es_oactive = 0;
                return;
        }
-#ifdef notdef
-       dest = mtod(m, struct ec_header *)->ec_dhost; /* wrong! */
-#endif
        ecput(es->es_buf[ECTBF], m);
 
        ecput(es->es_buf[ECTBF], m);
 
-#ifdef notdef
-       /*
-        * Ethernet cannot take back-to-back packets (no
-        * buffering in interface).  To avoid overrunning
-        * receivers, enforce a small delay (about 1ms) in interface:
-        *      * between all packets when ecalldelay
-        *      * whenever last packet was broadcast
-        *      * whenever this packet is to same host as last packet
-        */
-       if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {
-               es->es_delay = eclastdel;
-               es->es_mask = eclastmask;
-       }
-       es->es_lastx = dest;
-#endif
-
 restart:
 restart:
-       /*
-        * Start the output.
-        */
-       addr = (struct ecdevice *)ui->ui_addr;
+       addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
        addr->ec_xcr = EC_WRITE|ECTBF;
        es->es_oactive = 1;
 }
        addr->ec_xcr = EC_WRITE|ECTBF;
        es->es_oactive = 1;
 }
@@ -319,33 +290,25 @@ restart:
 ecxint(unit)
        int unit;
 {
 ecxint(unit)
        int unit;
 {
-       register struct uba_device *ui = ecinfo[unit];
        register struct ec_softc *es = &ec_softc[unit];
        register struct ec_softc *es = &ec_softc[unit];
-       register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;
-COUNT(ECXINT);
+       register struct ecdevice *addr =
+               (struct ecdevice *)ecinfo[unit]->ui_addr;
 
        if (es->es_oactive == 0)
                return;
 
        if (es->es_oactive == 0)
                return;
-       if (addr->ec_xcr&EC_XDONE == 0 || addr->ec_xcr&EC_XBN != ECTBF)
-               printf("ec%d: strange xmit interrupt!\n", unit);
+       if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) {
+               printf("ec%d: stray xmit interrupt, xcr=%b\n", unit,
+                       addr->ec_xcr, EC_XBITS);
+               es->es_oactive = 0;
+               addr->ec_xcr = EC_XCLR;
+               return;
+       }
        es->es_if.if_opackets++;
        es->es_oactive = 0;
        es->es_mask = ~0;
        addr->ec_xcr = EC_XCLR;
        es->es_if.if_opackets++;
        es->es_oactive = 0;
        es->es_mask = ~0;
        addr->ec_xcr = EC_XCLR;
-       /*
-        * There shouldn't ever be any mbuf's to free, but just in case...
-        */
-       if (es->es_ifuba.ifu_xtofree) {
-               m_freem(es->es_ifuba.ifu_xtofree);
-               es->es_ifuba.ifu_xtofree = 0;
-       }
-       if (es->es_if.if_snd.ifq_head == 0) {
-#ifdef notdef
-               es->es_lastx = 0; /* ? */
-#endif
-               return;
-       }
-       ecstart(unit);
+       if (es->es_if.if_snd.ifq_head)
+               ecstart(unit);
 }
 
 /*
 }
 
 /*
@@ -357,13 +320,10 @@ eccollide(unit)
        int unit;
 {
        struct ec_softc *es = &ec_softc[unit];
        int unit;
 {
        struct ec_softc *es = &ec_softc[unit];
-COUNT(ECCOLLIDE);
 
 
-       printf("ec%d: collision\n", unit);
        es->es_if.if_collisions++;
        es->es_if.if_collisions++;
-       if (es->es_oactive == 0)
-               return;
-       ecdocoll(unit);
+       if (es->es_oactive)
+               ecdocoll(unit);
 }
 
 ecdocoll(unit)
 }
 
 ecdocoll(unit)
@@ -413,14 +373,9 @@ ecdocoll(unit)
        /*
         * Clear the controller's collision flag, thus enabling retransmit.
         */
        /*
         * Clear the controller's collision flag, thus enabling retransmit.
         */
-       addr->ec_xcr = EC_JCLR;
+       addr->ec_xcr = EC_CLEAR;
 }
 
 }
 
-#ifdef notdef
-struct sockaddr_pup pupsrc = { AF_PUP };
-struct sockaddr_pup pupdst = { AF_PUP };
-struct sockproto pupproto = { PF_PUP };
-#endif
 /*
  * Ethernet interface receiver interrupt.
  * If input error just drop packet.
 /*
  * Ethernet interface receiver interrupt.
  * If input error just drop packet.
@@ -434,11 +389,7 @@ ecrint(unit)
        int unit;
 {
        struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
        int unit;
 {
        struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
-COUNT(ECRINT);
 
 
-#ifdef notdef
-       printf("ec%d: ecrint:%d\n", unit, addr->ec_rcr & 0xf);
-#endif
        while (addr->ec_rcr & EC_RDONE)
                ecread(unit);
 }
        while (addr->ec_rcr & EC_RDONE)
                ecread(unit);
 }
@@ -450,18 +401,15 @@ ecread(unit)
        struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
        register struct ec_header *ec;
        struct mbuf *m;
        struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr;
        register struct ec_header *ec;
        struct mbuf *m;
-       int len, off, resid;
+       int len, off, resid, ecoff, rbuf;
        register struct ifqueue *inq;
        register struct ifqueue *inq;
-       caddr_t ecbuf;
-       int ecoff;
-       int buf;
-COUNT(ECREAD);
+       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++;
@@ -469,7 +417,6 @@ COUNT(ECREAD);
                if (es->es_if.if_ierrors % 100 == 0)
                        printf("ec%d: += 100 input errors\n", unit);
 #endif
                if (es->es_if.if_ierrors % 100 == 0)
                        printf("ec%d: += 100 input errors\n", unit);
 #endif
-               printf("ec%d: input error (offset=%d)\n", unit, ecoff);
                goto setup;
        }
 
                goto setup;
        }
 
@@ -518,20 +465,6 @@ COUNT(ECREAD);
                schednetisr(NETISR_IP);
                inq = &ipintrq;
                break;
                schednetisr(NETISR_IP);
                inq = &ipintrq;
                break;
-#endif
-#ifdef notdef
-#ifdef PUP
-       case ECPUP_PUPTYPE: {
-               struct pup_header *pup = mtod(m, struct pup_header *);
-
-               pupproto.sp_protocol = pup->pup_type;
-               pupdst.spup_addr = pup->pup_dport;
-               pupsrc.spup_addr = pup->pup_sport;
-               raw_input(m, &pupproto, (struct sockaddr *)&pupsrc,
-                 (struct sockaddr *)&pupdst);
-               goto setup;
-       }
-#endif
 #endif
        default:
                m_freem(m);
 #endif
        default:
                m_freem(m);
@@ -541,14 +474,15 @@ COUNT(ECREAD);
        if (IF_QFULL(inq)) {
                IF_DROP(inq);
                m_freem(m);
        if (IF_QFULL(inq)) {
                IF_DROP(inq);
                m_freem(m);
-       } else
-               IF_ENQUEUE(inq, m);
+               goto setup;
+       }
+       IF_ENQUEUE(inq, m);
 
 setup:
        /*
         * Reset for next packet.
         */
 
 setup:
        /*
         * Reset for next packet.
         */
-       addr->ec_rcr = EC_READ|EC_RCLR|buf;
+       addr->ec_rcr = EC_READ|EC_RCLR|rbuf;
 }
 
 /*
 }
 
 /*
@@ -569,18 +503,16 @@ ecoutput(ifp, m0, dst)
        register struct ec_softc *es = &ec_softc[ifp->if_unit];
        register struct mbuf *m = m0;
        register struct ec_header *ec;
        register struct ec_softc *es = &ec_softc[ifp->if_unit];
        register struct mbuf *m = m0;
        register struct ec_header *ec;
-       register int off;
-       register int i;
+       register int off, i;
        struct mbuf *mcopy = (struct mbuf *) 0;         /* Null */
 
        struct mbuf *mcopy = (struct mbuf *) 0;         /* Null */
 
-COUNT(ECOUTPUT);
        switch (dst->sa_family) {
 
 #ifdef INET
        case AF_INET:
                dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
                if ((dest &~ 0xff) == 0)
        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);
+                       mcopy = m_copy(m, 0, (int)M_COPYALL);
                else if (dest == ((struct sockaddr_in *)&es->es_if.if_addr)->
                    sin_addr.s_addr) {
                        mcopy = m;
                else if (dest == ((struct sockaddr_in *)&es->es_if.if_addr)->
                    sin_addr.s_addr) {
                        mcopy = m;
@@ -599,15 +531,6 @@ COUNT(ECOUTPUT);
                type = ECPUP_IPTYPE;
                off = 0;
                goto gottype;
                type = ECPUP_IPTYPE;
                off = 0;
                goto gottype;
-#endif
-#ifdef notdef
-#ifdef PUP
-       case AF_PUP:
-               dest = ((struct sockaddr_pup *)dst)->spup_addr.pp_host;
-               type = ECPUP_PUPTYPE;
-               off = 0;
-               goto gottype;
-#endif
 #endif
 
        default:
 #endif
 
        default:
@@ -652,13 +575,20 @@ gottype:
        for (i=0; i<6; i++)
                ec->ec_shost[i] = es->es_enaddr[i];
        if ((dest &~ 0xff) == 0)
        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 {
                for (i=0; i<6; i++)
                        ec->ec_dhost[i] = 0xff;
        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) & 0xff;
+               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_dhost[4] = (dest>>16) & 0xff;
                ec->ec_dhost[5] = (dest>>24) & 0xff;
        }
@@ -678,11 +608,10 @@ gottype:
        if (es->es_oactive == 0)
                ecstart(ifp->if_unit);
        splx(s);
        if (es->es_oactive == 0)
                ecstart(ifp->if_unit);
        splx(s);
+
 gotlocal:
 gotlocal:
-       if (mcopy)                              /* Kludge, but it works! */
-               return(looutput(&loif, mcopy, dst));
-       else
-               return (0);
+       return(mcopy ? looutput(&loif, mcopy, dst) : 0);
+
 qfull:
        m0 = m;
        splx(s);
 qfull:
        m0 = m;
        splx(s);
@@ -692,55 +621,80 @@ bad:
 }
 
 /*
 }
 
 /*
- * Routine to copy from mbufs to UNIBUS memory.
- * Similar in spirit to if_wubaput.
+ * Routine to copy from mbuf chain to transmit
+ * 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)
  */
 ecput(ecbuf, m)
-       char *ecbuf;
+       u_char *ecbuf;
        struct mbuf *m;
 {
        struct mbuf *m;
 {
-       register int len;
        register struct mbuf *mp;
        register struct mbuf *mp;
-       register char *bp, *mcp;
-       register int i;
-
-COUNT(ECPUT);
-       len = 0;
-       for (mp=m; mp; mp=mp->m_next)
-               len += mp->m_len;
-       *(u_short *)ecbuf = 2048 - len;
-       bp = ecbuf + 2048 - len;
-       mp = m;
-       while (mp) {
-               mcp = mtod(mp, char *);
-               for (i=0; i<mp->m_len; i++)
+       register int off;
+       u_char *bp;
+
+       for (off = 2048, mp = m; mp; mp = mp->m_next)
+               off -= mp->m_len;
+       if (2048 - off < ECMIN + sizeof (struct ec_header))
+               off = 2048 - ECMIN - sizeof (struct ec_header);
+       *(u_short *)ecbuf = off;
+       bp = (u_char *)(ecbuf + off);
+       for (mp = m; mp; mp = mp->m_next) {
+               register unsigned len = mp->m_len;
+               u_char *mcp;
+
+               if (len == 0)
+                       continue;
+               mcp = mtod(mp, u_char *);
+               if ((unsigned)bp & 01) {
+                       *bp++ = *mcp++;
+                       len--;
+               }
+               if (off = (len >> 1)) {
+                       register u_short *to, *from;
+
+                       to = (u_short *)bp;
+                       from = (u_short *)mcp;
+                       do
+                               *to++ = *from++;
+                       while (--off > 0);
+                       bp = (u_char *)to,
+                       mcp = (u_char *)from;
+               }
+               if (len & 01)
                        *bp++ = *mcp++;
                        *bp++ = *mcp++;
-               mp = m_free(mp);
        }
        }
-       if (bp != ecbuf+2048)
-               printf("ec: bad ecput!\n");
+#ifdef notdef
+       if (bp - ecbuf != 2048)
+               printf("ec: bad ecput, diff=%d\n", bp-ecbuf);
+#endif
+       m_freem(m);
 }
 
 /*
  * Routine to copy from UNIBUS memory into mbufs.
  * Similar in spirit to if_rubaget.
 }
 
 /*
  * Routine to copy from UNIBUS memory into mbufs.
  * Similar in spirit to if_rubaget.
+ *
+ * Warning: This makes the fairly safe assumption that
+ * mbufs have even lengths.
  */
 struct mbuf *
 ecget(ecbuf, totlen, off0)
  */
 struct mbuf *
 ecget(ecbuf, totlen, off0)
-       char *ecbuf;
+       u_char *ecbuf;
        int totlen, off0;
 {
        int totlen, off0;
 {
-       struct mbuf *top, **mp, *m;
-       int off = off0;
-       int len;
-       register char *cp = ecbuf + ECRDOFF + sizeof (struct ec_header);
-       register char *mcp;
-       register int i;
-
-COUNT(ECGET);
-       top = 0;
-       mp = &top;
+       register struct mbuf *m;
+       struct mbuf *top = 0, **mp = &top;
+       register int off = off0, len;
+       u_char *cp;
+
+       cp = ecbuf + ECRDOFF + sizeof (struct ec_header);
        while (totlen > 0) {
        while (totlen > 0) {
+               register int words;
+               u_char *mcp;
+
                MGET(m, 0);
                if (m == 0)
                        goto bad;
                MGET(m, 0);
                if (m == 0)
                        goto bad;
@@ -764,72 +718,35 @@ COUNT(ECGET);
                        m->m_len = len = MIN(MLEN, len);
                        m->m_off = MMINOFF;
                }
                        m->m_len = len = MIN(MLEN, len);
                        m->m_off = MMINOFF;
                }
-               mcp = mtod(m, char *);
-               for (i=0; i<len; i++)
+               mcp = mtod(m, u_char *);
+               if (words = (len >> 1)) {
+                       register u_short *to, *from;
+
+                       to = (u_short *)mcp;
+                       from = (u_short *)cp;
+                       do
+                               *to++ = *from++;
+                       while (--words > 0);
+                       mcp = (u_char *)to;
+                       cp = (u_char *)from;
+               }
+               if (len & 01)
                        *mcp++ = *cp++;
                *mp = m;
                mp = &m->m_next;
                        *mcp++ = *cp++;
                *mp = m;
                mp = &m->m_next;
-               if (off) {
-                       off += len;
-                       if (off == totlen) {
-                               cp = ecbuf + ECRDOFF +
-                                   sizeof (struct ec_header);
-                               off = 0;
-                               totlen = off0;
-                       }
-               } else
+               if (off == 0) {
                        totlen -= len;
                        totlen -= len;
+                       continue;
+               }
+               off += len;
+               if (off == totlen) {
+                       cp = ecbuf + ECRDOFF + sizeof (struct ec_header);
+                       off = 0;
+                       totlen = off0;
+               }
        }
        return (top);
 bad:
        m_freem(top);
        return (0);
 }
        }
        return (top);
 bad:
        m_freem(top);
        return (0);
 }
-
-#if NIMP == 0 && NEC > 0
-/*
- * Logical host interface driver.
- * Allows host to appear as an ARPAnet
- * logical host.  Must also have routing
- * table entry set up to forward packets
- * to appropriate gateway on localnet.
- */
-
-struct ifnet eclhif;
-int    eclhoutput();
-
-/*
- * Called by localnet interface to allow logical
- * host interface to "attach".  Nothing should ever
- * be sent locally to this interface, it's purpose
- * is simply to establish the host's arpanet address.
- */
-eclhinit(addr)
-       int addr;
-{
-       register struct ifnet *ifp = &eclhif;
-       register struct sockaddr_in *sin;
-
-COUNT(ECLHINIT);
-       ifp->if_name = "lh";
-       ifp->if_mtu = ECMTU;
-       sin = (struct sockaddr_in *)&ifp->if_addr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr.s_addr = addr;
-       ifp->if_net = sin->sin_addr.s_net;
-       ifp->if_flags = IFF_UP;
-       ifp->if_output = eclhoutput;    /* should never be used */
-       if_attach(ifp);
-}
-
-eclhoutput(ifp, m0, dst)
-       struct ifnet *ifp;
-       struct mbuf *m0;
-       struct sockaddr *dst;
-{
-COUNT(ECLHOUTPUT);
-       ifp->if_oerrors++;
-       m_freem(m0);
-       return (0);
-}
-#endif