conditional kludge for byte swapping -- quiet cmu-stanford mafia
[unix-history] / usr / src / sys / vax / if / if_en.c
index b3b1e9e..f439693 100644 (file)
@@ -1,4 +1,4 @@
-/*     if_en.c 4.78    83/05/30        */
+/*     if_en.c 4.81    83/06/26        */
 
 #include "en.h"
 
 
 #include "en.h"
 
@@ -14,7 +14,8 @@
 #include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/vmmac.h"
 #include "../h/protosw.h"
 #include "../h/socket.h"
 #include "../h/vmmac.h"
-#include <errno.h>
+#include "../h/errno.h"
+#include "../h/ioctl.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
 
 #include "../net/if.h"
 #include "../net/netisr.h"
@@ -43,7 +44,15 @@ struct       uba_driver endriver =
        { enprobe, 0, enattach, 0, enstd, "en", eninfo };
 #define        ENUNIT(x)       minor(x)
 
        { enprobe, 0, enattach, 0, enstd, "en", eninfo };
 #define        ENUNIT(x)       minor(x)
 
-int    eninit(),enoutput(),enreset();
+int    eninit(),enoutput(),enreset(),enioctl();
+
+#ifdef notdef
+/*
+ * If you need to byte swap IP's in the system, define
+ * this and do a SIOCSIFFLAGS at boot time.
+ */
+#define        ENF_SWABIPS     0x100
+#endif
 
 /*
  * Ethernet software status per interface.
 
 /*
  * Ethernet software status per interface.
@@ -87,9 +96,6 @@ enprobe(reg)
        addr->en_ostat = EN_IEN|EN_GO;
        DELAY(100000);
        addr->en_ostat = 0;
        addr->en_ostat = EN_IEN|EN_GO;
        DELAY(100000);
        addr->en_ostat = 0;
-#ifdef ECHACK
-       br = 0x16;
-#endif
        return (1);
 }
 
        return (1);
 }
 
@@ -106,10 +112,9 @@ enattach(ui)
        es->es_if.if_unit = ui->ui_unit;
        es->es_if.if_name = "en";
        es->es_if.if_mtu = ENMTU;
        es->es_if.if_unit = ui->ui_unit;
        es->es_if.if_name = "en";
        es->es_if.if_mtu = ENMTU;
-       if (ui->ui_flags)
-               ensetaddr(es, ui->ui_flags);
        es->es_if.if_init = eninit;
        es->es_if.if_output = enoutput;
        es->es_if.if_init = eninit;
        es->es_if.if_output = enoutput;
+       es->es_if.if_ioctl = enioctl;
        es->es_if.if_reset = enreset;
        es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
 #if defined(VAX750)
        es->es_if.if_reset = enreset;
        es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;
 #if defined(VAX750)
@@ -120,31 +125,6 @@ enattach(ui)
        if_attach(&es->es_if);
 }
 
        if_attach(&es->es_if);
 }
 
-/*
- * Set interface's Internet address
- * given the network number.  The station
- * number, taken from the on-board register,
- * is used as the local part.
- */
-ensetaddr(es, net)
-       register struct en_softc *es;
-       int net;
-{
-       struct endevice *enaddr;
-       register struct sockaddr_in *sin;
-
-       es->es_if.if_net = net;
-       enaddr = (struct endevice *)eninfo[es->es_if.if_unit]->ui_addr;
-       es->es_if.if_host[0] = (~enaddr->en_addr) & 0xff;
-       sin = (struct sockaddr_in *)&es->es_if.if_addr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr = if_makeaddr(net, es->es_if.if_host[0]);
-       sin = (struct sockaddr_in *)&es->es_if.if_broadaddr;
-       sin->sin_family = AF_INET;
-       sin->sin_addr = if_makeaddr(net, INADDR_ANY);
-       es->es_if.if_flags |= IFF_BROADCAST;
-}
-
 /*
  * Reset of interface after UNIBUS reset.
  * If interface is on specified uba, reset its state.
 /*
  * Reset of interface after UNIBUS reset.
  * If interface is on specified uba, reset its state.
@@ -172,16 +152,10 @@ eninit(unit)
        register struct uba_device *ui = eninfo[unit];
        register struct endevice *addr;
        struct sockaddr_in *sin = (struct sockaddr_in *)&es->es_if.if_addr;
        register struct uba_device *ui = eninfo[unit];
        register struct endevice *addr;
        struct sockaddr_in *sin = (struct sockaddr_in *)&es->es_if.if_addr;
-       int net, s;
+       int s;
 
 
-       net = in_netof(sin->sin_addr);
-       if (net == 0)
+       if (in_netof(sin->sin_addr) == 0)
                return;
                return;
-       ensetaddr(es, net);
-#ifdef notdef
-       if (es->es_if.if_flags & IFF_UP)
-               return;
-#endif
        if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
            sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 
                printf("en%d: can't initialize\n", unit);
        if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,
            sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 
                printf("en%d: can't initialize\n", unit);
@@ -200,7 +174,7 @@ eninit(unit)
        addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
        addr->en_istat = EN_IEN|EN_GO;
        es->es_oactive = 1;
        addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;
        addr->en_istat = EN_IEN|EN_GO;
        es->es_oactive = 1;
-       es->es_if.if_flags |= IFF_UP;
+       es->es_if.if_flags |= IFF_UP|IFF_RUNNING;
        enxint(unit);
        splx(s);
        if_rtinit(&es->es_if, RTF_UP);
        enxint(unit);
        splx(s);
        if_rtinit(&es->es_if, RTF_UP);
@@ -243,6 +217,24 @@ enstart(dev)
        }
        dest = mtod(m, struct en_header *)->en_dhost;
        es->es_olen = if_wubaput(&es->es_ifuba, m);
        }
        dest = mtod(m, struct en_header *)->en_dhost;
        es->es_olen = if_wubaput(&es->es_ifuba, m);
+#ifdef ENF_SWABIPS
+       /*
+        * The Xerox interface does word at a time DMA, so
+        * someone must do byte swapping of user data if high
+        * and low ender machines are to communicate.  It doesn't
+        * belong here, but certain people depend on it, so...
+        *
+        * Should swab everybody, but this is a kludge anyway.
+        */
+       if (es->es_if.if_flags & ENF_SWABIPS) {
+               register struct en_header *en;
+
+               en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;
+               if (en->en_type == ENTYPE_IP)
+                       enswab((caddr_t)(en + 1), (caddr_t)(en + 1),
+                           es->es_olen - sizeof (struct en_header) + 1);
+       }
+#endif
 
        /*
         * Ethernet cannot take back-to-back packets (no
 
        /*
         * Ethernet cannot take back-to-back packets (no
@@ -412,6 +404,10 @@ enrint(unit)
                off = 0;
        if (len == 0)
                goto setup;
                off = 0;
        if (len == 0)
                goto setup;
+#ifdef ENF_SWABIPS
+       if (es->es_if.if_flags & ENF_SWABIPS && en->en_type == ENTYPE_IP)
+               enswab((caddr_t)(en + 1), (caddr_t)(en + 1), len);
+#endif
        /*
         * Pull packet off interface.  Off is nonzero if packet
         * has trailing header; if_rubaget will then force this header
        /*
         * Pull packet off interface.  Off is nonzero if packet
         * has trailing header; if_rubaget will then force this header
@@ -494,6 +490,8 @@ enoutput(ifp, m0, dst)
                }
                dest = (dest >> 24) & 0xff;
                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                }
                dest = (dest >> 24) & 0xff;
                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 = ENTYPE_TRAIL + (off>>9);
                if (off > 0 && (off & 0x1ff) == 0 &&
                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
                        type = ENTYPE_TRAIL + (off>>9);
@@ -580,3 +578,75 @@ bad:
        m_freem(m0);
        return (error);
 }
        m_freem(m0);
        return (error);
 }
+
+/*
+ * Process an ioctl request.
+ */
+enioctl(ifp, cmd, data)
+       register struct ifnet *ifp;
+       int cmd;
+       caddr_t data;
+{
+       struct ifreq *ifr = (struct ifreq *)data;
+       int s = splimp(), error = 0;
+
+       switch (cmd) {
+
+       case SIOCSIFADDR:
+               if (ifp->if_flags & IFF_RUNNING)
+                       if_rtinit(ifp, -1);     /* delete previous route */
+               ensetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr);
+               if (ifp->if_flags & IFF_RUNNING)
+                       if_rtinit(ifp, RTF_UP);
+               else
+                       eninit(ifp->if_unit);
+               break;
+
+       default:
+               error = EINVAL;
+       }
+       splx(s);
+       return (error);
+}
+
+ensetaddr(ifp, sin)
+       register struct ifnet *ifp;
+       register struct sockaddr_in *sin;
+{
+       struct endevice *enaddr;
+
+       ifp->if_net = in_netof(sin->sin_addr);
+       enaddr = (struct endevice *)eninfo[ifp->if_unit]->ui_addr;
+       ifp->if_host[0] = (~enaddr->en_addr) & 0xff;
+       sin = (struct sockaddr_in *)&ifp->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;
+}
+
+#ifdef ENF_SWABIPS
+/*
+ * Swab bytes
+ * Jeffrey Mogul, Stanford
+ */
+enswab(from, to, n)
+       register caddr_t *from, *to;
+       register int n;
+{
+       register unsigned long temp;
+       
+       n >>= 1; n++;
+#define        STEP    temp = *from++,*to++ = *from++,*to++ = temp
+       /* round to multiple of 8 */
+       while ((--n) & 07)
+               STEP;
+       n >>= 3;
+       while (--n >= 0) {
+               STEP; STEP; STEP; STEP;
+               STEP; STEP; STEP; STEP;
+       }
+}
+#endif