145163Ssklower /* 245163Ssklower * Copyright (c) 1990 Regents of the University of California. 345163Ssklower * All rights reserved. 445163Ssklower * 545163Ssklower * %sccs.include.redist.c% 645163Ssklower * 7*45236Ssklower * @(#)if_dp.c 7.4 (Berkeley) 09/14/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; 8645228Ssklower } dpstat; 8745228Ssklower /* 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 */ 10845228Ssklower int dp_ipl; 109*45236Ssklower struct dpdevice *dp_addr; /* dpcsr address */ 11045163Ssklower short dp_iused; /* input buffers given to DP */ 11145163Ssklower short dp_flags; /* flags */ 11245228Ssklower #define DPF_RUNNING 0x01 /* device initialized */ 11345228Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 11445228Ssklower #define DPF_RESTART 0x04 /* software restart in progress */ 11545228Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 11645163Ssklower short dp_ostate; /* restarting, etc. */ 11745163Ssklower short dp_istate; /* not sure this is necessary */ 11845163Ssklower #define DPS_IDLE 0 11945163Ssklower #define DPS_RESTART 1 12045163Ssklower #define DPS_ACTIVE 2 12145163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */ 12245163Ssklower int dp_errors[4]; /* non-fatal error counters */ 12345163Ssklower #define dp_datck dp_errors[0] 12445163Ssklower #define dp_timeo dp_errors[1] 12545163Ssklower #define dp_nobuf dp_errors[2] 12645163Ssklower #define dp_disc dp_errors[3] 12745228Ssklower struct timeval dp_xt; /* start of last transmission */ 12845163Ssklower char dp_obuf[DP_MTU+8]; 12945166Ssklower char dp_ibuf[DP_MTU+8]; 13045163Ssklower } dp_softc[NDP]; 13145163Ssklower 13245163Ssklower dpprobe(reg, ui) 13345163Ssklower caddr_t reg; 13445163Ssklower struct uba_device *ui; 13545163Ssklower { 13645163Ssklower register int br, cvec; 13745163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg; 138*45236Ssklower register int unit = ui->ui_unit; 13945163Ssklower 14045163Ssklower #ifdef lint 14145163Ssklower br = 0; cvec = br; br = cvec; 14245163Ssklower dprint(0); dpxint(0); 14345163Ssklower #endif 14445228Ssklower (void) spl6(); 14545163Ssklower addr->dpclr = DP_CLR; 14645163Ssklower addr->dpclr = DP_XIE|DP_XE; 14745163Ssklower DELAY(100000); 148*45236Ssklower dp_softc[unit].dp_ipl = br = qbgetpri(); 149*45236Ssklower dp_softc[unit].dp_addr = addr; 15045163Ssklower addr->dpclr = 0; 15145228Ssklower if (cvec && cvec != 0x200){ 15245228Ssklower cvec -= 4; 15345228Ssklower } 15445163Ssklower return (1); 15545163Ssklower } 15645163Ssklower 15745163Ssklower /* 15845163Ssklower * Interface exists: make available by filling in network interface 15945163Ssklower * record. System will initialize the interface when it is ready 16045163Ssklower * to accept packets. 16145163Ssklower */ 16245163Ssklower dpattach(ui) 16345163Ssklower register struct uba_device *ui; 16445163Ssklower { 16545163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 16645163Ssklower 16745163Ssklower dp->dp_if.if_unit = ui->ui_unit; 16845163Ssklower dp->dp_if.if_name = "dp"; 16945163Ssklower dp->dp_if.if_mtu = DP_MTU; 17045163Ssklower dp->dp_if.if_init = dpinit; 17145163Ssklower dp->dp_if.if_output = x25_ifoutput; 17245163Ssklower dp->dp_if.if_start = dpstart; 17345163Ssklower dp->dp_if.if_ioctl = dpioctl; 17445163Ssklower dp->dp_if.if_reset = dpreset; 17545163Ssklower dp->dp_if.if_watchdog = dptimeout; 17645228Ssklower dp->dp_if.if_flags = 0; 17745163Ssklower if_attach(&dp->dp_if); 17845163Ssklower } 17945163Ssklower 18045163Ssklower /* 18145163Ssklower * Reset of interface after UNIBUS reset. 18245163Ssklower * If interface is on specified UBA, reset its state. 18345163Ssklower */ 18445163Ssklower dpreset(unit, uban) 18545163Ssklower int unit, uban; 18645163Ssklower { 18745163Ssklower register struct uba_device *ui; 18845163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 18945163Ssklower register struct dpdevice *addr; 19045163Ssklower 19145228Ssklower dpstat.reset++; 19245163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 19345163Ssklower ui->ui_ubanum != uban) 19445163Ssklower return; 195*45236Ssklower dpdown(unit); 196*45236Ssklower dpinit(unit); 19745163Ssklower printf(" dp%d", unit); 19845163Ssklower } 19945163Ssklower 20045163Ssklower /* 20145163Ssklower * Initialization of interface. 20245163Ssklower */ 20345163Ssklower dpinit(unit) 20445163Ssklower int unit; 20545163Ssklower { 20645163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 20745163Ssklower register struct dpdevice *addr; 20845228Ssklower register struct ifaddr *ifa; 20945228Ssklower register struct pdma *pdp = &dppdma[unit*2]; 21045228Ssklower int base, s; 21145163Ssklower 21245228Ssklower dpstat.init++; 21345163Ssklower /* 21445163Ssklower * Check to see that an address has been set. 21545163Ssklower */ 21645228Ssklower for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) 21745163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 21845163Ssklower break; 21945163Ssklower if (ifa == (struct ifaddr *) 0) 22045163Ssklower return; 22145163Ssklower 222*45236Ssklower addr = dp->dp_addr; 22345228Ssklower s = splimp(); 22445163Ssklower dp->dp_iused = 0; 22545163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE; 22645228Ssklower dp->dp_if.if_flags |= IFF_RUNNING; 22745228Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 22845228Ssklower 22945228Ssklower pdp->p_addr = addr; 23045228Ssklower pdp->p_fcn = dpxint; 23145228Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf; 23245228Ssklower pdp++; 23345228Ssklower pdp->p_addr = addr; 23445228Ssklower pdp->p_fcn = dprint; 23545228Ssklower /* force initial interrupt to come to dprint */ 23645228Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; 23745228Ssklower 23845228Ssklower addr->dpclr = DP_CLR; 23945228Ssklower DELAY(1000); 24045163Ssklower addr->dpclr = 0; 24145228Ssklower DELAY(1000); 24245228Ssklower /* DP_ATA = 0, DP_CHRM = 0, 24345228Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 24445228Ssklower addr->dpsar = 0; 24545228Ssklower /* enable receive interrupt */ 24645228Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 24745228Ssklower dpstart(&dp->dp_if); 24845163Ssklower splx(s); 24945163Ssklower } 25045163Ssklower 25145228Ssklower int dpMessy = 0; 25245163Ssklower /* 25345163Ssklower * Start output on interface. Get another datagram 25445163Ssklower * to send from the interface queue and map it to 25545163Ssklower * the interface before starting output. 25645163Ssklower * 25745163Ssklower */ 25845163Ssklower dpstart(ifp) 25945163Ssklower struct ifnet *ifp; 26045163Ssklower { 26145228Ssklower int s, unit = ifp->if_unit, error = 0, len; 26245163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 263*45236Ssklower register struct dpdevice *addr = dp_addr; 26445163Ssklower register struct mbuf *m; 26545163Ssklower register char *cp; 26645163Ssklower char *cplim; 26745163Ssklower 26845163Ssklower /* 26945163Ssklower * If already doing output, go away and depend on transmit 27045163Ssklower * complete or error. 27145163Ssklower */ 27245228Ssklower dpstat.start++; 273*45236Ssklower if ((dp->dp_if.if_flags & IFF_OACTIVE) || 274*45236Ssklower ! (dp->dp_if.if_flags & IFF_RUNNING)) 27545228Ssklower goto out; 27645163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m); 27745163Ssklower if (m == 0) 27845228Ssklower goto out; 27945228Ssklower dp->dp_if.if_collisions++; 28045228Ssklower if (m->m_flags & M_PKTHDR) 28145228Ssklower len = m->m_pkthdr.len; 28245228Ssklower else { 28345228Ssklower struct mbuf *m0 = m; 28445228Ssklower for (len = 0; m; m = m->m_next) 28545228Ssklower len += m->m_len; 28645228Ssklower m = m0; 28745228Ssklower dpstat.nohdr++; 28845228Ssklower } 28945228Ssklower if (len == 0) 29045228Ssklower goto out; 29145228Ssklower if (len > DP_MTU) { 29245228Ssklower error = EINVAL; 29345228Ssklower goto out; 29445228Ssklower } 29545228Ssklower cp = dp->dp_obuf; 29645228Ssklower dppdma[2*unit].p_mem = cp + 1; 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; 30445228Ssklower if (dpMessy) 30545228Ssklower printf("dp: len %d, start %x, end %x, first %x, next %x", 30645228Ssklower len, dp->dp_obuf, cp, *(int *)dp->dp_obuf, 30745228Ssklower 1[(int *)dp->dp_obuf]); 30845163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE; 30945163Ssklower dp->dp_ostate = DPS_ACTIVE; 31045228Ssklower dp->dp_if.if_collisions--; 31145228Ssklower dp->dp_xt = time; 31245228Ssklower addr->dpclr = DP_XE | DP_XIE; 31345228Ssklower addr->dptdsr = DP_XSM | (0xff & dp->dp_obuf[0]); 31445228Ssklower out: 31545228Ssklower return (error); 31645163Ssklower } 31745163Ssklower /* 31845163Ssklower * Receive done or error interrupt 31945163Ssklower */ 32045163Ssklower dprint(unit, pdma, addr) 32145163Ssklower register struct pdma *pdma; 32245163Ssklower register struct dpdevice *addr; 32345163Ssklower { 32445166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 32545228Ssklower short rdsr = addr->dprdsr, rcsr; 32645163Ssklower 32745228Ssklower dpstat.rint++; 32845228Ssklower splx(dp->dp_ipl); 32945166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */ 33045166Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF; 33145163Ssklower pdma->p_mem = dp->dp_ibuf + 1; 33245166Ssklower dp->dp_flags &= ~DPF_FLUSH; 33345163Ssklower return; 33445163Ssklower } 33545166Ssklower if (rdsr & DP_REM) { /* Received End of Message */ 33645166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 33745166Ssklower dp->dp_if.if_ierrors++; 33845228Ssklower } else 33945228Ssklower dpinput(&dp->dp_if, 34045228Ssklower pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf); 34145228Ssklower pdma->p_mem = pdma->p_end; 34245228Ssklower dp->dp_flags &= ~ DPF_FLUSH; 34345228Ssklower return; 34445228Ssklower } 34545228Ssklower if (rdsr & DP_ROVR) { 34645228Ssklower dp->dp_flags |= DPF_FLUSH; 34745228Ssklower return; 34845228Ssklower } 34945228Ssklower rcsr = pdma->p_arg; 35045228Ssklower if (rcsr & DP_MSC) { 35145228Ssklower dpstat.mchange++; 35245228Ssklower if (0 == (rcsr & DP_DSR)) { 35345228Ssklower log(LOG_DEBUG, "dp%d: lost modem\n", unit); 35445228Ssklower dpdown(unit); 35545163Ssklower } 35645163Ssklower return; 35745163Ssklower } 35845163Ssklower dp->dp_flags |= DPF_FLUSH; 35945163Ssklower if (pdma->p_mem != pdma->p_end) 36045166Ssklower log("dp%d: unexplained receiver interrupt\n", unit); 36145163Ssklower } 36245228Ssklower struct timeval dp_xt; 36345163Ssklower 36445163Ssklower /* 36545163Ssklower * Transmit complete or error interrupt 36645163Ssklower */ 36745163Ssklower dpxint(unit, pdma, addr) 36845163Ssklower register struct pdma *pdma; 36945163Ssklower register struct dpdevice *addr; 37045163Ssklower { 37145166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 37245228Ssklower int s; 37345163Ssklower 37445228Ssklower splx(dp->dp_ipl); 37545228Ssklower dpstat.xint++; 37645163Ssklower if (addr->dptdsr & DP_XERR) { 37745163Ssklower log("if_dp%d: data late\n", unit); 37845163Ssklower restart: 37945163Ssklower pdma->p_mem = dp->dp_obuf; 38045163Ssklower addr->dptdsr = DP_XSM; 38145228Ssklower dp->dp_if.if_oerrors++; 38245163Ssklower return; 38345163Ssklower } 38445163Ssklower switch (dp->dp_ostate) { 38545163Ssklower 38645163Ssklower case DPS_ACTIVE: 38745163Ssklower if (pdma->p_mem != pdma->p_end) { 38845228Ssklower log("if_dp%d: misc error in dpxint\n", unit); 38945163Ssklower goto restart; 39045163Ssklower } 39145163Ssklower addr->dptdsr = DP_XEM; 39245163Ssklower dp->dp_ostate = DPS_XEM; 39345163Ssklower break; 39445163Ssklower 39545163Ssklower case DPS_XEM: 39645228Ssklower dp->dp_if.if_opackets++; 39745163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 39845228Ssklower s = splclock(); 39945228Ssklower dp_xt = time; 40045228Ssklower timevalsub(&dp_xt, &dp->dp_xt); 40145228Ssklower splx(s); 40245163Ssklower if (dp->dp_if.if_snd.ifq_len) 40345163Ssklower dpstart(&dp->dp_if); 40445163Ssklower else { 40545163Ssklower addr->dpclr = 0; 40645163Ssklower dp->dp_ostate = DPS_IDLE; 40745163Ssklower } 40845163Ssklower break; 40945163Ssklower 41045163Ssklower default: 41145163Ssklower log("if_dp%d: impossible state in dpxint\n"); 41245163Ssklower } 41345163Ssklower } 41445163Ssklower /* 41545163Ssklower * Routine to copy from device buffer into mbufs. 41645163Ssklower * 41745163Ssklower * Warning: This makes the fairly safe assumption that 41845163Ssklower * mbufs have even lengths. 41945163Ssklower */ 42045163Ssklower struct mbuf * 42145163Ssklower dpget(rxbuf, totlen, off, ifp) 42245163Ssklower caddr_t rxbuf; 42345163Ssklower int totlen, off; 42445163Ssklower struct ifnet *ifp; 42545163Ssklower { 42645163Ssklower register caddr_t cp; 42745163Ssklower register struct mbuf *m; 42845163Ssklower struct mbuf *top = 0, **mp = ⊤ 42945163Ssklower int len; 43045163Ssklower caddr_t packet_end; 43145163Ssklower 43245163Ssklower cp = rxbuf; 43345163Ssklower packet_end = cp + totlen; 43445163Ssklower if (off) { 43545163Ssklower off += 2 * sizeof(u_short); 43645163Ssklower totlen -= 2 *sizeof(u_short); 43745163Ssklower cp = rxbuf + off; 43845163Ssklower } 43945163Ssklower 44045163Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 44145163Ssklower if (m == 0) 44245163Ssklower return (0); 44345163Ssklower m->m_pkthdr.rcvif = ifp; 44445163Ssklower m->m_pkthdr.len = totlen; 44545163Ssklower m->m_len = MHLEN; 44645163Ssklower 44745163Ssklower while (totlen > 0) { 44845163Ssklower if (top) { 44945163Ssklower MGET(m, M_DONTWAIT, MT_DATA); 45045163Ssklower if (m == 0) { 45145163Ssklower m_freem(top); 45245163Ssklower return (0); 45345163Ssklower } 45445163Ssklower m->m_len = MLEN; 45545163Ssklower } 45645163Ssklower len = min(totlen, (packet_end - cp)); 45745163Ssklower if (len >= MINCLSIZE) { 45845163Ssklower MCLGET(m, M_DONTWAIT); 45945163Ssklower if (m->m_flags & M_EXT) 46045163Ssklower m->m_len = len = min(len, MCLBYTES); 46145163Ssklower else 46245163Ssklower len = m->m_len; 46345163Ssklower } else { 46445163Ssklower /* 46545163Ssklower * Place initial small packet/header at end of mbuf. 46645163Ssklower */ 46745163Ssklower if (len < m->m_len) { 46845163Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 46945163Ssklower m->m_data += max_linkhdr; 47045163Ssklower m->m_len = len; 47145163Ssklower } else 47245163Ssklower len = m->m_len; 47345163Ssklower } 47445163Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 47545163Ssklower *mp = m; 47645163Ssklower mp = &m->m_next; 47745163Ssklower totlen -= len; 47845163Ssklower cp += len; 47945163Ssklower if (cp == packet_end) 48045163Ssklower cp = rxbuf; 48145163Ssklower } 48245163Ssklower return (top); 48345163Ssklower } 48445163Ssklower 48545228Ssklower dpinput(ifp, len, buffer) 48645228Ssklower register struct ifnet *ifp; 48745163Ssklower caddr_t buffer; 48845163Ssklower { 48945163Ssklower register struct ifqueue *inq; 49045163Ssklower register struct mbuf *m; 49145228Ssklower extern struct ifqueue hdintrq, ipintrq; 49245228Ssklower int netisr; 49345163Ssklower 49445228Ssklower ifp->if_ipackets++; 49545228Ssklower { 49645228Ssklower register struct ifaddr *ifa = ifp->if_addrlist; 49745228Ssklower register u_char *cp = (u_char *)buffer; 49845228Ssklower 49945228Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 50045228Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 50145228Ssklower break; 50245228Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 50345228Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 50445228Ssklower protocol. for now, IP only. */ 50545228Ssklower buffer += 4; 50645228Ssklower len -= 4; 50745228Ssklower inq = &ipintrq; 50845228Ssklower netisr = NETISR_IP; 50945228Ssklower } else { 51045228Ssklower inq = &hdintrq; 51145228Ssklower netisr = NETISR_CCITT; 51245228Ssklower } 51345228Ssklower } 51445228Ssklower if (len <= 0) 51545163Ssklower return; 51645163Ssklower 51745163Ssklower m = dpget(buffer, len , 0, ifp); 51845163Ssklower if (m == 0) 51945163Ssklower return; 52045163Ssklower 52145163Ssklower if(IF_QFULL(inq)) { 52245163Ssklower IF_DROP(inq); 52345163Ssklower m_freem(m); 52445163Ssklower } else { 52545163Ssklower IF_ENQUEUE(inq, m); 52645228Ssklower schednetisr(netisr); 52745163Ssklower } 52845163Ssklower } 52945163Ssklower 53045163Ssklower /* 53145163Ssklower * Process an ioctl request. 53245163Ssklower */ 53345163Ssklower dpioctl(ifp, cmd, data) 53445163Ssklower register struct ifnet *ifp; 53545163Ssklower int cmd; 53645163Ssklower caddr_t data; 53745163Ssklower { 53845163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 53945163Ssklower int s = splimp(), error = 0; 54045166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit]; 54145163Ssklower 54245228Ssklower dpstat.ioctl++; 54345163Ssklower switch (cmd) { 54445163Ssklower 54545163Ssklower case SIOCSIFADDR: 54645163Ssklower ifp->if_flags |= IFF_UP; 54745163Ssklower switch (ifa->ifa_addr->sa_family) { 54845228Ssklower case AF_INET: 54945228Ssklower ifp->if_output = dptestoutput; 55045163Ssklower default: 55145163Ssklower dpinit(ifp->if_unit); 55245163Ssklower break; 55345163Ssklower } 55445163Ssklower break; 55545228Ssklower #ifdef CCITT 55645228Ssklower case SIOCSIFCONF_X25: 55745228Ssklower ifp->if_flags |= IFF_UP; 55845228Ssklower ifp->if_output = x25_ifoutput; 55945228Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 56045228Ssklower if (error == 0) 56145228Ssklower dpinit(ifp->if_unit); 56245228Ssklower break; 56345228Ssklower #endif 56445163Ssklower 56545228Ssklower case SIOCSIFFLAGS: 56645228Ssklower if ((ifp->if_flags & IFF_UP) == 0 && 56745228Ssklower (ifp->if_flags & IFF_RUNNING)) 56845228Ssklower dpdown(ifp->if_unit); 56945228Ssklower else if (ifp->if_flags & IFF_UP && 57045228Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 57145228Ssklower dpinit(ifp->if_unit); 57245228Ssklower break; 57345163Ssklower 57445228Ssklower 57545163Ssklower default: 57645163Ssklower error = EINVAL; 57745163Ssklower } 57845163Ssklower splx(s); 57945163Ssklower return (error); 58045163Ssklower } 58145163Ssklower /* 58245163Ssklower * Reset a device and mark down. 58345163Ssklower * Flush output queue and drop queue limit. 58445163Ssklower */ 58545163Ssklower dpdown(unit) 586*45236Ssklower int unit; 58745163Ssklower { 588*45236Ssklower 58945163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 590*45236Ssklower register struct dpdevice *addr = dp->dp_addr; 59145163Ssklower 59245228Ssklower dpstat.down++; 59345163Ssklower if_qflush(&dp->dp_if.if_snd); 594*45236Ssklower dp->dp_flags = 0; 595*45236Ssklower dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 596*45236Ssklower 597*45236Ssklower addr->dpclr = DP_CLR; 598*45236Ssklower DELAY(1000); 599*45236Ssklower addr->dpsar = 0; 600*45236Ssklower addr->dprcsr = 0; 60145163Ssklower } 60245163Ssklower 60345163Ssklower /* 60445163Ssklower * Watchdog timeout to see that transmitted packets don't 60545163Ssklower * lose interrupts. The device has to be online (the first 60645163Ssklower * transmission may block until the other side comes up). 60745163Ssklower */ 60845163Ssklower dptimeout(unit) 60945163Ssklower int unit; 61045163Ssklower { 61145163Ssklower register struct dp_softc *dp; 61245163Ssklower 61345228Ssklower /* currently not armed */ 61445228Ssklower dpstat.timeout++; 61545163Ssklower dp = &dp_softc[unit]; 61645228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) { 61745228Ssklower dpstart(&dp->dp_if); 61845163Ssklower } 61945163Ssklower } 62045228Ssklower /* 62145228Ssklower * For debugging loopback activity. 62245228Ssklower */ 62345228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 62445228Ssklower int dp_louts; 62545228Ssklower 62645228Ssklower dptestoutput(ifp, m, dst, rt) 62745228Ssklower register struct ifnet *ifp; 62845228Ssklower register struct mbuf *m; 62945228Ssklower struct sockaddr *dst; 63045228Ssklower struct rtentry *rt; 63145228Ssklower { 63245228Ssklower /* 63345228Ssklower * Queue message on interface, and start output if interface 63445228Ssklower * not yet active. 63545228Ssklower */ 63645228Ssklower int s = splimp(), error = 0; 63745228Ssklower dp_louts++; 63845228Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 63945228Ssklower if (m == 0) { 64045228Ssklower splx(s); 64145228Ssklower return ENOBUFS; 64245228Ssklower } 64345228Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 64445228Ssklower if (IF_QFULL(&ifp->if_snd)) { 64545228Ssklower IF_DROP(&ifp->if_snd); 64645228Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 64745228Ssklower ifp->if_name, ifp->if_unit);*/ 64845228Ssklower m_freem(m); 64945228Ssklower error = ENOBUFS; 65045228Ssklower } else { 65145228Ssklower IF_ENQUEUE(&ifp->if_snd, m); 65245228Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 65345228Ssklower (*ifp->if_start)(ifp); 65445228Ssklower } 65545228Ssklower splx(s); 65645228Ssklower return (error); 65745228Ssklower } 65845228Ssklower 65945163Ssklower #endif 660