145163Ssklower /* 245163Ssklower * Copyright (c) 1990 Regents of the University of California. 345163Ssklower * All rights reserved. 445163Ssklower * 545163Ssklower * %sccs.include.redist.c% 645163Ssklower * 7*45237Ssklower * @(#)if_dp.c 7.5 (Berkeley) 09/17/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" 3645228Ssklower #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 5045228Ssklower #define dzdevice dpdevice 5145163Ssklower #include "../vaxuba/pdma.h" 5245166Ssklower #include "../vaxuba/ubavar.h" 5345163Ssklower 5445228Ssklower #include "../netccitt/x25.h" 5545228Ssklower #include "../netccitt/pk.h" 5645228Ssklower #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(); 6445228Ssklower 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 /* 7345228Ssklower * debug info 7445228Ssklower */ 7545228Ssklower struct dpstat { 7645228Ssklower long start; 7745228Ssklower long nohdr; 7845228Ssklower long init; 7945228Ssklower long rint; 8045228Ssklower long xint; 8145228Ssklower long reset; 8245228Ssklower long ioctl; 8345228Ssklower long down; 8445228Ssklower long mchange; 8545228Ssklower long timeout; 86*45237Ssklower long rsm; 87*45237Ssklower long rem; 88*45237Ssklower long rsmchr; 89*45237Ssklower long rga; 9045228Ssklower } dpstat; 9145228Ssklower /* 9245163Ssklower * Pdma structures for fast interrupts. 9345163Ssklower */ 9445163Ssklower struct pdma dppdma[2*NDP]; 9545163Ssklower 9645163Ssklower /* error reporting intervals */ 9745163Ssklower #define DPI_RPNBFS 50 9845163Ssklower #define DPI_RPDSC 1 9945163Ssklower #define DPI_RPTMO 10 10045163Ssklower #define DPI_RPDCK 10 10145163Ssklower 10245163Ssklower 10345163Ssklower /* 10445163Ssklower * DP software status per interface. 10545163Ssklower * 10645163Ssklower * Each interface is referenced by a network interface structure, 10745163Ssklower * dp_if, which the routing code uses to locate the interface. 10845163Ssklower * This structure contains the output queue for the interface, its address, ... 10945163Ssklower */ 11045163Ssklower struct dp_softc { 11145163Ssklower struct ifnet dp_if; /* network-visible interface */ 11245228Ssklower int dp_ipl; 11345236Ssklower struct dpdevice *dp_addr; /* dpcsr address */ 11445163Ssklower short dp_iused; /* input buffers given to DP */ 11545163Ssklower short dp_flags; /* flags */ 11645228Ssklower #define DPF_RUNNING 0x01 /* device initialized */ 11745228Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 11845228Ssklower #define DPF_RESTART 0x04 /* software restart in progress */ 11945228Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 12045163Ssklower short dp_ostate; /* restarting, etc. */ 12145163Ssklower short dp_istate; /* not sure this is necessary */ 12245163Ssklower #define DPS_IDLE 0 12345163Ssklower #define DPS_RESTART 1 12445163Ssklower #define DPS_ACTIVE 2 12545163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */ 12645163Ssklower int dp_errors[4]; /* non-fatal error counters */ 12745163Ssklower #define dp_datck dp_errors[0] 12845163Ssklower #define dp_timeo dp_errors[1] 12945163Ssklower #define dp_nobuf dp_errors[2] 13045163Ssklower #define dp_disc dp_errors[3] 13145163Ssklower char dp_obuf[DP_MTU+8]; 13245166Ssklower char dp_ibuf[DP_MTU+8]; 13345163Ssklower } dp_softc[NDP]; 13445163Ssklower 13545163Ssklower dpprobe(reg, ui) 13645163Ssklower caddr_t reg; 13745163Ssklower struct uba_device *ui; 13845163Ssklower { 13945163Ssklower register int br, cvec; 14045163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg; 14145236Ssklower register int unit = ui->ui_unit; 14245163Ssklower 14345163Ssklower #ifdef lint 14445163Ssklower br = 0; cvec = br; br = cvec; 14545163Ssklower dprint(0); dpxint(0); 14645163Ssklower #endif 14745228Ssklower (void) spl6(); 14845163Ssklower addr->dpclr = DP_CLR; 14945163Ssklower addr->dpclr = DP_XIE|DP_XE; 15045163Ssklower DELAY(100000); 15145236Ssklower dp_softc[unit].dp_ipl = br = qbgetpri(); 15245236Ssklower dp_softc[unit].dp_addr = addr; 15345163Ssklower addr->dpclr = 0; 15445228Ssklower if (cvec && cvec != 0x200){ 15545228Ssklower cvec -= 4; 15645228Ssklower } 15745163Ssklower return (1); 15845163Ssklower } 15945163Ssklower 16045163Ssklower /* 16145163Ssklower * Interface exists: make available by filling in network interface 16245163Ssklower * record. System will initialize the interface when it is ready 16345163Ssklower * to accept packets. 16445163Ssklower */ 16545163Ssklower dpattach(ui) 16645163Ssklower register struct uba_device *ui; 16745163Ssklower { 16845163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 16945163Ssklower 17045163Ssklower dp->dp_if.if_unit = ui->ui_unit; 17145163Ssklower dp->dp_if.if_name = "dp"; 17245163Ssklower dp->dp_if.if_mtu = DP_MTU; 17345163Ssklower dp->dp_if.if_init = dpinit; 17445163Ssklower dp->dp_if.if_output = x25_ifoutput; 17545163Ssklower dp->dp_if.if_start = dpstart; 17645163Ssklower dp->dp_if.if_ioctl = dpioctl; 17745163Ssklower dp->dp_if.if_reset = dpreset; 17845163Ssklower dp->dp_if.if_watchdog = dptimeout; 17945228Ssklower dp->dp_if.if_flags = 0; 18045163Ssklower if_attach(&dp->dp_if); 18145163Ssklower } 18245163Ssklower 18345163Ssklower /* 18445163Ssklower * Reset of interface after UNIBUS reset. 18545163Ssklower * If interface is on specified UBA, reset its state. 18645163Ssklower */ 18745163Ssklower dpreset(unit, uban) 18845163Ssklower int unit, uban; 18945163Ssklower { 19045163Ssklower register struct uba_device *ui; 19145163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 19245163Ssklower register struct dpdevice *addr; 19345163Ssklower 19445228Ssklower dpstat.reset++; 19545163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 19645163Ssklower ui->ui_ubanum != uban) 19745163Ssklower return; 19845236Ssklower dpdown(unit); 19945236Ssklower dpinit(unit); 20045163Ssklower printf(" dp%d", unit); 20145163Ssklower } 20245163Ssklower 20345163Ssklower /* 20445163Ssklower * Initialization of interface. 20545163Ssklower */ 20645163Ssklower dpinit(unit) 20745163Ssklower int unit; 20845163Ssklower { 20945163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 21045163Ssklower register struct dpdevice *addr; 21145228Ssklower register struct ifaddr *ifa; 21245228Ssklower register struct pdma *pdp = &dppdma[unit*2]; 21345228Ssklower int base, s; 21445163Ssklower 21545228Ssklower dpstat.init++; 21645163Ssklower /* 21745163Ssklower * Check to see that an address has been set. 21845163Ssklower */ 21945228Ssklower for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) 22045163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 22145163Ssklower break; 22245163Ssklower if (ifa == (struct ifaddr *) 0) 22345163Ssklower return; 22445163Ssklower 22545236Ssklower addr = dp->dp_addr; 22645228Ssklower s = splimp(); 22745163Ssklower dp->dp_iused = 0; 22845163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE; 22945228Ssklower dp->dp_if.if_flags |= IFF_RUNNING; 23045228Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 23145228Ssklower 23245228Ssklower pdp->p_addr = addr; 23345228Ssklower pdp->p_fcn = dpxint; 23445228Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf; 23545228Ssklower pdp++; 23645228Ssklower pdp->p_addr = addr; 23745228Ssklower pdp->p_fcn = dprint; 23845228Ssklower /* force initial interrupt to come to dprint */ 23945228Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; 24045228Ssklower 24145228Ssklower addr->dpclr = DP_CLR; 24245228Ssklower DELAY(1000); 243*45237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 244*45237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 245*45237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 24645163Ssklower addr->dpclr = 0; 247*45237Ssklower /* enable receiver, receive interrupt, DTR, RTS */ 24845228Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 24945228Ssklower dpstart(&dp->dp_if); 25045163Ssklower splx(s); 25145163Ssklower } 25245163Ssklower 25345163Ssklower /* 25445163Ssklower * Start output on interface. Get another datagram 25545163Ssklower * to send from the interface queue and map it to 25645163Ssklower * the interface before starting output. 25745163Ssklower * 25845163Ssklower */ 25945163Ssklower dpstart(ifp) 26045163Ssklower struct ifnet *ifp; 26145163Ssklower { 26245228Ssklower int s, unit = ifp->if_unit, error = 0, len; 26345163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 264*45237Ssklower register struct dpdevice *addr = dp->dp_addr; 26545163Ssklower register struct mbuf *m; 26645163Ssklower register char *cp; 26745163Ssklower char *cplim; 26845163Ssklower 26945163Ssklower /* 27045163Ssklower * If already doing output, go away and depend on transmit 27145163Ssklower * complete or error. 27245163Ssklower */ 27345228Ssklower dpstat.start++; 27445236Ssklower if ((dp->dp_if.if_flags & IFF_OACTIVE) || 27545236Ssklower ! (dp->dp_if.if_flags & IFF_RUNNING)) 27645228Ssklower goto out; 27745163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m); 27845163Ssklower if (m == 0) 27945228Ssklower goto out; 28045228Ssklower dp->dp_if.if_collisions++; 28145228Ssklower if (m->m_flags & M_PKTHDR) 28245228Ssklower len = m->m_pkthdr.len; 28345228Ssklower else { 28445228Ssklower struct mbuf *m0 = m; 28545228Ssklower for (len = 0; m; m = m->m_next) 28645228Ssklower len += m->m_len; 28745228Ssklower m = m0; 28845228Ssklower dpstat.nohdr++; 28945228Ssklower } 29045228Ssklower if (len == 0) 29145228Ssklower goto out; 29245228Ssklower if (len > DP_MTU) { 29345228Ssklower error = EINVAL; 29445228Ssklower goto out; 29545228Ssklower } 296*45237Ssklower dppdma[2*unit].p_mem = 1 + (cp = dp->dp_obuf); 29745163Ssklower while (m) { 29845163Ssklower struct mbuf *n; 29945163Ssklower bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 30045163Ssklower cp += m->m_len; 30145163Ssklower MFREE(m, n); m = n; 30245163Ssklower } 30345163Ssklower dppdma[2*unit].p_end = cp; 30445163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE; 30545163Ssklower dp->dp_ostate = DPS_ACTIVE; 30645228Ssklower dp->dp_if.if_collisions--; 307*45237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 308*45237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 309*45237Ssklower addr->dpclr = DP_XIE | DP_XE; 310*45237Ssklower addr->dptdsr = DP_XSM | (0xff & *cp); 31145228Ssklower out: 31245228Ssklower return (error); 31345163Ssklower } 314*45237Ssklower long dp_rdsr; 31545163Ssklower /* 31645163Ssklower * Receive done or error interrupt 31745163Ssklower */ 31845163Ssklower dprint(unit, pdma, addr) 31945163Ssklower register struct pdma *pdma; 32045163Ssklower register struct dpdevice *addr; 32145163Ssklower { 32245166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 323*45237Ssklower short rdsr = addr->dprdsr, rcsr = pdma->p_arg; 32445163Ssklower 32545228Ssklower dpstat.rint++; 326*45237Ssklower dp_rdsr = rdsr; 32745228Ssklower splx(dp->dp_ipl); 328*45237Ssklower if (rdsr & DP_RGA) { 329*45237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 330*45237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 331*45237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 332*45237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 333*45237Ssklower dpstat.rga++; 334*45237Ssklower return; 335*45237Ssklower } 33645166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */ 337*45237Ssklower dpstat.rsm++; 338*45237Ssklower pdma->p_mem = dp->dp_ibuf; 339*45237Ssklower if (rcsr & DP_RDR) { 340*45237Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF; 341*45237Ssklower pdma->p_mem++; 342*45237Ssklower dpstat.rsmchr++; 343*45237Ssklower } 34445166Ssklower dp->dp_flags &= ~DPF_FLUSH; 34545163Ssklower return; 34645163Ssklower } 34745166Ssklower if (rdsr & DP_REM) { /* Received End of Message */ 348*45237Ssklower dpstat.rem++; 34945166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 35045166Ssklower dp->dp_if.if_ierrors++; 35145228Ssklower } else 35245228Ssklower dpinput(&dp->dp_if, 35345228Ssklower pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf); 35445228Ssklower pdma->p_mem = pdma->p_end; 35545228Ssklower dp->dp_flags &= ~ DPF_FLUSH; 35645228Ssklower return; 35745228Ssklower } 35845228Ssklower if (rdsr & DP_ROVR) { 35945228Ssklower dp->dp_flags |= DPF_FLUSH; 36045228Ssklower return; 36145228Ssklower } 36245228Ssklower if (rcsr & DP_MSC) { 36345228Ssklower dpstat.mchange++; 36445228Ssklower if (0 == (rcsr & DP_DSR)) { 36545228Ssklower log(LOG_DEBUG, "dp%d: lost modem\n", unit); 366*45237Ssklower /*dpdown(unit);*/ 36745163Ssklower } 36845163Ssklower return; 36945163Ssklower } 37045163Ssklower dp->dp_flags |= DPF_FLUSH; 37145163Ssklower if (pdma->p_mem != pdma->p_end) 37245166Ssklower log("dp%d: unexplained receiver interrupt\n", unit); 37345163Ssklower } 374*45237Ssklower int dp_fill; 37545163Ssklower 37645163Ssklower /* 37745163Ssklower * Transmit complete or error interrupt 37845163Ssklower */ 37945163Ssklower dpxint(unit, pdma, addr) 38045163Ssklower register struct pdma *pdma; 38145163Ssklower register struct dpdevice *addr; 38245163Ssklower { 38345166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 38445228Ssklower int s; 38545163Ssklower 38645228Ssklower splx(dp->dp_ipl); 38745228Ssklower dpstat.xint++; 38845163Ssklower if (addr->dptdsr & DP_XERR) { 38945163Ssklower log("if_dp%d: data late\n", unit); 39045163Ssklower restart: 39145163Ssklower pdma->p_mem = dp->dp_obuf; 39245163Ssklower addr->dptdsr = DP_XSM; 39345228Ssklower dp->dp_if.if_oerrors++; 39445163Ssklower return; 39545163Ssklower } 39645163Ssklower switch (dp->dp_ostate) { 39745163Ssklower 39845163Ssklower case DPS_ACTIVE: 39945163Ssklower if (pdma->p_mem != pdma->p_end) { 40045228Ssklower log("if_dp%d: misc error in dpxint\n", unit); 40145163Ssklower goto restart; 40245163Ssklower } 403*45237Ssklower addr->dpclr = DP_XIE; /* &= ~DP_XE */ 40445163Ssklower addr->dptdsr = DP_XEM; 40545163Ssklower dp->dp_ostate = DPS_XEM; 40645163Ssklower break; 40745163Ssklower 40845163Ssklower case DPS_XEM: 40945228Ssklower dp->dp_if.if_opackets++; 41045163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 41145163Ssklower if (dp->dp_if.if_snd.ifq_len) 41245163Ssklower dpstart(&dp->dp_if); 41345163Ssklower else { 414*45237Ssklower if (dp_fill) { 415*45237Ssklower addr->dpsar = DP_IDLE|DP_SSLM; 416*45237Ssklower addr->dptdsr = DP_XABO; 417*45237Ssklower } else { 418*45237Ssklower addr->dptdsr = 0; 419*45237Ssklower } 42045163Ssklower addr->dpclr = 0; 42145163Ssklower dp->dp_ostate = DPS_IDLE; 42245163Ssklower } 42345163Ssklower break; 42445163Ssklower 42545163Ssklower default: 42645163Ssklower log("if_dp%d: impossible state in dpxint\n"); 42745163Ssklower } 42845163Ssklower } 42945163Ssklower /* 43045163Ssklower * Routine to copy from device buffer into mbufs. 43145163Ssklower * 43245163Ssklower * Warning: This makes the fairly safe assumption that 43345163Ssklower * mbufs have even lengths. 43445163Ssklower */ 43545163Ssklower struct mbuf * 43645163Ssklower dpget(rxbuf, totlen, off, ifp) 43745163Ssklower caddr_t rxbuf; 43845163Ssklower int totlen, off; 43945163Ssklower struct ifnet *ifp; 44045163Ssklower { 44145163Ssklower register caddr_t cp; 44245163Ssklower register struct mbuf *m; 44345163Ssklower struct mbuf *top = 0, **mp = ⊤ 44445163Ssklower int len; 44545163Ssklower caddr_t packet_end; 44645163Ssklower 44745163Ssklower cp = rxbuf; 44845163Ssklower packet_end = cp + totlen; 44945163Ssklower if (off) { 45045163Ssklower off += 2 * sizeof(u_short); 45145163Ssklower totlen -= 2 *sizeof(u_short); 45245163Ssklower cp = rxbuf + off; 45345163Ssklower } 45445163Ssklower 45545163Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 45645163Ssklower if (m == 0) 45745163Ssklower return (0); 45845163Ssklower m->m_pkthdr.rcvif = ifp; 45945163Ssklower m->m_pkthdr.len = totlen; 46045163Ssklower m->m_len = MHLEN; 46145163Ssklower 46245163Ssklower while (totlen > 0) { 46345163Ssklower if (top) { 46445163Ssklower MGET(m, M_DONTWAIT, MT_DATA); 46545163Ssklower if (m == 0) { 46645163Ssklower m_freem(top); 46745163Ssklower return (0); 46845163Ssklower } 46945163Ssklower m->m_len = MLEN; 47045163Ssklower } 47145163Ssklower len = min(totlen, (packet_end - cp)); 47245163Ssklower if (len >= MINCLSIZE) { 47345163Ssklower MCLGET(m, M_DONTWAIT); 47445163Ssklower if (m->m_flags & M_EXT) 47545163Ssklower m->m_len = len = min(len, MCLBYTES); 47645163Ssklower else 47745163Ssklower len = m->m_len; 47845163Ssklower } else { 47945163Ssklower /* 48045163Ssklower * Place initial small packet/header at end of mbuf. 48145163Ssklower */ 48245163Ssklower if (len < m->m_len) { 48345163Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 48445163Ssklower m->m_data += max_linkhdr; 48545163Ssklower m->m_len = len; 48645163Ssklower } else 48745163Ssklower len = m->m_len; 48845163Ssklower } 48945163Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 49045163Ssklower *mp = m; 49145163Ssklower mp = &m->m_next; 49245163Ssklower totlen -= len; 49345163Ssklower cp += len; 49445163Ssklower if (cp == packet_end) 49545163Ssklower cp = rxbuf; 49645163Ssklower } 49745163Ssklower return (top); 49845163Ssklower } 49945163Ssklower 50045228Ssklower dpinput(ifp, len, buffer) 50145228Ssklower register struct ifnet *ifp; 50245163Ssklower caddr_t buffer; 50345163Ssklower { 50445163Ssklower register struct ifqueue *inq; 50545163Ssklower register struct mbuf *m; 50645228Ssklower extern struct ifqueue hdintrq, ipintrq; 50745228Ssklower int netisr; 50845163Ssklower 50945228Ssklower ifp->if_ipackets++; 51045228Ssklower { 51145228Ssklower register struct ifaddr *ifa = ifp->if_addrlist; 51245228Ssklower register u_char *cp = (u_char *)buffer; 51345228Ssklower 51445228Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 51545228Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 51645228Ssklower break; 51745228Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 51845228Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 51945228Ssklower protocol. for now, IP only. */ 52045228Ssklower buffer += 4; 52145228Ssklower len -= 4; 52245228Ssklower inq = &ipintrq; 52345228Ssklower netisr = NETISR_IP; 52445228Ssklower } else { 52545228Ssklower inq = &hdintrq; 52645228Ssklower netisr = NETISR_CCITT; 52745228Ssklower } 52845228Ssklower } 52945228Ssklower if (len <= 0) 53045163Ssklower return; 53145163Ssklower 53245163Ssklower m = dpget(buffer, len , 0, ifp); 53345163Ssklower if (m == 0) 53445163Ssklower return; 53545163Ssklower 53645163Ssklower if(IF_QFULL(inq)) { 53745163Ssklower IF_DROP(inq); 53845163Ssklower m_freem(m); 53945163Ssklower } else { 54045163Ssklower IF_ENQUEUE(inq, m); 54145228Ssklower schednetisr(netisr); 54245163Ssklower } 54345163Ssklower } 54445163Ssklower 54545163Ssklower /* 54645163Ssklower * Process an ioctl request. 54745163Ssklower */ 54845163Ssklower dpioctl(ifp, cmd, data) 54945163Ssklower register struct ifnet *ifp; 55045163Ssklower int cmd; 55145163Ssklower caddr_t data; 55245163Ssklower { 55345163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 55445163Ssklower int s = splimp(), error = 0; 55545166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit]; 55645163Ssklower 55745228Ssklower dpstat.ioctl++; 55845163Ssklower switch (cmd) { 55945163Ssklower 56045163Ssklower case SIOCSIFADDR: 56145163Ssklower ifp->if_flags |= IFF_UP; 56245163Ssklower switch (ifa->ifa_addr->sa_family) { 56345228Ssklower case AF_INET: 56445228Ssklower ifp->if_output = dptestoutput; 56545163Ssklower default: 56645163Ssklower dpinit(ifp->if_unit); 56745163Ssklower break; 56845163Ssklower } 56945163Ssklower break; 57045228Ssklower #ifdef CCITT 57145228Ssklower case SIOCSIFCONF_X25: 57245228Ssklower ifp->if_flags |= IFF_UP; 57345228Ssklower ifp->if_output = x25_ifoutput; 57445228Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 57545228Ssklower if (error == 0) 57645228Ssklower dpinit(ifp->if_unit); 57745228Ssklower break; 57845228Ssklower #endif 57945163Ssklower 58045228Ssklower case SIOCSIFFLAGS: 58145228Ssklower if ((ifp->if_flags & IFF_UP) == 0 && 58245228Ssklower (ifp->if_flags & IFF_RUNNING)) 58345228Ssklower dpdown(ifp->if_unit); 58445228Ssklower else if (ifp->if_flags & IFF_UP && 58545228Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 58645228Ssklower dpinit(ifp->if_unit); 58745228Ssklower break; 58845163Ssklower 58945228Ssklower 59045163Ssklower default: 59145163Ssklower error = EINVAL; 59245163Ssklower } 59345163Ssklower splx(s); 59445163Ssklower return (error); 59545163Ssklower } 59645163Ssklower /* 59745163Ssklower * Reset a device and mark down. 59845163Ssklower * Flush output queue and drop queue limit. 59945163Ssklower */ 60045163Ssklower dpdown(unit) 60145236Ssklower int unit; 60245163Ssklower { 60345236Ssklower 60445163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 60545236Ssklower register struct dpdevice *addr = dp->dp_addr; 60645163Ssklower 60745228Ssklower dpstat.down++; 60845163Ssklower if_qflush(&dp->dp_if.if_snd); 60945236Ssklower dp->dp_flags = 0; 61045236Ssklower dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 61145236Ssklower 61245236Ssklower addr->dpclr = DP_CLR; 61345236Ssklower DELAY(1000); 61445236Ssklower addr->dpsar = 0; 61545236Ssklower addr->dprcsr = 0; 61645163Ssklower } 61745163Ssklower 61845163Ssklower /* 61945163Ssklower * Watchdog timeout to see that transmitted packets don't 62045163Ssklower * lose interrupts. The device has to be online (the first 62145163Ssklower * transmission may block until the other side comes up). 62245163Ssklower */ 62345163Ssklower dptimeout(unit) 62445163Ssklower int unit; 62545163Ssklower { 62645163Ssklower register struct dp_softc *dp; 62745163Ssklower 62845228Ssklower /* currently not armed */ 62945228Ssklower dpstat.timeout++; 63045163Ssklower dp = &dp_softc[unit]; 63145228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) { 63245228Ssklower dpstart(&dp->dp_if); 63345163Ssklower } 63445163Ssklower } 63545228Ssklower /* 63645228Ssklower * For debugging loopback activity. 63745228Ssklower */ 63845228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 63945228Ssklower int dp_louts; 64045228Ssklower 64145228Ssklower dptestoutput(ifp, m, dst, rt) 64245228Ssklower register struct ifnet *ifp; 64345228Ssklower register struct mbuf *m; 64445228Ssklower struct sockaddr *dst; 64545228Ssklower struct rtentry *rt; 64645228Ssklower { 64745228Ssklower /* 64845228Ssklower * Queue message on interface, and start output if interface 64945228Ssklower * not yet active. 65045228Ssklower */ 65145228Ssklower int s = splimp(), error = 0; 65245228Ssklower dp_louts++; 65345228Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 65445228Ssklower if (m == 0) { 65545228Ssklower splx(s); 65645228Ssklower return ENOBUFS; 65745228Ssklower } 65845228Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 65945228Ssklower if (IF_QFULL(&ifp->if_snd)) { 66045228Ssklower IF_DROP(&ifp->if_snd); 66145228Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 66245228Ssklower ifp->if_name, ifp->if_unit);*/ 66345228Ssklower m_freem(m); 66445228Ssklower error = ENOBUFS; 66545228Ssklower } else { 66645228Ssklower IF_ENQUEUE(&ifp->if_snd, m); 66745228Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 66845228Ssklower (*ifp->if_start)(ifp); 66945228Ssklower } 67045228Ssklower splx(s); 67145228Ssklower return (error); 67245228Ssklower } 67345228Ssklower 67445163Ssklower #endif 675