Latest fixes from Nesheim@cornell
[unix-history] / usr / src / sys / vax / if / if_de.c
index cbe328b..28e6ced 100644 (file)
@@ -1,4 +1,10 @@
-/*     if_de.c 6.6     84/07/16        */
+/*
+ * 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,7 +69,6 @@ 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();
 
@@ -152,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
@@ -198,10 +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;
        ifp->if_init = deinit;
        ifp->if_output = deoutput;
        ifp->if_ioctl = deioctl;
        ifp->if_init = deinit;
        ifp->if_output = deoutput;
        ifp->if_ioctl = deioctl;
@@ -227,6 +242,7 @@ dereset(unit, uban)
            ui->ui_ubanum != uban)
                return;
        printf(" de%d", unit);
            ui->ui_ubanum != uban)
                return;
        printf(" de%d", unit);
+       de_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
        deinit(unit);
 }
 
        deinit(unit);
 }
 
@@ -243,18 +259,17 @@ deinit(unit)
        register struct ifrw *ifrw;
        register struct ifxmt *ifxp;
        struct ifnet *ifp = &ds->ds_if;
        register struct ifrw *ifrw;
        register struct ifxmt *ifxp;
        struct ifnet *ifp = &ds->ds_if;
-       struct sockaddr_in *sin;
        int s;
        struct de_ring *rp;
        int incaddr;
        int csr0;
 
        int s;
        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);
@@ -336,15 +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);
-       arpwhohas(&ds->ds_ac, &sin->sin_addr);
 }
 
 /*
 }
 
 /*
@@ -538,16 +550,16 @@ deread(ds, ifrw, len)
        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 *));
@@ -576,14 +588,21 @@ 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);
 #endif
        default:
                m_freem(m);
@@ -613,7 +632,7 @@ deoutput(ifp, m0, dst)
        struct sockaddr *dst;
 {
        int type, s, error;
        struct sockaddr *dst;
 {
        int type, s, error;
-       struct ether_addr edst;
+       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;
@@ -625,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;
-               edst = eh->ether_dhost;
+               bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
                type = eh->ether_type;
                goto gottype;
 
                type = eh->ether_type;
                goto gottype;
 
@@ -690,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);
-       eh->ether_dhost = edst;
+       bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
        /* DEUNA fills in source address */
 
        /*
        /* DEUNA fills in source address */
 
        /*
@@ -986,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:
@@ -1005,17 +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
 #endif
+