145163Ssklower /* 245163Ssklower * Copyright (c) 1990 Regents of the University of California. 345163Ssklower * All rights reserved. 445163Ssklower * 545163Ssklower * %sccs.include.redist.c% 645163Ssklower * 7*45228Ssklower * @(#)if_dp.c 7.3 (Berkeley) 09/12/90 845163Ssklower */ 945163Ssklower 1045163Ssklower #include "dp.h" 1145163Ssklower #if NDP > 0 1245163Ssklower 1345163Ssklower /* 1445163Ssklower * DPV-11 device driver, X.25 version 1545163Ssklower * 1645163Ssklower * Derived from dmc-11 driver: 1745163Ssklower * 1845163Ssklower * Bill Nesheim 1945163Ssklower * Cornell University 2045163Ssklower * 2145163Ssklower * Lou Salkind 2245163Ssklower * New York University 2345163Ssklower */ 2445163Ssklower 2545163Ssklower /* #define DEBUG /* for base table dump on fatal error */ 2645163Ssklower 2745163Ssklower #include "machine/pte.h" 2845163Ssklower 2945163Ssklower #include "param.h" 3045163Ssklower #include "systm.h" 3145163Ssklower #include "mbuf.h" 3245163Ssklower #include "buf.h" 3345163Ssklower #include "ioctl.h" /* must precede tty.h */ 3445163Ssklower #include "protosw.h" 3545163Ssklower #include "socket.h" 36*45228Ssklower #include "socketvar.h" 3745163Ssklower #include "syslog.h" 3845163Ssklower #include "vmmac.h" 3945163Ssklower #include "errno.h" 4045163Ssklower #include "time.h" 4145163Ssklower #include "kernel.h" 4245163Ssklower 4345163Ssklower #include "../net/if.h" 4445163Ssklower #include "../net/netisr.h" 4545163Ssklower #include "../net/route.h" 4645163Ssklower 4745163Ssklower #include "../vax/cpu.h" 4845163Ssklower #include "../vax/mtpr.h" 4945166Ssklower 50*45228Ssklower #define dzdevice dpdevice 5145163Ssklower #include "../vaxuba/pdma.h" 5245166Ssklower #include "../vaxuba/ubavar.h" 5345163Ssklower 54*45228Ssklower #include "../netccitt/x25.h" 55*45228Ssklower #include "../netccitt/pk.h" 56*45228Ssklower #include "../netccitt/pk_var.h" 5745166Ssklower 5845163Ssklower #include "if_dpreg.h" 5945163Ssklower 6045163Ssklower /* 6145163Ssklower * Driver information for auto-configuration stuff. 6245163Ssklower */ 6345163Ssklower int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint(); 64*45228Ssklower int dpoutput(), dpreset(), dptimeout(), dpstart(), x25_ifoutput(), dptestoutput(); 6545163Ssklower 6645163Ssklower struct uba_device *dpinfo[NDP]; 6745163Ssklower 6845163Ssklower u_short dpstd[] = { 0 }; 6945163Ssklower struct uba_driver dpdriver = 7045163Ssklower { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo }; 7145163Ssklower 7245163Ssklower /* 73*45228Ssklower * debug info 74*45228Ssklower */ 75*45228Ssklower struct dpstat { 76*45228Ssklower long start; 77*45228Ssklower long nohdr; 78*45228Ssklower long init; 79*45228Ssklower long rint; 80*45228Ssklower long xint; 81*45228Ssklower long reset; 82*45228Ssklower long ioctl; 83*45228Ssklower long down; 84*45228Ssklower long mchange; 85*45228Ssklower long timeout; 86*45228Ssklower } dpstat; 87*45228Ssklower /* 8845163Ssklower * Pdma structures for fast interrupts. 8945163Ssklower */ 9045163Ssklower struct pdma dppdma[2*NDP]; 9145163Ssklower 9245163Ssklower /* error reporting intervals */ 9345163Ssklower #define DPI_RPNBFS 50 9445163Ssklower #define DPI_RPDSC 1 9545163Ssklower #define DPI_RPTMO 10 9645163Ssklower #define DPI_RPDCK 10 9745163Ssklower 9845163Ssklower 9945163Ssklower /* 10045163Ssklower * DP software status per interface. 10145163Ssklower * 10245163Ssklower * Each interface is referenced by a network interface structure, 10345163Ssklower * dp_if, which the routing code uses to locate the interface. 10445163Ssklower * This structure contains the output queue for the interface, its address, ... 10545163Ssklower */ 10645163Ssklower struct dp_softc { 10745163Ssklower struct ifnet dp_if; /* network-visible interface */ 108*45228Ssklower int dp_ipl; 10945163Ssklower short dp_iused; /* input buffers given to DP */ 11045163Ssklower short dp_flags; /* flags */ 111*45228Ssklower #define DPF_RUNNING 0x01 /* device initialized */ 112*45228Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 113*45228Ssklower #define DPF_RESTART 0x04 /* software restart in progress */ 114*45228Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 11545163Ssklower short dp_ostate; /* restarting, etc. */ 11645163Ssklower short dp_istate; /* not sure this is necessary */ 11745163Ssklower #define DPS_IDLE 0 11845163Ssklower #define DPS_RESTART 1 11945163Ssklower #define DPS_ACTIVE 2 12045163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */ 12145163Ssklower int dp_errors[4]; /* non-fatal error counters */ 12245163Ssklower #define dp_datck dp_errors[0] 12345163Ssklower #define dp_timeo dp_errors[1] 12445163Ssklower #define dp_nobuf dp_errors[2] 12545163Ssklower #define dp_disc dp_errors[3] 126*45228Ssklower struct timeval dp_xt; /* start of last transmission */ 12745163Ssklower char dp_obuf[DP_MTU+8]; 12845166Ssklower char dp_ibuf[DP_MTU+8]; 12945163Ssklower } dp_softc[NDP]; 13045163Ssklower 13145163Ssklower dpprobe(reg, ui) 13245163Ssklower caddr_t reg; 13345163Ssklower struct uba_device *ui; 13445163Ssklower { 13545163Ssklower register int br, cvec; 13645163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg; 13745163Ssklower register int i; 13845163Ssklower 13945163Ssklower #ifdef lint 14045163Ssklower br = 0; cvec = br; br = cvec; 14145163Ssklower dprint(0); dpxint(0); 14245163Ssklower #endif 143*45228Ssklower (void) spl6(); 14445163Ssklower addr->dpclr = DP_CLR; 14545163Ssklower addr->dpclr = DP_XIE|DP_XE; 14645163Ssklower DELAY(100000); 147*45228Ssklower dp_softc[ui->ui_unit].dp_ipl = br = qbgetpri(); 14845163Ssklower addr->dpclr = 0; 149*45228Ssklower if (cvec && cvec != 0x200){ 150*45228Ssklower cvec -= 4; 151*45228Ssklower } 15245163Ssklower return (1); 15345163Ssklower } 15445163Ssklower 15545163Ssklower /* 15645163Ssklower * Interface exists: make available by filling in network interface 15745163Ssklower * record. System will initialize the interface when it is ready 15845163Ssklower * to accept packets. 15945163Ssklower */ 16045163Ssklower dpattach(ui) 16145163Ssklower register struct uba_device *ui; 16245163Ssklower { 16345163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 16445163Ssklower 16545163Ssklower dp->dp_if.if_unit = ui->ui_unit; 16645163Ssklower dp->dp_if.if_name = "dp"; 16745163Ssklower dp->dp_if.if_mtu = DP_MTU; 16845163Ssklower dp->dp_if.if_init = dpinit; 16945163Ssklower dp->dp_if.if_output = x25_ifoutput; 17045163Ssklower dp->dp_if.if_start = dpstart; 17145163Ssklower dp->dp_if.if_ioctl = dpioctl; 17245163Ssklower dp->dp_if.if_reset = dpreset; 17345163Ssklower dp->dp_if.if_watchdog = dptimeout; 174*45228Ssklower dp->dp_if.if_flags = 0; 17545163Ssklower if_attach(&dp->dp_if); 17645163Ssklower } 17745163Ssklower 17845163Ssklower /* 17945163Ssklower * Reset of interface after UNIBUS reset. 18045163Ssklower * If interface is on specified UBA, reset its state. 18145163Ssklower */ 18245163Ssklower dpreset(unit, uban) 18345163Ssklower int unit, uban; 18445163Ssklower { 18545163Ssklower register struct uba_device *ui; 18645163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 18745163Ssklower register struct dpdevice *addr; 18845163Ssklower 189*45228Ssklower dpstat.reset++; 19045163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 19145163Ssklower ui->ui_ubanum != uban) 19245163Ssklower return; 19345163Ssklower printf(" dp%d", unit); 19445166Ssklower dp->dp_flags = 0; 19545163Ssklower dp->dp_if.if_flags &= ~IFF_RUNNING; 19645166Ssklower addr = (struct dpdevice *)ui->ui_addr; 19745163Ssklower addr->dpclr = DP_CLR; 198*45228Ssklower DELAY(1000); 19945163Ssklower addr->dpsar = 0; 20045163Ssklower addr->dprcsr = 0; 20145163Ssklower dpinit(unit); 20245163Ssklower } 20345163Ssklower 20445163Ssklower /* 20545163Ssklower * Initialization of interface. 20645163Ssklower */ 20745163Ssklower dpinit(unit) 20845163Ssklower int unit; 20945163Ssklower { 21045163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 21145163Ssklower register struct uba_device *ui = dpinfo[unit]; 21245163Ssklower register struct dpdevice *addr; 213*45228Ssklower register struct ifaddr *ifa; 214*45228Ssklower register struct pdma *pdp = &dppdma[unit*2]; 215*45228Ssklower int base, s; 21645163Ssklower 217*45228Ssklower dpstat.init++; 21845163Ssklower /* 21945163Ssklower * Check to see that an address has been set. 22045163Ssklower */ 221*45228Ssklower for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) 22245163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 22345163Ssklower break; 22445163Ssklower if (ifa == (struct ifaddr *) 0) 22545163Ssklower return; 22645163Ssklower 227*45228Ssklower addr = (struct dpdevice *)ui->ui_addr; 228*45228Ssklower s = splimp(); 22945163Ssklower dp->dp_iused = 0; 23045163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE; 231*45228Ssklower dp->dp_if.if_flags |= IFF_RUNNING; 232*45228Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 233*45228Ssklower 234*45228Ssklower pdp->p_addr = addr; 235*45228Ssklower pdp->p_fcn = dpxint; 236*45228Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf; 237*45228Ssklower pdp++; 238*45228Ssklower pdp->p_addr = addr; 239*45228Ssklower pdp->p_fcn = dprint; 240*45228Ssklower /* force initial interrupt to come to dprint */ 241*45228Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; 242*45228Ssklower 243*45228Ssklower addr->dpclr = DP_CLR; 244*45228Ssklower DELAY(1000); 24545163Ssklower addr->dpclr = 0; 246*45228Ssklower DELAY(1000); 247*45228Ssklower /* DP_ATA = 0, DP_CHRM = 0, 248*45228Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 249*45228Ssklower addr->dpsar = 0; 250*45228Ssklower /* enable receive interrupt */ 251*45228Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 252*45228Ssklower dpstart(&dp->dp_if); 25345163Ssklower splx(s); 25445163Ssklower } 25545163Ssklower 256*45228Ssklower int dpMessy = 0; 25745163Ssklower /* 25845163Ssklower * Start output on interface. Get another datagram 25945163Ssklower * to send from the interface queue and map it to 26045163Ssklower * the interface before starting output. 26145163Ssklower * 26245163Ssklower */ 26345163Ssklower dpstart(ifp) 26445163Ssklower struct ifnet *ifp; 26545163Ssklower { 266*45228Ssklower int s, unit = ifp->if_unit, error = 0, len; 26745163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 26845166Ssklower register struct dpdevice *addr = 26945166Ssklower (struct dpdevice *)(dpinfo[unit]->ui_addr); 27045163Ssklower register struct mbuf *m; 27145163Ssklower register char *cp; 27245163Ssklower char *cplim; 27345163Ssklower 27445163Ssklower /* 27545163Ssklower * If already doing output, go away and depend on transmit 27645163Ssklower * complete or error. 27745163Ssklower */ 278*45228Ssklower dpstat.start++; 279*45228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) 280*45228Ssklower goto out; 28145163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m); 28245163Ssklower if (m == 0) 283*45228Ssklower goto out; 284*45228Ssklower dp->dp_if.if_collisions++; 285*45228Ssklower if (m->m_flags & M_PKTHDR) 286*45228Ssklower len = m->m_pkthdr.len; 287*45228Ssklower else { 288*45228Ssklower struct mbuf *m0 = m; 289*45228Ssklower for (len = 0; m; m = m->m_next) 290*45228Ssklower len += m->m_len; 291*45228Ssklower m = m0; 292*45228Ssklower dpstat.nohdr++; 293*45228Ssklower } 294*45228Ssklower if (len == 0) 295*45228Ssklower goto out; 296*45228Ssklower if (len > DP_MTU) { 297*45228Ssklower error = EINVAL; 298*45228Ssklower goto out; 299*45228Ssklower } 300*45228Ssklower cp = dp->dp_obuf; 301*45228Ssklower dppdma[2*unit].p_mem = cp + 1; 30245163Ssklower while (m) { 30345163Ssklower struct mbuf *n; 30445163Ssklower bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 30545163Ssklower cp += m->m_len; 30645163Ssklower MFREE(m, n); m = n; 30745163Ssklower } 30845163Ssklower dppdma[2*unit].p_end = cp; 309*45228Ssklower if (dpMessy) 310*45228Ssklower printf("dp: len %d, start %x, end %x, first %x, next %x", 311*45228Ssklower len, dp->dp_obuf, cp, *(int *)dp->dp_obuf, 312*45228Ssklower 1[(int *)dp->dp_obuf]); 31345163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE; 31445163Ssklower dp->dp_ostate = DPS_ACTIVE; 315*45228Ssklower dp->dp_if.if_collisions--; 316*45228Ssklower dp->dp_xt = time; 317*45228Ssklower addr->dpclr = DP_XE | DP_XIE; 318*45228Ssklower addr->dptdsr = DP_XSM | (0xff & dp->dp_obuf[0]); 319*45228Ssklower out: 320*45228Ssklower return (error); 32145163Ssklower } 32245163Ssklower /* 32345163Ssklower * Receive done or error interrupt 32445163Ssklower */ 32545163Ssklower dprint(unit, pdma, addr) 32645163Ssklower register struct pdma *pdma; 32745163Ssklower register struct dpdevice *addr; 32845163Ssklower { 32945166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 330*45228Ssklower short rdsr = addr->dprdsr, rcsr; 33145163Ssklower 332*45228Ssklower dpstat.rint++; 333*45228Ssklower splx(dp->dp_ipl); 33445166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */ 33545166Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF; 33645163Ssklower pdma->p_mem = dp->dp_ibuf + 1; 33745166Ssklower dp->dp_flags &= ~DPF_FLUSH; 33845163Ssklower return; 33945163Ssklower } 34045166Ssklower if (rdsr & DP_REM) { /* Received End of Message */ 34145166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 34245166Ssklower dp->dp_if.if_ierrors++; 343*45228Ssklower } else 344*45228Ssklower dpinput(&dp->dp_if, 345*45228Ssklower pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf); 346*45228Ssklower pdma->p_mem = pdma->p_end; 347*45228Ssklower dp->dp_flags &= ~ DPF_FLUSH; 348*45228Ssklower return; 349*45228Ssklower } 350*45228Ssklower if (rdsr & DP_ROVR) { 351*45228Ssklower dp->dp_flags |= DPF_FLUSH; 352*45228Ssklower return; 353*45228Ssklower } 354*45228Ssklower rcsr = pdma->p_arg; 355*45228Ssklower if (rcsr & DP_MSC) { 356*45228Ssklower dpstat.mchange++; 357*45228Ssklower if (0 == (rcsr & DP_DSR)) { 358*45228Ssklower log(LOG_DEBUG, "dp%d: lost modem\n", unit); 359*45228Ssklower dpdown(unit); 36045163Ssklower } 36145163Ssklower return; 36245163Ssklower } 36345163Ssklower dp->dp_flags |= DPF_FLUSH; 36445163Ssklower if (pdma->p_mem != pdma->p_end) 36545166Ssklower log("dp%d: unexplained receiver interrupt\n", unit); 36645163Ssklower } 367*45228Ssklower struct timeval dp_xt; 36845163Ssklower 36945163Ssklower /* 37045163Ssklower * Transmit complete or error interrupt 37145163Ssklower */ 37245163Ssklower dpxint(unit, pdma, addr) 37345163Ssklower register struct pdma *pdma; 37445163Ssklower register struct dpdevice *addr; 37545163Ssklower { 37645166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 377*45228Ssklower int s; 37845163Ssklower 379*45228Ssklower splx(dp->dp_ipl); 380*45228Ssklower dpstat.xint++; 38145163Ssklower if (addr->dptdsr & DP_XERR) { 38245163Ssklower log("if_dp%d: data late\n", unit); 38345163Ssklower restart: 38445163Ssklower pdma->p_mem = dp->dp_obuf; 38545163Ssklower addr->dptdsr = DP_XSM; 386*45228Ssklower dp->dp_if.if_oerrors++; 38745163Ssklower return; 38845163Ssklower } 38945163Ssklower switch (dp->dp_ostate) { 39045163Ssklower 39145163Ssklower case DPS_ACTIVE: 39245163Ssklower if (pdma->p_mem != pdma->p_end) { 393*45228Ssklower log("if_dp%d: misc error in dpxint\n", unit); 39445163Ssklower goto restart; 39545163Ssklower } 39645163Ssklower addr->dptdsr = DP_XEM; 39745163Ssklower dp->dp_ostate = DPS_XEM; 39845163Ssklower break; 39945163Ssklower 40045163Ssklower case DPS_XEM: 401*45228Ssklower dp->dp_if.if_opackets++; 40245163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 403*45228Ssklower s = splclock(); 404*45228Ssklower dp_xt = time; 405*45228Ssklower timevalsub(&dp_xt, &dp->dp_xt); 406*45228Ssklower splx(s); 40745163Ssklower if (dp->dp_if.if_snd.ifq_len) 40845163Ssklower dpstart(&dp->dp_if); 40945163Ssklower else { 41045163Ssklower addr->dpclr = 0; 41145163Ssklower dp->dp_ostate = DPS_IDLE; 41245163Ssklower } 41345163Ssklower break; 41445163Ssklower 41545163Ssklower default: 41645163Ssklower log("if_dp%d: impossible state in dpxint\n"); 41745163Ssklower } 41845163Ssklower } 41945163Ssklower /* 42045163Ssklower * Routine to copy from device buffer into mbufs. 42145163Ssklower * 42245163Ssklower * Warning: This makes the fairly safe assumption that 42345163Ssklower * mbufs have even lengths. 42445163Ssklower */ 42545163Ssklower struct mbuf * 42645163Ssklower dpget(rxbuf, totlen, off, ifp) 42745163Ssklower caddr_t rxbuf; 42845163Ssklower int totlen, off; 42945163Ssklower struct ifnet *ifp; 43045163Ssklower { 43145163Ssklower register caddr_t cp; 43245163Ssklower register struct mbuf *m; 43345163Ssklower struct mbuf *top = 0, **mp = ⊤ 43445163Ssklower int len; 43545163Ssklower caddr_t packet_end; 43645163Ssklower 43745163Ssklower cp = rxbuf; 43845163Ssklower packet_end = cp + totlen; 43945163Ssklower if (off) { 44045163Ssklower off += 2 * sizeof(u_short); 44145163Ssklower totlen -= 2 *sizeof(u_short); 44245163Ssklower cp = rxbuf + off; 44345163Ssklower } 44445163Ssklower 44545163Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 44645163Ssklower if (m == 0) 44745163Ssklower return (0); 44845163Ssklower m->m_pkthdr.rcvif = ifp; 44945163Ssklower m->m_pkthdr.len = totlen; 45045163Ssklower m->m_len = MHLEN; 45145163Ssklower 45245163Ssklower while (totlen > 0) { 45345163Ssklower if (top) { 45445163Ssklower MGET(m, M_DONTWAIT, MT_DATA); 45545163Ssklower if (m == 0) { 45645163Ssklower m_freem(top); 45745163Ssklower return (0); 45845163Ssklower } 45945163Ssklower m->m_len = MLEN; 46045163Ssklower } 46145163Ssklower len = min(totlen, (packet_end - cp)); 46245163Ssklower if (len >= MINCLSIZE) { 46345163Ssklower MCLGET(m, M_DONTWAIT); 46445163Ssklower if (m->m_flags & M_EXT) 46545163Ssklower m->m_len = len = min(len, MCLBYTES); 46645163Ssklower else 46745163Ssklower len = m->m_len; 46845163Ssklower } else { 46945163Ssklower /* 47045163Ssklower * Place initial small packet/header at end of mbuf. 47145163Ssklower */ 47245163Ssklower if (len < m->m_len) { 47345163Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 47445163Ssklower m->m_data += max_linkhdr; 47545163Ssklower m->m_len = len; 47645163Ssklower } else 47745163Ssklower len = m->m_len; 47845163Ssklower } 47945163Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 48045163Ssklower *mp = m; 48145163Ssklower mp = &m->m_next; 48245163Ssklower totlen -= len; 48345163Ssklower cp += len; 48445163Ssklower if (cp == packet_end) 48545163Ssklower cp = rxbuf; 48645163Ssklower } 48745163Ssklower return (top); 48845163Ssklower } 48945163Ssklower 490*45228Ssklower dpinput(ifp, len, buffer) 491*45228Ssklower register struct ifnet *ifp; 49245163Ssklower caddr_t buffer; 49345163Ssklower { 49445163Ssklower register struct ifqueue *inq; 49545163Ssklower register struct mbuf *m; 496*45228Ssklower extern struct ifqueue hdintrq, ipintrq; 497*45228Ssklower int netisr; 49845163Ssklower 499*45228Ssklower ifp->if_ipackets++; 500*45228Ssklower { 501*45228Ssklower register struct ifaddr *ifa = ifp->if_addrlist; 502*45228Ssklower register u_char *cp = (u_char *)buffer; 503*45228Ssklower 504*45228Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 505*45228Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 506*45228Ssklower break; 507*45228Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 508*45228Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 509*45228Ssklower protocol. for now, IP only. */ 510*45228Ssklower buffer += 4; 511*45228Ssklower len -= 4; 512*45228Ssklower inq = &ipintrq; 513*45228Ssklower netisr = NETISR_IP; 514*45228Ssklower } else { 515*45228Ssklower inq = &hdintrq; 516*45228Ssklower netisr = NETISR_CCITT; 517*45228Ssklower } 518*45228Ssklower } 519*45228Ssklower if (len <= 0) 52045163Ssklower return; 52145163Ssklower 52245163Ssklower m = dpget(buffer, len , 0, ifp); 52345163Ssklower if (m == 0) 52445163Ssklower return; 52545163Ssklower 52645163Ssklower if(IF_QFULL(inq)) { 52745163Ssklower IF_DROP(inq); 52845163Ssklower m_freem(m); 52945163Ssklower } else { 53045163Ssklower IF_ENQUEUE(inq, m); 531*45228Ssklower schednetisr(netisr); 53245163Ssklower } 53345163Ssklower } 53445163Ssklower 53545163Ssklower /* 53645163Ssklower * Process an ioctl request. 53745163Ssklower */ 53845163Ssklower dpioctl(ifp, cmd, data) 53945163Ssklower register struct ifnet *ifp; 54045163Ssklower int cmd; 54145163Ssklower caddr_t data; 54245163Ssklower { 54345163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 54445163Ssklower int s = splimp(), error = 0; 54545166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit]; 54645163Ssklower 547*45228Ssklower dpstat.ioctl++; 54845163Ssklower switch (cmd) { 54945163Ssklower 55045163Ssklower case SIOCSIFADDR: 55145163Ssklower ifp->if_flags |= IFF_UP; 55245163Ssklower switch (ifa->ifa_addr->sa_family) { 553*45228Ssklower case AF_INET: 554*45228Ssklower ifp->if_output = dptestoutput; 55545163Ssklower default: 55645163Ssklower dpinit(ifp->if_unit); 55745163Ssklower break; 55845163Ssklower } 55945163Ssklower break; 560*45228Ssklower #ifdef CCITT 561*45228Ssklower case SIOCSIFCONF_X25: 562*45228Ssklower ifp->if_flags |= IFF_UP; 563*45228Ssklower ifp->if_output = x25_ifoutput; 564*45228Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 565*45228Ssklower if (error == 0) 566*45228Ssklower dpinit(ifp->if_unit); 567*45228Ssklower break; 568*45228Ssklower #endif 56945163Ssklower 570*45228Ssklower case SIOCSIFFLAGS: 571*45228Ssklower if ((ifp->if_flags & IFF_UP) == 0 && 572*45228Ssklower (ifp->if_flags & IFF_RUNNING)) 573*45228Ssklower dpdown(ifp->if_unit); 574*45228Ssklower else if (ifp->if_flags & IFF_UP && 575*45228Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 576*45228Ssklower dpinit(ifp->if_unit); 577*45228Ssklower break; 57845163Ssklower 579*45228Ssklower 58045163Ssklower default: 58145163Ssklower error = EINVAL; 58245163Ssklower } 58345163Ssklower splx(s); 58445163Ssklower return (error); 58545163Ssklower } 58645163Ssklower /* 58745163Ssklower * Reset a device and mark down. 58845163Ssklower * Flush output queue and drop queue limit. 58945163Ssklower */ 59045163Ssklower dpdown(unit) 59145163Ssklower int unit; 59245163Ssklower { 59345163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 59445163Ssklower 595*45228Ssklower dpstat.down++; 59645163Ssklower if_qflush(&dp->dp_if.if_snd); 597*45228Ssklower dpreset(unit); 59845163Ssklower } 59945163Ssklower 60045163Ssklower /* 60145163Ssklower * Watchdog timeout to see that transmitted packets don't 60245163Ssklower * lose interrupts. The device has to be online (the first 60345163Ssklower * transmission may block until the other side comes up). 60445163Ssklower */ 60545163Ssklower dptimeout(unit) 60645163Ssklower int unit; 60745163Ssklower { 60845163Ssklower register struct dp_softc *dp; 60945163Ssklower 610*45228Ssklower /* currently not armed */ 611*45228Ssklower dpstat.timeout++; 61245163Ssklower dp = &dp_softc[unit]; 613*45228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) { 614*45228Ssklower dpstart(&dp->dp_if); 61545163Ssklower } 61645163Ssklower } 617*45228Ssklower /* 618*45228Ssklower * For debugging loopback activity. 619*45228Ssklower */ 620*45228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 621*45228Ssklower int dp_louts; 622*45228Ssklower 623*45228Ssklower dptestoutput(ifp, m, dst, rt) 624*45228Ssklower register struct ifnet *ifp; 625*45228Ssklower register struct mbuf *m; 626*45228Ssklower struct sockaddr *dst; 627*45228Ssklower struct rtentry *rt; 628*45228Ssklower { 629*45228Ssklower /* 630*45228Ssklower * Queue message on interface, and start output if interface 631*45228Ssklower * not yet active. 632*45228Ssklower */ 633*45228Ssklower int s = splimp(), error = 0; 634*45228Ssklower dp_louts++; 635*45228Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 636*45228Ssklower if (m == 0) { 637*45228Ssklower splx(s); 638*45228Ssklower return ENOBUFS; 639*45228Ssklower } 640*45228Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 641*45228Ssklower if (IF_QFULL(&ifp->if_snd)) { 642*45228Ssklower IF_DROP(&ifp->if_snd); 643*45228Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 644*45228Ssklower ifp->if_name, ifp->if_unit);*/ 645*45228Ssklower m_freem(m); 646*45228Ssklower error = ENOBUFS; 647*45228Ssklower } else { 648*45228Ssklower IF_ENQUEUE(&ifp->if_snd, m); 649*45228Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 650*45228Ssklower (*ifp->if_start)(ifp); 651*45228Ssklower } 652*45228Ssklower splx(s); 653*45228Ssklower return (error); 654*45228Ssklower } 655*45228Ssklower 65645163Ssklower #endif 657