BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / vax / if / if_dp.c
index 143046d..f029aa3 100644 (file)
@@ -2,9 +2,35 @@
  * Copyright (c) 1990 Regents of the University of California.
  * All rights reserved.
  *
  * Copyright (c) 1990 Regents of the University of California.
  * All rights reserved.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)if_dp.c     7.1 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)if_dp.c     7.9 (Berkeley) 6/27/91
  */
 
 #include "dp.h"
  */
 
 #include "dp.h"
 
 /* #define DEBUG       /* for base table dump on fatal error */
 
 
 /* #define DEBUG       /* for base table dump on fatal error */
 
-#include "machine/pte.h"
-
-#include "param.h"
-#include "systm.h"
-#include "mbuf.h"
-#include "buf.h"
-#include "ioctl.h"             /* must precede tty.h */
-#include "protosw.h"
-#include "socket.h"
-#include "syslog.h"
-#include "vmmac.h"
-#include "errno.h"
-#include "time.h"
-#include "kernel.h"
-
-#include "../net/if.h"
-#include "../net/netisr.h"
-#include "../net/route.h"
-
-#include "../vax/cpu.h"
-#include "../vax/mtpr.h"
-#include "../vaxuba/pdma.h"
+#include "../include/pte.h"
+
+#include "sys/param.h"
+#include "sys/systm.h"
+#include "sys/mbuf.h"
+#include "sys/buf.h"
+#include "sys/ioctl.h"         /* must precede tty.h */
+#include "sys/protosw.h"
+#include "sys/socket.h"
+#include "sys/socketvar.h"
+#include "sys/syslog.h"
+#include "sys/vmmac.h"
+#include "sys/errno.h"
+#include "sys/time.h"
+#include "sys/kernel.h"
+
+#include "net/if.h"
+#include "net/if_types.h"
+#include "net/netisr.h"
+#include "net/route.h"
+
+#include "../include/cpu.h"
+#include "../include/mtpr.h"
+
+#define        dzdevice dpdevice
+#include "../uba/pdma.h"
+#include "../uba/ubavar.h"
+
+#include "netccitt/x25.h"
+#include "netccitt/pk.h"
+#include "netccitt/pk_var.h"
 
 #include "if_dpreg.h"
 
 
 #include "if_dpreg.h"
 
@@ -53,7 +88,8 @@
  * Driver information for auto-configuration stuff.
  */
 int    dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint();
  * Driver information for auto-configuration stuff.
  */
 int    dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint();
-int    dpoutput(), dpreset(), dptimeout(), x25_ifoutput();
+int    dpoutput(), dpreset(), dptimeout(), dpstart(), dptestoutput();
+int    x25_ifoutput(), x25_rtrequest();
 
 struct uba_device *dpinfo[NDP];
 
 
 struct uba_device *dpinfo[NDP];
 
@@ -66,13 +102,6 @@ struct      uba_driver dpdriver =
  */
 struct pdma dppdma[2*NDP];
 
  */
 struct pdma dppdma[2*NDP];
 
-/* error reporting intervals */
-#define DPI_RPNBFS     50
-#define DPI_RPDSC      1
-#define DPI_RPTMO      10
-#define DPI_RPDCK      10
-
-
 /*
  * DP software status per interface.
  *
 /*
  * DP software status per interface.
  *
@@ -82,44 +111,81 @@ struct     pdma dppdma[2*NDP];
  */
 struct dp_softc {
        struct  ifnet dp_if;            /* network-visible interface */
  */
 struct dp_softc {
        struct  ifnet dp_if;            /* network-visible interface */
+       int     dp_ipl;
+       struct  dpdevice *dp_addr;      /* dpcsr address */
        short   dp_iused;               /* input buffers given to DP */
        short   dp_flags;               /* flags */
        short   dp_iused;               /* input buffers given to DP */
        short   dp_flags;               /* flags */
+#define DPF_RUNNING    0x01            /* device initialized */
+#define DPF_ONLINE     0x02            /* device running (had a RDYO) */
+#define DPF_RESTART    0x04            /* software restart in progress */
+#define DPF_FLUSH      0x08            /* had a ROVR, flush ipkt when done */
+#define DPF_X25UP      0x10            /* XXX -- someday we'll do PPP also */
        short   dp_ostate;              /* restarting, etc. */
        short   dp_istate;              /* not sure this is necessary */
 #define DPS_IDLE       0
 #define DPS_RESTART    1
 #define DPS_ACTIVE     2
 #define DPS_XEM                3               /* transmitting CRC, etc. */
        short   dp_ostate;              /* restarting, etc. */
        short   dp_istate;              /* not sure this is necessary */
 #define DPS_IDLE       0
 #define DPS_RESTART    1
 #define DPS_ACTIVE     2
 #define DPS_XEM                3               /* transmitting CRC, etc. */
-/* flags */
-#define DPF_RUNNING    0x01            /* device initialized */
-#define DPF_ONLINE     0x02            /* device running (had a RDYO) */
-#define DPF_RESTART    0x04            /* software restart in progress */
-#define DPF_FLUSH      0x08            /* had a ROVR, flush ipkt when done */
-       int     dp_errors[4];           /* non-fatal error counters */
-#define dp_datck dp_errors[0]
-#define dp_timeo dp_errors[1]
-#define dp_nobuf dp_errors[2]
-#define dp_disc  dp_errors[3]
+       short   dp_olen;                /* length of last packet sent */
+       short   dp_ilen;                /* length of last packet recvd */
        char    dp_obuf[DP_MTU+8];
        char    dp_obuf[DP_MTU+8];
-       char    dp_rbuf[DP_MTU+8];
+       char    dp_ibuf[DP_MTU+8];
 } dp_softc[NDP];
 
 } dp_softc[NDP];
 
+/*
+ * Debug info
+ */
+struct dpstat {
+       long    start;
+       long    nohdr;
+       long    init;
+       long    rint;
+       long    xint;
+       long    reset;
+       long    ioctl;
+       long    down;
+       long    mchange;
+       long    timeout;
+       long    rsm;
+       long    rem;
+       long    remchr;
+       long    rga;
+       long    xem;
+       long    rovr;
+} dpstat;
+
+short dp_ilb = 0;
+short dp_log = 0;
+
+#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
+int dp_sizes[] = {
+       sizeof(dp_softc[0]), sizeof(struct ifnet),
+       _offsetof(struct dp_softc, dp_obuf[0]),
+       _offsetof(struct dp_softc, dp_ibuf[0]),
+       };
+
 dpprobe(reg, ui)
        caddr_t reg;
        struct  uba_device *ui;
 {
        register int br, cvec;
        register struct dpdevice *addr = (struct dpdevice *)reg;
 dpprobe(reg, ui)
        caddr_t reg;
        struct  uba_device *ui;
 {
        register int br, cvec;
        register struct dpdevice *addr = (struct dpdevice *)reg;
-       register int i;
+       register int unit = ui->ui_unit;
 
 #ifdef lint
        br = 0; cvec = br; br = cvec;
        dprint(0); dpxint(0);
 #endif
 
 #ifdef lint
        br = 0; cvec = br; br = cvec;
        dprint(0); dpxint(0);
 #endif
+       (void) spl6();
        addr->dpclr = DP_CLR;
        addr->dpclr = DP_XIE|DP_XE;
        DELAY(100000);
        addr->dpclr = DP_CLR;
        addr->dpclr = DP_XIE|DP_XE;
        DELAY(100000);
+       dp_softc[unit].dp_ipl = br = qbgetpri();
+       dp_softc[unit].dp_addr = addr;
        addr->dpclr = 0;
        addr->dpclr = 0;
+       if (cvec && cvec != 0x200){
+               cvec -= 4;
+       }
        return (1);
 }
 
        return (1);
 }
 
@@ -132,30 +198,20 @@ dpattach(ui)
        register struct uba_device *ui;
 {
        register struct dp_softc *dp = &dp_softc[ui->ui_unit];
        register struct uba_device *ui;
 {
        register struct dp_softc *dp = &dp_softc[ui->ui_unit];
-       register struct pdma *pdp = &dppdma[ui->ui_unit*2];
 
        dp->dp_if.if_unit = ui->ui_unit;
        dp->dp_if.if_name = "dp";
        dp->dp_if.if_mtu = DP_MTU;
        dp->dp_if.if_init = dpinit;
        dp->dp_if.if_output = x25_ifoutput;
 
        dp->dp_if.if_unit = ui->ui_unit;
        dp->dp_if.if_name = "dp";
        dp->dp_if.if_mtu = DP_MTU;
        dp->dp_if.if_init = dpinit;
        dp->dp_if.if_output = x25_ifoutput;
+       dp->dp_if.if_type = IFT_X25;
+       dp->dp_if.if_hdrlen = 5;
+       dp->dp_if.if_addrlen = 8;
        dp->dp_if.if_start = dpstart;
        dp->dp_if.if_ioctl = dpioctl;
        dp->dp_if.if_reset = dpreset;
        dp->dp_if.if_watchdog = dptimeout;
        dp->dp_if.if_start = dpstart;
        dp->dp_if.if_ioctl = dpioctl;
        dp->dp_if.if_reset = dpreset;
        dp->dp_if.if_watchdog = dptimeout;
-       dp->dp_if.if_flags = IFF_POINTOPOINT;
-
-
-       pdp->p_addr = (struct dzdevice *)ui->ui_addr;
-       pdp->p_arg = (int)dp;
-       pdp->p_fcn = dpxint;
-       pdp->p_mem = pdp->p_end = dp->dp_obuf;
-       pdp++;
-       pdp->p_addr = (struct dzdevice *)ui->ui_addr;
-       pdp->p_arg = (int)dp;
-       pdp->p_fcn = dprint;
-       pdp->p_mem = pdp->p_end = dp->dp_rbuf;
-
+       dp->dp_if.if_flags = 0;
        if_attach(&dp->dp_if);
 }
 
        if_attach(&dp->dp_if);
 }
 
@@ -170,17 +226,13 @@ dpreset(unit, uban)
        register struct dp_softc *dp = &dp_softc[unit];
        register struct dpdevice *addr;
 
        register struct dp_softc *dp = &dp_softc[unit];
        register struct dpdevice *addr;
 
+       dpstat.reset++;
        if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 ||
            ui->ui_ubanum != uban)
                return;
        if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 ||
            ui->ui_ubanum != uban)
                return;
-       printf(" dp%d", unit);
-       dp->dp_flag = 0;
-       dp->dp_if.if_flags &= ~IFF_RUNNING;
-       addr = ui->ui_addr;
-       addr->dpclr = DP_CLR;
-       addr->dpsar = 0;
-       addr->dprcsr = 0;
+       dpdown(unit);
        dpinit(unit);
        dpinit(unit);
+       printf(" dp%d", unit);
 }
 
 /*
 }
 
 /*
@@ -190,33 +242,47 @@ dpinit(unit)
        int unit;
 {
        register struct dp_softc *dp = &dp_softc[unit];
        int unit;
 {
        register struct dp_softc *dp = &dp_softc[unit];
-       register struct uba_device *ui = dpinfo[unit];
        register struct dpdevice *addr;
        register struct dpdevice *addr;
-       register struct ifnet *ifp = &dp->dp_if;
-       struct ifaddr *ifa;
-       int base;
-       int s;
-
-       addr = (struct dpdevice *)ui->ui_addr;
+       register struct ifaddr *ifa;
+       register struct pdma *pdp = &dppdma[unit*2];
+       int base, s;
 
 
+       dpstat.init++;
        /*
         * Check to see that an address has been set.
         */
        /*
         * Check to see that an address has been set.
         */
-       for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+       for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next)
                if (ifa->ifa_addr->sa_family != AF_LINK)
                        break;
        if (ifa == (struct ifaddr *) 0)
                return;
 
                if (ifa->ifa_addr->sa_family != AF_LINK)
                        break;
        if (ifa == (struct ifaddr *) 0)
                return;
 
-       s = spl5();
+       addr = dp->dp_addr;
+       s = splimp();
        dp->dp_iused = 0;
        dp->dp_istate = dp->dp_ostate = DPS_IDLE;
        dp->dp_iused = 0;
        dp->dp_istate = dp->dp_ostate = DPS_IDLE;
-       dppdma[2*unit+1].p_end = 
-               dppdma[2*unit+1].p_mem = = dp->dp_rbuf;
-       /* enable receive interrupt; CTS comming up will trigger it also */
-       addr->dpsar = DP_CHRM | 0x7E; /* 7E is the flag character */
-       addr->dpclr = 0;
-       addr->dprcsr = DP_RIE | DP_DTR | DP_RE;
+       dp->dp_if.if_flags |= IFF_RUNNING;
+       dp->dp_if.if_flags &= ~IFF_OACTIVE;
+
+       pdp->p_addr = addr;
+       pdp->p_fcn = dpxint;
+       pdp->p_mem = pdp->p_end = dp->dp_obuf;
+       pdp++;
+       pdp->p_addr = addr;
+       pdp->p_fcn = dprint;
+       /* force initial interrupt to come to dprint */
+       pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8;
+
+       addr->dpclr = DP_CLR;
+       DELAY(5000);
+       /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
+                           CRC = CCIIT, initially all ones, 2nd addr = 0 */
+       addr->dpsar = DP_SSLM | DP_IDLE;
+       addr->dpclr = DP_XE | dp_ilb;
+       addr->dptdsr = DP_XSM;
+       /* enable receiver, receive interrupt, DTR, RTS */
+       addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
+       dpstart(&dp->dp_if);
        splx(s);
 }
 
        splx(s);
 }
 
@@ -229,9 +295,9 @@ dpinit(unit)
 dpstart(ifp)
        struct ifnet *ifp;
 {
 dpstart(ifp)
        struct ifnet *ifp;
 {
-       int s, unit = ifp->if_unit;
+       int s, unit = ifp->if_unit, error = 0, len;
        register struct dp_softc *dp = &dp_softc[unit];
        register struct dp_softc *dp = &dp_softc[unit];
-       register struct dpdevice *addr = dpinfo[unit].ui_addr;
+       register struct dpdevice *addr = dp->dp_addr;
        register struct mbuf *m;
        register char *cp;
        char *cplim;
        register struct mbuf *m;
        register char *cp;
        char *cplim;
@@ -240,17 +306,29 @@ dpstart(ifp)
         * If already doing output, go away and depend on transmit
         * complete or error.
         */
         * If already doing output, go away and depend on transmit
         * complete or error.
         */
-       s = splimp();
-       if (dp->dp_if.if_flags & IFF_OACTIVE) {
-               splx(s);
-               return (0);
-       }
+       dpstat.start++;
+       if ((dp->dp_if.if_flags & IFF_OACTIVE) ||
+           (dp->dp_if.if_flags & IFF_RUNNING) == 0)
+               goto out;
        IF_DEQUEUE(&dp->dp_if.if_snd, m);
        if (m == 0)
        IF_DEQUEUE(&dp->dp_if.if_snd, m);
        if (m == 0)
-               return (0);
-       if ((m->m_flags | M_PKTHDR) == 0 || m->m_pkthdr.len > DP_MTU)
-               return (EINVAL);
-       s = spl5();
+               goto out;
+       dp->dp_if.if_collisions++;
+       if (m->m_flags & M_PKTHDR)
+               len = m->m_pkthdr.len;
+       else {
+               struct mbuf *m0 = m;
+               for (len = 0; m; m = m->m_next)
+                       len += m->m_len;
+               m = m0;
+               dpstat.nohdr++;
+       }
+       if (len < 2)
+               goto out;
+       if (len > DP_MTU) {
+               error = EINVAL;
+               goto out;
+       }
        dppdma[2*unit].p_mem = cp = dp->dp_obuf;
        while (m) {
                struct mbuf *n;
        dppdma[2*unit].p_mem = cp = dp->dp_obuf;
        while (m) {
                struct mbuf *n;
@@ -258,15 +336,22 @@ dpstart(ifp)
                cp += m->m_len;
                MFREE(m, n); m = n;
        }
                cp += m->m_len;
                MFREE(m, n); m = n;
        }
-       if (cp == dp->dp_obuf)
-               return (0);
-       dppdma[2*unit].p_end = cp;
-       addr->dpclr = DP_XE | DP_XIE;
-       addr->dptdsr = DP_XSM;
+       dppdma[2*unit].p_end = cp - 1;
        dp->dp_if.if_flags |= IFF_OACTIVE;
        dp->dp_ostate = DPS_ACTIVE;
        dp->dp_if.if_flags |= IFF_OACTIVE;
        dp->dp_ostate = DPS_ACTIVE;
-       splx(s);
-       return (0);
+       dp->dp_if.if_collisions--;
+       dp->dp_olen = len;
+       if (dp_log) {
+               register u_char *p = (u_char *)dp->dp_obuf;
+               log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n",
+                       len, p[0], p[1], p[2], p[3], p[4]);
+       }
+       addr->dpsar = DP_SSLM | DP_IDLE;
+       addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
+       addr->dpclr = DP_XIE | DP_XE | dp_ilb;
+       addr->dptdsr = DP_XSM;
+out:
+       return (error);
 }
 /*
  * Receive done or error interrupt
 }
 /*
  * Receive done or error interrupt
@@ -275,34 +360,61 @@ dprint(unit, pdma, addr)
 register struct pdma *pdma;
 register struct dpdevice *addr;
 {
 register struct pdma *pdma;
 register struct dpdevice *addr;
 {
-       register struct dpsoftc *dp = &dpsoftc[unit];
-       unsigned short dprdsr = addr->dprdsr;
-
-       if (dprdsr & DP_ROVR) {
-               dp->dp_flags |= DPF_FLUSH;
+       register struct dp_softc *dp = &dp_softc[unit];
+       short rdsr = addr->dprdsr, rcsr = pdma->p_arg;
+
+       dpstat.rint++;
+       splx(dp->dp_ipl);
+       if (rdsr & DP_RGA) {
+               /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts),
+                           CRC = CCIIT, initially all ones, 2nd addr = 0 */
+               addr->dpsar = DP_SSLM | DP_IDLE;
+               addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
+               dpstat.rga++;
+               return;
+       }
+       if (rdsr & DP_RSM) { /* Received Start of Message */
+               dpstat.rsm++;
+               pdma->p_mem = dp->dp_ibuf;
+               if (rcsr & DP_RDR) {
+                   dp->dp_ibuf[0] = rdsr & DP_RBUF;
+                   pdma->p_mem++;
+               }
+               dp->dp_flags &= ~DPF_FLUSH;
                return;
        }
                return;
        }
-       if (dprdsr & DP_RSM) { /* Received Start of Message */
-               dp->dp_ibuf[0] = dprdsr & DP_RBUF;
-               pdma->p_mem = dp->dp_ibuf + 1;
-               dpflags &= ~DPF_FLUSH;
+       if (rdsr & DP_REM) { /* Received End of Message */
+               dpstat.rem++;
+               if (rcsr & DP_RDR) {
+                   *(pdma->p_mem++) = rdsr;
+                   dpstat.remchr++;
+               }
+               dp->dp_ilen = pdma->p_mem - dp->dp_ibuf;
+               if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) {
+                       dp->dp_if.if_ierrors++;
+               } else
+                       dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf);
+               pdma->p_mem = pdma->p_end;
+               dp->dp_flags &= ~ DPF_FLUSH;
+               return;
+       }
+       if (rdsr & DP_ROVR) {
+               dpstat.rovr++;
+               dp->dp_flags |= DPF_FLUSH;
                return;
        }
                return;
        }
-       if (dprdsr & DP_REM) { /* Received End of Message */
-               if (dprdsr & DP_REC || dp->dp_flags & DPF_FLUSH) {
-                       dp->dp_if.if_errors++;
-                       pdma->p_mem = dp->dp_ibuf;
-                       dp->dp_flags &= ~ DPF_FLUSH;
-                       return;
+       if (rcsr & DP_MSC) {
+               dpstat.mchange++;
+               if (0 == (rcsr & DP_DSR)) {
+                       log(LOG_DEBUG, "dp%d: lost modem\n", unit);
+                       /*dpdown(unit);*/
                }
                }
-               dpinput(dp, pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf);
                return;
        }
        dp->dp_flags |= DPF_FLUSH;
        if (pdma->p_mem != pdma->p_end)
                return;
        }
        dp->dp_flags |= DPF_FLUSH;
        if (pdma->p_mem != pdma->p_end)
-               log(dp%d: unexplained receiver interrupt\n");
+               log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit);
 }
 }
-
 /*
  * Transmit complete or error interrupt
  */
 /*
  * Transmit complete or error interrupt
  */
@@ -310,38 +422,50 @@ dpxint(unit, pdma, addr)
 register struct pdma *pdma;
 register struct dpdevice *addr;
 {
 register struct pdma *pdma;
 register struct dpdevice *addr;
 {
-       register struct dpsoftc *dp = &dpsoftc[unit];
+       register struct dp_softc *dp = &dp_softc[unit];
+       int s;
 
 
+       splx(dp->dp_ipl);
+       dpstat.xint++;
        if (addr->dptdsr & DP_XERR) {
        if (addr->dptdsr & DP_XERR) {
-               log("if_dp%d: data late\n", unit);
+               log(LOG_DEBUG, "if_dp%d: data late\n", unit);
        restart:
                pdma->p_mem = dp->dp_obuf;
                addr->dptdsr = DP_XSM;
        restart:
                pdma->p_mem = dp->dp_obuf;
                addr->dptdsr = DP_XSM;
+               dp->dp_if.if_oerrors++;
                return;
        }
        switch (dp->dp_ostate) {
 
        case DPS_ACTIVE:
                if (pdma->p_mem != pdma->p_end) {
                return;
        }
        switch (dp->dp_ostate) {
 
        case DPS_ACTIVE:
                if (pdma->p_mem != pdma->p_end) {
-                       log("if_dp%d: misc error in dpxint\n");
+                       log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit);
                        goto restart;
                }
                        goto restart;
                }
-               addr->dptdsr = DP_XEM;
+               addr->dpsar = DP_IDLE|DP_SSLM;
+               addr->dpclr = DP_XE | DP_XIE | dp_ilb;
+               addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]);
+               addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS;
                dp->dp_ostate = DPS_XEM;
                break;
 
        case DPS_XEM:
                dp->dp_ostate = DPS_XEM;
                break;
 
        case DPS_XEM:
+               dpstat.xem++;
+               dp->dp_if.if_opackets++;
+               dp->dp_ostate = DPS_IDLE;
                dp->dp_if.if_flags &= ~IFF_OACTIVE;
                if (dp->dp_if.if_snd.ifq_len)
                        dpstart(&dp->dp_if);
                else {
                dp->dp_if.if_flags &= ~IFF_OACTIVE;
                if (dp->dp_if.if_snd.ifq_len)
                        dpstart(&dp->dp_if);
                else {
-                       addr->dpclr = 0;
-                       dp->dp_ostate = DPS_IDLE;
+                       addr->dpsar = DP_IDLE|DP_SSLM;
+                       addr->dpclr = DP_XE | dp_ilb;
+                       addr->dptdsr = DP_XSM;
+                       addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS;
                }
                break;
 
        default:
                }
                break;
 
        default:
-               log("if_dp%d: impossible state in dpxint\n");
+               log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n");
        }
 }
 /*
        }
 }
 /*
@@ -415,32 +539,54 @@ dpget(rxbuf, totlen, off, ifp)
        return (top);
 }
 
        return (top);
 }
 
-dpinput(dp, len, buffer)
-register struct dpsoftc *dp;
+dpinput(ifp, len, buffer)
+register struct ifnet *ifp;
 caddr_t buffer;
 {
 caddr_t buffer;
 {
-       register struct ifnet *ifp = &dp->dp_if;
        register struct ifqueue *inq;
        register struct mbuf *m;
        register struct ifqueue *inq;
        register struct mbuf *m;
-       extern struct ifqueue hdintrq;
+       extern struct ifqueue hdintrq, ipintrq;
+       int isr;
+
+       ifp->if_ipackets++;
+       if (dp_log) {
+               register u_char *p = (u_char *)buffer;
+               log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n",
+                       len, p[0], p[1], p[2], p[3], p[4]);
+       }
+       
+    {
+       register struct ifaddr *ifa = ifp->if_addrlist;
+       register u_char *cp = (u_char *)buffer;
 
 
-       if(len <= 0 || ifp->if_addrlist == 0)
+       for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+               if (ifa->ifa_addr->sa_family != AF_LINK)
+                       break;
+       if (cp[0] == 0xff && cp[1] == 0x3) {
+               /* This is a UI HDLC Packet, so we'll assume PPP
+                  protocol.  for now, IP only. */
+               buffer += 4;
+               len -= 4;
+               inq = &ipintrq;
+               isr = NETISR_IP;
+       } else {
+               inq = &hdintrq;
+               isr = NETISR_CCITT;
+       }
+    }
+       if (len <= 0)
                return;
 
        m = dpget(buffer, len , 0, ifp);
        if (m == 0)
                return;
                return;
 
        m = dpget(buffer, len , 0, ifp);
        if (m == 0)
                return;
-       ifp->if_ipackets++;
-       
-       /* Only AF_CCITT makes sense at this point */
-       inq = &hdintrq;
 
        if(IF_QFULL(inq)) {
                IF_DROP(inq);
                m_freem(m);
        } else {
                IF_ENQUEUE(inq, m);
 
        if(IF_QFULL(inq)) {
                IF_DROP(inq);
                m_freem(m);
        } else {
                IF_ENQUEUE(inq, m);
-               schednetisr(NETISR_HD);
+               schednetisr(isr);
        }
 }
 
        }
 }
 
@@ -454,35 +600,30 @@ dpioctl(ifp, cmd, data)
 {
        register struct ifaddr *ifa = (struct ifaddr *)data;
        int s = splimp(), error = 0;
 {
        register struct ifaddr *ifa = (struct ifaddr *)data;
        int s = splimp(), error = 0;
+       struct dp_softc *dp = &dp_softc[ifp->if_unit];
 
 
+       dpstat.ioctl++;
        switch (cmd) {
        switch (cmd) {
+       case SIOCSIFCONF_X25:
+               ifp->if_flags |= IFF_UP;
+               error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr);
+               if (error == 0)
+                       dpinit(ifp->if_unit);
+               break;
 
        case SIOCSIFADDR:
 
        case SIOCSIFADDR:
-               ifp->if_flags |= IFF_UP;
-               switch (ifa->ifa_addr->sa_family) {
-#ifdef CCITT
-               case AF_CCITT:
-                       error = hd_ctlinput (PRC_IFUP, (caddr_t)&ifa->ifa_addr);
-                       if (error == 0)
-                               dpinit(ifp->if_unit);
-                       break;
-#endif
-               case SIOCSIFFLAGS:
-                       if ((ifp->if_flags & IFF_UP) == 0 &&
-                           (dp->dp_flags & DPF_RUNNING))
-                               dpdown(ifp->if_unit);
-                       else if (ifp->if_flags & IFF_UP &&
-                           (dp->dp_flags & DPF_RUNNING) == 0)
-                               dpinit(ifp->if_unit);
-                       break;
+               ifa->ifa_rtrequest = x25_rtrequest;
+               break;
 
 
-               default:
+       case SIOCSIFFLAGS:
+               if ((ifp->if_flags & IFF_UP) == 0 &&
+                   (ifp->if_flags & IFF_RUNNING))
+                       dpdown(ifp->if_unit);
+               else if (ifp->if_flags & IFF_UP &&
+                   (ifp->if_flags & IFF_RUNNING) == 0)
                        dpinit(ifp->if_unit);
                        dpinit(ifp->if_unit);
-                       break;
-               }
                break;
 
                break;
 
-       /* case SIOCSIFFLAGS: ... */
 
        default:
                error = EINVAL;
 
        default:
                error = EINVAL;
@@ -495,16 +636,21 @@ dpioctl(ifp, cmd, data)
  * Flush output queue and drop queue limit.
  */
 dpdown(unit)
  * Flush output queue and drop queue limit.
  */
 dpdown(unit)
-       int unit;
+int unit;
 {
 {
-       register struct dp_softc *dp = &dp_softc[unit];
-       register struct ifxmt *ifxp;
 
 
-       dp->dp_flags &= ~(DP_RUNNING | DP_ONLINE);
-       addr->dpclr = DP_CLR;
-       addr->dpclr = 0;
+       register struct dp_softc *dp = &dp_softc[unit];
+       register struct dpdevice *addr = dp->dp_addr;
 
 
+       dpstat.down++;
        if_qflush(&dp->dp_if.if_snd);
        if_qflush(&dp->dp_if.if_snd);
+       dp->dp_flags = 0;
+       dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+
+       addr->dpclr = DP_CLR;
+       DELAY(1000);
+       addr->dpsar = 0;
+       addr->dprcsr = 0;
 }
 
 /*
 }
 
 /*
@@ -516,12 +662,51 @@ dptimeout(unit)
        int unit;
 {
        register struct dp_softc *dp;
        int unit;
 {
        register struct dp_softc *dp;
-       struct dpdevice *addr;
 
 
+       /* currently not armed */
+       dpstat.timeout++;
        dp = &dp_softc[unit];
        dp = &dp_softc[unit];
-       if (dp->dp_flags & DP_ONLINE) {
-               addr = (struct dpdevice *)(dpinfo[unit]->ui_addr);
-               dpstart(unit);
+       if (dp->dp_if.if_flags & IFF_OACTIVE) {
+               dpstart(&dp->dp_if);
+       }
+}
+/*
+ * For debugging loopback activity.
+ */
+static char pppheader[4] = { -1, 3, 0, 0x21 };
+int dp_louts;
+
+dptestoutput(ifp, m, dst, rt)
+register struct ifnet *ifp;
+register struct mbuf *m;
+struct sockaddr *dst;
+struct rtentry *rt;
+{
+       /*
+        * Queue message on interface, and start output if interface
+        * not yet active.
+        */
+       int s = splimp(), error = 0;
+       dp_louts++;
+       M_PREPEND(m, sizeof pppheader, M_DONTWAIT);
+       if (m == 0) {
+               splx(s);
+               return ENOBUFS;
+       }
+       bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader);
+       if (IF_QFULL(&ifp->if_snd)) {
+               IF_DROP(&ifp->if_snd);
+           /* printf("%s%d: HDLC says OK to send but queue full, may hang\n",
+                       ifp->if_name, ifp->if_unit);*/
+               m_freem(m);
+               error = ENOBUFS;
+       } else {
+               IF_ENQUEUE(&ifp->if_snd, m);
+               if ((ifp->if_flags & IFF_OACTIVE) == 0)
+                       (*ifp->if_start)(ifp);
        }
        }
+       splx(s);
+       return (error);
 }
 }
+
 #endif
 #endif