145163Ssklower /* 245163Ssklower * Copyright (c) 1990 Regents of the University of California. 345163Ssklower * All rights reserved. 445163Ssklower * 545163Ssklower * %sccs.include.redist.c% 645163Ssklower * 7*45801Sbostic * @(#)if_dp.c 7.7 (Berkeley) 12/16/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 27*45801Sbostic #include "../include/pte.h" 2845163Ssklower 29*45801Sbostic #include "sys/param.h" 30*45801Sbostic #include "sys/systm.h" 31*45801Sbostic #include "sys/mbuf.h" 32*45801Sbostic #include "sys/buf.h" 33*45801Sbostic #include "sys/ioctl.h" /* must precede tty.h */ 34*45801Sbostic #include "sys/protosw.h" 35*45801Sbostic #include "sys/socket.h" 36*45801Sbostic #include "sys/socketvar.h" 37*45801Sbostic #include "sys/syslog.h" 38*45801Sbostic #include "sys/vmmac.h" 39*45801Sbostic #include "sys/errno.h" 40*45801Sbostic #include "sys/time.h" 41*45801Sbostic #include "sys/kernel.h" 4245163Ssklower 43*45801Sbostic #include "net/if.h" 44*45801Sbostic #include "net/netisr.h" 45*45801Sbostic #include "net/route.h" 4645163Ssklower 47*45801Sbostic #include "../include/cpu.h" 48*45801Sbostic #include "../include/mtpr.h" 4945166Ssklower 5045228Ssklower #define dzdevice dpdevice 51*45801Sbostic #include "../uba/pdma.h" 52*45801Sbostic #include "../uba/ubavar.h" 5345163Ssklower 54*45801Sbostic #include "netccitt/x25.h" 55*45801Sbostic #include "netccitt/pk.h" 56*45801Sbostic #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 /* 7345163Ssklower * Pdma structures for fast interrupts. 7445163Ssklower */ 7545163Ssklower struct pdma dppdma[2*NDP]; 7645163Ssklower 7745163Ssklower /* 7845163Ssklower * DP software status per interface. 7945163Ssklower * 8045163Ssklower * Each interface is referenced by a network interface structure, 8145163Ssklower * dp_if, which the routing code uses to locate the interface. 8245163Ssklower * This structure contains the output queue for the interface, its address, ... 8345163Ssklower */ 8445163Ssklower struct dp_softc { 8545163Ssklower struct ifnet dp_if; /* network-visible interface */ 8645228Ssklower int dp_ipl; 8745236Ssklower struct dpdevice *dp_addr; /* dpcsr address */ 8845163Ssklower short dp_iused; /* input buffers given to DP */ 8945163Ssklower short dp_flags; /* flags */ 9045228Ssklower #define DPF_RUNNING 0x01 /* device initialized */ 9145228Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 9245228Ssklower #define DPF_RESTART 0x04 /* software restart in progress */ 9345228Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 9445163Ssklower short dp_ostate; /* restarting, etc. */ 9545163Ssklower short dp_istate; /* not sure this is necessary */ 9645163Ssklower #define DPS_IDLE 0 9745163Ssklower #define DPS_RESTART 1 9845163Ssklower #define DPS_ACTIVE 2 9945163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */ 10045289Ssklower short dp_olen; /* length of last packet sent */ 10145289Ssklower short dp_ilen; /* length of last packet recvd */ 10245163Ssklower char dp_obuf[DP_MTU+8]; 10345166Ssklower char dp_ibuf[DP_MTU+8]; 10445163Ssklower } dp_softc[NDP]; 10545163Ssklower 10645289Ssklower /* 10745289Ssklower * Debug info 10845289Ssklower */ 10945289Ssklower struct dpstat { 11045289Ssklower long start; 11145289Ssklower long nohdr; 11245289Ssklower long init; 11345289Ssklower long rint; 11445289Ssklower long xint; 11545289Ssklower long reset; 11645289Ssklower long ioctl; 11745289Ssklower long down; 11845289Ssklower long mchange; 11945289Ssklower long timeout; 12045289Ssklower long rsm; 12145289Ssklower long rem; 12245289Ssklower long remchr; 12345289Ssklower long rga; 12445289Ssklower long xem; 12545289Ssklower long rovr; 12645289Ssklower } dpstat; 12745289Ssklower 12845289Ssklower short dp_ilb = 0; 12945289Ssklower short dp_log = 1; 13045289Ssklower 13145289Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 13245289Ssklower int dp_sizes[] = { 13345289Ssklower sizeof(dp_softc[0]), sizeof(struct ifnet), 13445289Ssklower _offsetof(struct dp_softc, dp_obuf[0]), 13545289Ssklower _offsetof(struct dp_softc, dp_ibuf[0]), 13645289Ssklower }; 13745289Ssklower 13845163Ssklower dpprobe(reg, ui) 13945163Ssklower caddr_t reg; 14045163Ssklower struct uba_device *ui; 14145163Ssklower { 14245163Ssklower register int br, cvec; 14345163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg; 14445236Ssklower register int unit = ui->ui_unit; 14545163Ssklower 14645163Ssklower #ifdef lint 14745163Ssklower br = 0; cvec = br; br = cvec; 14845163Ssklower dprint(0); dpxint(0); 14945163Ssklower #endif 15045228Ssklower (void) spl6(); 15145163Ssklower addr->dpclr = DP_CLR; 15245163Ssklower addr->dpclr = DP_XIE|DP_XE; 15345163Ssklower DELAY(100000); 15445236Ssklower dp_softc[unit].dp_ipl = br = qbgetpri(); 15545236Ssklower dp_softc[unit].dp_addr = addr; 15645163Ssklower addr->dpclr = 0; 15745228Ssklower if (cvec && cvec != 0x200){ 15845228Ssklower cvec -= 4; 15945228Ssklower } 16045163Ssklower return (1); 16145163Ssklower } 16245163Ssklower 16345163Ssklower /* 16445163Ssklower * Interface exists: make available by filling in network interface 16545163Ssklower * record. System will initialize the interface when it is ready 16645163Ssklower * to accept packets. 16745163Ssklower */ 16845163Ssklower dpattach(ui) 16945163Ssklower register struct uba_device *ui; 17045163Ssklower { 17145163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 17245163Ssklower 17345163Ssklower dp->dp_if.if_unit = ui->ui_unit; 17445163Ssklower dp->dp_if.if_name = "dp"; 17545163Ssklower dp->dp_if.if_mtu = DP_MTU; 17645163Ssklower dp->dp_if.if_init = dpinit; 17745163Ssklower dp->dp_if.if_output = x25_ifoutput; 17845163Ssklower dp->dp_if.if_start = dpstart; 17945163Ssklower dp->dp_if.if_ioctl = dpioctl; 18045163Ssklower dp->dp_if.if_reset = dpreset; 18145163Ssklower dp->dp_if.if_watchdog = dptimeout; 18245228Ssklower dp->dp_if.if_flags = 0; 18345163Ssklower if_attach(&dp->dp_if); 18445163Ssklower } 18545163Ssklower 18645163Ssklower /* 18745163Ssklower * Reset of interface after UNIBUS reset. 18845163Ssklower * If interface is on specified UBA, reset its state. 18945163Ssklower */ 19045163Ssklower dpreset(unit, uban) 19145163Ssklower int unit, uban; 19245163Ssklower { 19345163Ssklower register struct uba_device *ui; 19445163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 19545163Ssklower register struct dpdevice *addr; 19645163Ssklower 19745228Ssklower dpstat.reset++; 19845163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 19945163Ssklower ui->ui_ubanum != uban) 20045163Ssklower return; 20145236Ssklower dpdown(unit); 20245236Ssklower dpinit(unit); 20345163Ssklower printf(" dp%d", unit); 20445163Ssklower } 20545163Ssklower 20645163Ssklower /* 20745163Ssklower * Initialization of interface. 20845163Ssklower */ 20945163Ssklower dpinit(unit) 21045163Ssklower int unit; 21145163Ssklower { 21245163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 21345163Ssklower register struct dpdevice *addr; 21445228Ssklower register struct ifaddr *ifa; 21545228Ssklower register struct pdma *pdp = &dppdma[unit*2]; 21645228Ssklower int base, s; 21745163Ssklower 21845228Ssklower dpstat.init++; 21945163Ssklower /* 22045163Ssklower * Check to see that an address has been set. 22145163Ssklower */ 22245228Ssklower for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) 22345163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 22445163Ssklower break; 22545163Ssklower if (ifa == (struct ifaddr *) 0) 22645163Ssklower return; 22745163Ssklower 22845236Ssklower addr = dp->dp_addr; 22945228Ssklower s = splimp(); 23045163Ssklower dp->dp_iused = 0; 23145163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE; 23245228Ssklower dp->dp_if.if_flags |= IFF_RUNNING; 23345228Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 23445228Ssklower 23545228Ssklower pdp->p_addr = addr; 23645228Ssklower pdp->p_fcn = dpxint; 23745228Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf; 23845228Ssklower pdp++; 23945228Ssklower pdp->p_addr = addr; 24045228Ssklower pdp->p_fcn = dprint; 24145228Ssklower /* force initial interrupt to come to dprint */ 24245228Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; 24345228Ssklower 24445228Ssklower addr->dpclr = DP_CLR; 24545289Ssklower DELAY(5000); 24645237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 24745237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 24845237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 24945289Ssklower addr->dpclr = DP_XE | dp_ilb; 25045289Ssklower addr->dptdsr = DP_XSM; 25145237Ssklower /* enable receiver, receive interrupt, DTR, RTS */ 25245228Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 25345228Ssklower dpstart(&dp->dp_if); 25445163Ssklower splx(s); 25545163Ssklower } 25645163Ssklower 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 { 26645228Ssklower int s, unit = ifp->if_unit, error = 0, len; 26745163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 26845237Ssklower register struct dpdevice *addr = dp->dp_addr; 26945163Ssklower register struct mbuf *m; 27045163Ssklower register char *cp; 27145163Ssklower char *cplim; 27245163Ssklower 27345163Ssklower /* 27445163Ssklower * If already doing output, go away and depend on transmit 27545163Ssklower * complete or error. 27645163Ssklower */ 27745228Ssklower dpstat.start++; 27845236Ssklower if ((dp->dp_if.if_flags & IFF_OACTIVE) || 27945289Ssklower (dp->dp_if.if_flags & IFF_RUNNING) == 0) 28045228Ssklower goto out; 28145163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m); 28245163Ssklower if (m == 0) 28345228Ssklower goto out; 28445228Ssklower dp->dp_if.if_collisions++; 28545228Ssklower if (m->m_flags & M_PKTHDR) 28645228Ssklower len = m->m_pkthdr.len; 28745228Ssklower else { 28845228Ssklower struct mbuf *m0 = m; 28945228Ssklower for (len = 0; m; m = m->m_next) 29045228Ssklower len += m->m_len; 29145228Ssklower m = m0; 29245228Ssklower dpstat.nohdr++; 29345228Ssklower } 29445289Ssklower if (len < 2) 29545228Ssklower goto out; 29645228Ssklower if (len > DP_MTU) { 29745228Ssklower error = EINVAL; 29845228Ssklower goto out; 29945228Ssklower } 30045289Ssklower dppdma[2*unit].p_mem = cp = dp->dp_obuf; 30145163Ssklower while (m) { 30245163Ssklower struct mbuf *n; 30345163Ssklower bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 30445163Ssklower cp += m->m_len; 30545163Ssklower MFREE(m, n); m = n; 30645163Ssklower } 30745289Ssklower dppdma[2*unit].p_end = cp - 1; 30845163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE; 30945163Ssklower dp->dp_ostate = DPS_ACTIVE; 31045228Ssklower dp->dp_if.if_collisions--; 31145289Ssklower dp->dp_olen = len; 31245289Ssklower if (dp_log) { 31345289Ssklower register u_char *p = (u_char *)dp->dp_obuf; 31445289Ssklower log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n", 31545289Ssklower len, p[0], p[1], p[2], p[3], p[4]); 31645289Ssklower } 31745237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 31845237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 31945289Ssklower addr->dpclr = DP_XIE | DP_XE | dp_ilb; 32045289Ssklower addr->dptdsr = DP_XSM; 32145228Ssklower out: 32245228Ssklower return (error); 32345163Ssklower } 32445163Ssklower /* 32545163Ssklower * Receive done or error interrupt 32645163Ssklower */ 32745163Ssklower dprint(unit, pdma, addr) 32845163Ssklower register struct pdma *pdma; 32945163Ssklower register struct dpdevice *addr; 33045163Ssklower { 33145166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 33245237Ssklower short rdsr = addr->dprdsr, rcsr = pdma->p_arg; 33345163Ssklower 33445228Ssklower dpstat.rint++; 33545228Ssklower splx(dp->dp_ipl); 33645237Ssklower if (rdsr & DP_RGA) { 33745237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 33845237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 33945237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 34045237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 34145237Ssklower dpstat.rga++; 34245237Ssklower return; 34345237Ssklower } 34445166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */ 34545237Ssklower dpstat.rsm++; 34645237Ssklower pdma->p_mem = dp->dp_ibuf; 34745237Ssklower if (rcsr & DP_RDR) { 34845237Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF; 34945237Ssklower pdma->p_mem++; 35045237Ssklower } 35145166Ssklower dp->dp_flags &= ~DPF_FLUSH; 35245163Ssklower return; 35345163Ssklower } 35445166Ssklower if (rdsr & DP_REM) { /* Received End of Message */ 35545237Ssklower dpstat.rem++; 35645289Ssklower if (rcsr & DP_RDR) { 35745289Ssklower *(pdma->p_mem++) = rdsr; 35845289Ssklower dpstat.remchr++; 35945289Ssklower } 36045289Ssklower dp->dp_ilen = pdma->p_mem - dp->dp_ibuf; 36145166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 36245166Ssklower dp->dp_if.if_ierrors++; 36345228Ssklower } else 36445289Ssklower dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf); 36545228Ssklower pdma->p_mem = pdma->p_end; 36645228Ssklower dp->dp_flags &= ~ DPF_FLUSH; 36745228Ssklower return; 36845228Ssklower } 36945228Ssklower if (rdsr & DP_ROVR) { 37045289Ssklower dpstat.rovr++; 37145228Ssklower dp->dp_flags |= DPF_FLUSH; 37245228Ssklower return; 37345228Ssklower } 37445228Ssklower if (rcsr & DP_MSC) { 37545228Ssklower dpstat.mchange++; 37645228Ssklower if (0 == (rcsr & DP_DSR)) { 37745228Ssklower log(LOG_DEBUG, "dp%d: lost modem\n", unit); 37845237Ssklower /*dpdown(unit);*/ 37945163Ssklower } 38045163Ssklower return; 38145163Ssklower } 38245163Ssklower dp->dp_flags |= DPF_FLUSH; 38345163Ssklower if (pdma->p_mem != pdma->p_end) 38445289Ssklower log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit); 38545163Ssklower } 38645163Ssklower /* 38745163Ssklower * Transmit complete or error interrupt 38845163Ssklower */ 38945163Ssklower dpxint(unit, pdma, addr) 39045163Ssklower register struct pdma *pdma; 39145163Ssklower register struct dpdevice *addr; 39245163Ssklower { 39345166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 39445228Ssklower int s; 39545163Ssklower 39645228Ssklower splx(dp->dp_ipl); 39745228Ssklower dpstat.xint++; 39845163Ssklower if (addr->dptdsr & DP_XERR) { 39945289Ssklower log(LOG_DEBUG, "if_dp%d: data late\n", unit); 40045163Ssklower restart: 40145163Ssklower pdma->p_mem = dp->dp_obuf; 40245163Ssklower addr->dptdsr = DP_XSM; 40345228Ssklower dp->dp_if.if_oerrors++; 40445163Ssklower return; 40545163Ssklower } 40645163Ssklower switch (dp->dp_ostate) { 40745163Ssklower 40845163Ssklower case DPS_ACTIVE: 40945163Ssklower if (pdma->p_mem != pdma->p_end) { 41045289Ssklower log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit); 41145163Ssklower goto restart; 41245163Ssklower } 41345289Ssklower addr->dpsar = DP_IDLE|DP_SSLM; 41445289Ssklower addr->dpclr = DP_XE | DP_XIE | dp_ilb; 41545289Ssklower addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]); 41645289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 41745163Ssklower dp->dp_ostate = DPS_XEM; 41845163Ssklower break; 41945163Ssklower 42045163Ssklower case DPS_XEM: 42145289Ssklower dpstat.xem++; 42245228Ssklower dp->dp_if.if_opackets++; 42345289Ssklower dp->dp_ostate = DPS_IDLE; 42445163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 42545163Ssklower if (dp->dp_if.if_snd.ifq_len) 42645163Ssklower dpstart(&dp->dp_if); 42745163Ssklower else { 42845289Ssklower addr->dpsar = DP_IDLE|DP_SSLM; 42945289Ssklower addr->dpclr = DP_XE | dp_ilb; 43045289Ssklower addr->dptdsr = DP_XSM; 43145289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS; 43245163Ssklower } 43345163Ssklower break; 43445163Ssklower 43545163Ssklower default: 43645289Ssklower log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n"); 43745163Ssklower } 43845163Ssklower } 43945163Ssklower /* 44045163Ssklower * Routine to copy from device buffer into mbufs. 44145163Ssklower * 44245163Ssklower * Warning: This makes the fairly safe assumption that 44345163Ssklower * mbufs have even lengths. 44445163Ssklower */ 44545163Ssklower struct mbuf * 44645163Ssklower dpget(rxbuf, totlen, off, ifp) 44745163Ssklower caddr_t rxbuf; 44845163Ssklower int totlen, off; 44945163Ssklower struct ifnet *ifp; 45045163Ssklower { 45145163Ssklower register caddr_t cp; 45245163Ssklower register struct mbuf *m; 45345163Ssklower struct mbuf *top = 0, **mp = ⊤ 45445163Ssklower int len; 45545163Ssklower caddr_t packet_end; 45645163Ssklower 45745163Ssklower cp = rxbuf; 45845163Ssklower packet_end = cp + totlen; 45945163Ssklower if (off) { 46045163Ssklower off += 2 * sizeof(u_short); 46145163Ssklower totlen -= 2 *sizeof(u_short); 46245163Ssklower cp = rxbuf + off; 46345163Ssklower } 46445163Ssklower 46545163Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 46645163Ssklower if (m == 0) 46745163Ssklower return (0); 46845163Ssklower m->m_pkthdr.rcvif = ifp; 46945163Ssklower m->m_pkthdr.len = totlen; 47045163Ssklower m->m_len = MHLEN; 47145163Ssklower 47245163Ssklower while (totlen > 0) { 47345163Ssklower if (top) { 47445163Ssklower MGET(m, M_DONTWAIT, MT_DATA); 47545163Ssklower if (m == 0) { 47645163Ssklower m_freem(top); 47745163Ssklower return (0); 47845163Ssklower } 47945163Ssklower m->m_len = MLEN; 48045163Ssklower } 48145163Ssklower len = min(totlen, (packet_end - cp)); 48245163Ssklower if (len >= MINCLSIZE) { 48345163Ssklower MCLGET(m, M_DONTWAIT); 48445163Ssklower if (m->m_flags & M_EXT) 48545163Ssklower m->m_len = len = min(len, MCLBYTES); 48645163Ssklower else 48745163Ssklower len = m->m_len; 48845163Ssklower } else { 48945163Ssklower /* 49045163Ssklower * Place initial small packet/header at end of mbuf. 49145163Ssklower */ 49245163Ssklower if (len < m->m_len) { 49345163Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 49445163Ssklower m->m_data += max_linkhdr; 49545163Ssklower m->m_len = len; 49645163Ssklower } else 49745163Ssklower len = m->m_len; 49845163Ssklower } 49945163Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 50045163Ssklower *mp = m; 50145163Ssklower mp = &m->m_next; 50245163Ssklower totlen -= len; 50345163Ssklower cp += len; 50445163Ssklower if (cp == packet_end) 50545163Ssklower cp = rxbuf; 50645163Ssklower } 50745163Ssklower return (top); 50845163Ssklower } 50945163Ssklower 51045228Ssklower dpinput(ifp, len, buffer) 51145228Ssklower register struct ifnet *ifp; 51245163Ssklower caddr_t buffer; 51345163Ssklower { 51445163Ssklower register struct ifqueue *inq; 51545163Ssklower register struct mbuf *m; 51645228Ssklower extern struct ifqueue hdintrq, ipintrq; 51745289Ssklower int isr; 51845163Ssklower 51945228Ssklower ifp->if_ipackets++; 52045289Ssklower if (dp_log) { 52145289Ssklower register u_char *p = (u_char *)buffer; 52245289Ssklower log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n", 52345289Ssklower len, p[0], p[1], p[2], p[3], p[4]); 52445289Ssklower } 52545289Ssklower 52645228Ssklower { 52745228Ssklower register struct ifaddr *ifa = ifp->if_addrlist; 52845228Ssklower register u_char *cp = (u_char *)buffer; 52945228Ssklower 53045228Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 53145228Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 53245228Ssklower break; 53345228Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 53445228Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 53545228Ssklower protocol. for now, IP only. */ 53645228Ssklower buffer += 4; 53745228Ssklower len -= 4; 53845228Ssklower inq = &ipintrq; 53945289Ssklower isr = NETISR_IP; 54045228Ssklower } else { 54145228Ssklower inq = &hdintrq; 54245289Ssklower isr = NETISR_CCITT; 54345228Ssklower } 54445228Ssklower } 54545228Ssklower if (len <= 0) 54645163Ssklower return; 54745163Ssklower 54845163Ssklower m = dpget(buffer, len , 0, ifp); 54945163Ssklower if (m == 0) 55045163Ssklower return; 55145163Ssklower 55245163Ssklower if(IF_QFULL(inq)) { 55345163Ssklower IF_DROP(inq); 55445163Ssklower m_freem(m); 55545163Ssklower } else { 55645163Ssklower IF_ENQUEUE(inq, m); 55745289Ssklower schednetisr(isr); 55845163Ssklower } 55945163Ssklower } 56045163Ssklower 56145163Ssklower /* 56245163Ssklower * Process an ioctl request. 56345163Ssklower */ 56445163Ssklower dpioctl(ifp, cmd, data) 56545163Ssklower register struct ifnet *ifp; 56645163Ssklower int cmd; 56745163Ssklower caddr_t data; 56845163Ssklower { 56945163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 57045163Ssklower int s = splimp(), error = 0; 57145166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit]; 57245163Ssklower 57345228Ssklower dpstat.ioctl++; 57445163Ssklower switch (cmd) { 57545163Ssklower 57645163Ssklower case SIOCSIFADDR: 57745163Ssklower ifp->if_flags |= IFF_UP; 57845163Ssklower switch (ifa->ifa_addr->sa_family) { 57945228Ssklower case AF_INET: 58045228Ssklower ifp->if_output = dptestoutput; 58145163Ssklower default: 58245163Ssklower dpinit(ifp->if_unit); 58345163Ssklower break; 58445163Ssklower } 58545163Ssklower break; 58645228Ssklower #ifdef CCITT 58745228Ssklower case SIOCSIFCONF_X25: 58845228Ssklower ifp->if_flags |= IFF_UP; 58945228Ssklower ifp->if_output = x25_ifoutput; 59045228Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 59145228Ssklower if (error == 0) 59245228Ssklower dpinit(ifp->if_unit); 59345228Ssklower break; 59445228Ssklower #endif 59545163Ssklower 59645228Ssklower case SIOCSIFFLAGS: 59745228Ssklower if ((ifp->if_flags & IFF_UP) == 0 && 59845228Ssklower (ifp->if_flags & IFF_RUNNING)) 59945228Ssklower dpdown(ifp->if_unit); 60045228Ssklower else if (ifp->if_flags & IFF_UP && 60145228Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 60245228Ssklower dpinit(ifp->if_unit); 60345228Ssklower break; 60445163Ssklower 60545228Ssklower 60645163Ssklower default: 60745163Ssklower error = EINVAL; 60845163Ssklower } 60945163Ssklower splx(s); 61045163Ssklower return (error); 61145163Ssklower } 61245163Ssklower /* 61345163Ssklower * Reset a device and mark down. 61445163Ssklower * Flush output queue and drop queue limit. 61545163Ssklower */ 61645163Ssklower dpdown(unit) 61745236Ssklower int unit; 61845163Ssklower { 61945236Ssklower 62045163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 62145236Ssklower register struct dpdevice *addr = dp->dp_addr; 62245163Ssklower 62345228Ssklower dpstat.down++; 62445163Ssklower if_qflush(&dp->dp_if.if_snd); 62545236Ssklower dp->dp_flags = 0; 62645236Ssklower dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 62745236Ssklower 62845236Ssklower addr->dpclr = DP_CLR; 62945236Ssklower DELAY(1000); 63045236Ssklower addr->dpsar = 0; 63145236Ssklower addr->dprcsr = 0; 63245163Ssklower } 63345163Ssklower 63445163Ssklower /* 63545163Ssklower * Watchdog timeout to see that transmitted packets don't 63645163Ssklower * lose interrupts. The device has to be online (the first 63745163Ssklower * transmission may block until the other side comes up). 63845163Ssklower */ 63945163Ssklower dptimeout(unit) 64045163Ssklower int unit; 64145163Ssklower { 64245163Ssklower register struct dp_softc *dp; 64345163Ssklower 64445228Ssklower /* currently not armed */ 64545228Ssklower dpstat.timeout++; 64645163Ssklower dp = &dp_softc[unit]; 64745228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) { 64845228Ssklower dpstart(&dp->dp_if); 64945163Ssklower } 65045163Ssklower } 65145228Ssklower /* 65245228Ssklower * For debugging loopback activity. 65345228Ssklower */ 65445228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 65545228Ssklower int dp_louts; 65645228Ssklower 65745228Ssklower dptestoutput(ifp, m, dst, rt) 65845228Ssklower register struct ifnet *ifp; 65945228Ssklower register struct mbuf *m; 66045228Ssklower struct sockaddr *dst; 66145228Ssklower struct rtentry *rt; 66245228Ssklower { 66345228Ssklower /* 66445228Ssklower * Queue message on interface, and start output if interface 66545228Ssklower * not yet active. 66645228Ssklower */ 66745228Ssklower int s = splimp(), error = 0; 66845228Ssklower dp_louts++; 66945228Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 67045228Ssklower if (m == 0) { 67145228Ssklower splx(s); 67245228Ssklower return ENOBUFS; 67345228Ssklower } 67445228Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 67545228Ssklower if (IF_QFULL(&ifp->if_snd)) { 67645228Ssklower IF_DROP(&ifp->if_snd); 67745228Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 67845228Ssklower ifp->if_name, ifp->if_unit);*/ 67945228Ssklower m_freem(m); 68045228Ssklower error = ENOBUFS; 68145228Ssklower } else { 68245228Ssklower IF_ENQUEUE(&ifp->if_snd, m); 68345228Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 68445228Ssklower (*ifp->if_start)(ifp); 68545228Ssklower } 68645228Ssklower splx(s); 68745228Ssklower return (error); 68845228Ssklower } 68945228Ssklower 69045163Ssklower #endif 691