145163Ssklower /* 245163Ssklower * Copyright (c) 1990 Regents of the University of California. 345163Ssklower * All rights reserved. 445163Ssklower * 545163Ssklower * %sccs.include.redist.c% 645163Ssklower * 7*48964Ssklower * @(#)if_dp.c 7.8 (Berkeley) 05/02/91 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 2745801Sbostic #include "../include/pte.h" 2845163Ssklower 2945801Sbostic #include "sys/param.h" 3045801Sbostic #include "sys/systm.h" 3145801Sbostic #include "sys/mbuf.h" 3245801Sbostic #include "sys/buf.h" 3345801Sbostic #include "sys/ioctl.h" /* must precede tty.h */ 3445801Sbostic #include "sys/protosw.h" 3545801Sbostic #include "sys/socket.h" 3645801Sbostic #include "sys/socketvar.h" 3745801Sbostic #include "sys/syslog.h" 3845801Sbostic #include "sys/vmmac.h" 3945801Sbostic #include "sys/errno.h" 4045801Sbostic #include "sys/time.h" 4145801Sbostic #include "sys/kernel.h" 4245163Ssklower 4345801Sbostic #include "net/if.h" 44*48964Ssklower #include "net/if_types.h" 4545801Sbostic #include "net/netisr.h" 4645801Sbostic #include "net/route.h" 4745163Ssklower 4845801Sbostic #include "../include/cpu.h" 4945801Sbostic #include "../include/mtpr.h" 5045166Ssklower 5145228Ssklower #define dzdevice dpdevice 5245801Sbostic #include "../uba/pdma.h" 5345801Sbostic #include "../uba/ubavar.h" 5445163Ssklower 5545801Sbostic #include "netccitt/x25.h" 5645801Sbostic #include "netccitt/pk.h" 5745801Sbostic #include "netccitt/pk_var.h" 5845166Ssklower 5945163Ssklower #include "if_dpreg.h" 6045163Ssklower 6145163Ssklower /* 6245163Ssklower * Driver information for auto-configuration stuff. 6345163Ssklower */ 6445163Ssklower int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint(); 6545228Ssklower int dpoutput(), dpreset(), dptimeout(), dpstart(), x25_ifoutput(), dptestoutput(); 6645163Ssklower 6745163Ssklower struct uba_device *dpinfo[NDP]; 6845163Ssklower 6945163Ssklower u_short dpstd[] = { 0 }; 7045163Ssklower struct uba_driver dpdriver = 7145163Ssklower { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo }; 7245163Ssklower 7345163Ssklower /* 7445163Ssklower * Pdma structures for fast interrupts. 7545163Ssklower */ 7645163Ssklower struct pdma dppdma[2*NDP]; 7745163Ssklower 7845163Ssklower /* 7945163Ssklower * DP software status per interface. 8045163Ssklower * 8145163Ssklower * Each interface is referenced by a network interface structure, 8245163Ssklower * dp_if, which the routing code uses to locate the interface. 8345163Ssklower * This structure contains the output queue for the interface, its address, ... 8445163Ssklower */ 8545163Ssklower struct dp_softc { 8645163Ssklower struct ifnet dp_if; /* network-visible interface */ 8745228Ssklower int dp_ipl; 8845236Ssklower struct dpdevice *dp_addr; /* dpcsr address */ 8945163Ssklower short dp_iused; /* input buffers given to DP */ 9045163Ssklower short dp_flags; /* flags */ 9145228Ssklower #define DPF_RUNNING 0x01 /* device initialized */ 9245228Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 9345228Ssklower #define DPF_RESTART 0x04 /* software restart in progress */ 9445228Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 9545163Ssklower short dp_ostate; /* restarting, etc. */ 9645163Ssklower short dp_istate; /* not sure this is necessary */ 9745163Ssklower #define DPS_IDLE 0 9845163Ssklower #define DPS_RESTART 1 9945163Ssklower #define DPS_ACTIVE 2 10045163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */ 10145289Ssklower short dp_olen; /* length of last packet sent */ 10245289Ssklower short dp_ilen; /* length of last packet recvd */ 10345163Ssklower char dp_obuf[DP_MTU+8]; 10445166Ssklower char dp_ibuf[DP_MTU+8]; 10545163Ssklower } dp_softc[NDP]; 10645163Ssklower 10745289Ssklower /* 10845289Ssklower * Debug info 10945289Ssklower */ 11045289Ssklower struct dpstat { 11145289Ssklower long start; 11245289Ssklower long nohdr; 11345289Ssklower long init; 11445289Ssklower long rint; 11545289Ssklower long xint; 11645289Ssklower long reset; 11745289Ssklower long ioctl; 11845289Ssklower long down; 11945289Ssklower long mchange; 12045289Ssklower long timeout; 12145289Ssklower long rsm; 12245289Ssklower long rem; 12345289Ssklower long remchr; 12445289Ssklower long rga; 12545289Ssklower long xem; 12645289Ssklower long rovr; 12745289Ssklower } dpstat; 12845289Ssklower 12945289Ssklower short dp_ilb = 0; 130*48964Ssklower short dp_log = 0; 13145289Ssklower 13245289Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 13345289Ssklower int dp_sizes[] = { 13445289Ssklower sizeof(dp_softc[0]), sizeof(struct ifnet), 13545289Ssklower _offsetof(struct dp_softc, dp_obuf[0]), 13645289Ssklower _offsetof(struct dp_softc, dp_ibuf[0]), 13745289Ssklower }; 13845289Ssklower 13945163Ssklower dpprobe(reg, ui) 14045163Ssklower caddr_t reg; 14145163Ssklower struct uba_device *ui; 14245163Ssklower { 14345163Ssklower register int br, cvec; 14445163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg; 14545236Ssklower register int unit = ui->ui_unit; 14645163Ssklower 14745163Ssklower #ifdef lint 14845163Ssklower br = 0; cvec = br; br = cvec; 14945163Ssklower dprint(0); dpxint(0); 15045163Ssklower #endif 15145228Ssklower (void) spl6(); 15245163Ssklower addr->dpclr = DP_CLR; 15345163Ssklower addr->dpclr = DP_XIE|DP_XE; 15445163Ssklower DELAY(100000); 15545236Ssklower dp_softc[unit].dp_ipl = br = qbgetpri(); 15645236Ssklower dp_softc[unit].dp_addr = addr; 15745163Ssklower addr->dpclr = 0; 15845228Ssklower if (cvec && cvec != 0x200){ 15945228Ssklower cvec -= 4; 16045228Ssklower } 16145163Ssklower return (1); 16245163Ssklower } 16345163Ssklower 16445163Ssklower /* 16545163Ssklower * Interface exists: make available by filling in network interface 16645163Ssklower * record. System will initialize the interface when it is ready 16745163Ssklower * to accept packets. 16845163Ssklower */ 16945163Ssklower dpattach(ui) 17045163Ssklower register struct uba_device *ui; 17145163Ssklower { 17245163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 17345163Ssklower 17445163Ssklower dp->dp_if.if_unit = ui->ui_unit; 17545163Ssklower dp->dp_if.if_name = "dp"; 17645163Ssklower dp->dp_if.if_mtu = DP_MTU; 17745163Ssklower dp->dp_if.if_init = dpinit; 17845163Ssklower dp->dp_if.if_output = x25_ifoutput; 179*48964Ssklower dp->dp_if.if_type = IFT_X25; 180*48964Ssklower dp->dp_if.if_hdrlen = 5; 181*48964Ssklower dp->dp_if.if_addrlen = 8; 18245163Ssklower dp->dp_if.if_start = dpstart; 18345163Ssklower dp->dp_if.if_ioctl = dpioctl; 18445163Ssklower dp->dp_if.if_reset = dpreset; 18545163Ssklower dp->dp_if.if_watchdog = dptimeout; 18645228Ssklower dp->dp_if.if_flags = 0; 18745163Ssklower if_attach(&dp->dp_if); 18845163Ssklower } 18945163Ssklower 19045163Ssklower /* 19145163Ssklower * Reset of interface after UNIBUS reset. 19245163Ssklower * If interface is on specified UBA, reset its state. 19345163Ssklower */ 19445163Ssklower dpreset(unit, uban) 19545163Ssklower int unit, uban; 19645163Ssklower { 19745163Ssklower register struct uba_device *ui; 19845163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 19945163Ssklower register struct dpdevice *addr; 20045163Ssklower 20145228Ssklower dpstat.reset++; 20245163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 20345163Ssklower ui->ui_ubanum != uban) 20445163Ssklower return; 20545236Ssklower dpdown(unit); 20645236Ssklower dpinit(unit); 20745163Ssklower printf(" dp%d", unit); 20845163Ssklower } 20945163Ssklower 21045163Ssklower /* 21145163Ssklower * Initialization of interface. 21245163Ssklower */ 21345163Ssklower dpinit(unit) 21445163Ssklower int unit; 21545163Ssklower { 21645163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 21745163Ssklower register struct dpdevice *addr; 21845228Ssklower register struct ifaddr *ifa; 21945228Ssklower register struct pdma *pdp = &dppdma[unit*2]; 22045228Ssklower int base, s; 22145163Ssklower 22245228Ssklower dpstat.init++; 22345163Ssklower /* 22445163Ssklower * Check to see that an address has been set. 22545163Ssklower */ 22645228Ssklower for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) 22745163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 22845163Ssklower break; 22945163Ssklower if (ifa == (struct ifaddr *) 0) 23045163Ssklower return; 23145163Ssklower 23245236Ssklower addr = dp->dp_addr; 23345228Ssklower s = splimp(); 23445163Ssklower dp->dp_iused = 0; 23545163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE; 23645228Ssklower dp->dp_if.if_flags |= IFF_RUNNING; 23745228Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 23845228Ssklower 23945228Ssklower pdp->p_addr = addr; 24045228Ssklower pdp->p_fcn = dpxint; 24145228Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf; 24245228Ssklower pdp++; 24345228Ssklower pdp->p_addr = addr; 24445228Ssklower pdp->p_fcn = dprint; 24545228Ssklower /* force initial interrupt to come to dprint */ 24645228Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; 24745228Ssklower 24845228Ssklower addr->dpclr = DP_CLR; 24945289Ssklower DELAY(5000); 25045237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 25145237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 25245237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 25345289Ssklower addr->dpclr = DP_XE | dp_ilb; 25445289Ssklower addr->dptdsr = DP_XSM; 25545237Ssklower /* enable receiver, receive interrupt, DTR, RTS */ 25645228Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 25745228Ssklower dpstart(&dp->dp_if); 25845163Ssklower splx(s); 25945163Ssklower } 26045163Ssklower 26145163Ssklower /* 26245163Ssklower * Start output on interface. Get another datagram 26345163Ssklower * to send from the interface queue and map it to 26445163Ssklower * the interface before starting output. 26545163Ssklower * 26645163Ssklower */ 26745163Ssklower dpstart(ifp) 26845163Ssklower struct ifnet *ifp; 26945163Ssklower { 27045228Ssklower int s, unit = ifp->if_unit, error = 0, len; 27145163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 27245237Ssklower register struct dpdevice *addr = dp->dp_addr; 27345163Ssklower register struct mbuf *m; 27445163Ssklower register char *cp; 27545163Ssklower char *cplim; 27645163Ssklower 27745163Ssklower /* 27845163Ssklower * If already doing output, go away and depend on transmit 27945163Ssklower * complete or error. 28045163Ssklower */ 28145228Ssklower dpstat.start++; 28245236Ssklower if ((dp->dp_if.if_flags & IFF_OACTIVE) || 28345289Ssklower (dp->dp_if.if_flags & IFF_RUNNING) == 0) 28445228Ssklower goto out; 28545163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m); 28645163Ssklower if (m == 0) 28745228Ssklower goto out; 28845228Ssklower dp->dp_if.if_collisions++; 28945228Ssklower if (m->m_flags & M_PKTHDR) 29045228Ssklower len = m->m_pkthdr.len; 29145228Ssklower else { 29245228Ssklower struct mbuf *m0 = m; 29345228Ssklower for (len = 0; m; m = m->m_next) 29445228Ssklower len += m->m_len; 29545228Ssklower m = m0; 29645228Ssklower dpstat.nohdr++; 29745228Ssklower } 29845289Ssklower if (len < 2) 29945228Ssklower goto out; 30045228Ssklower if (len > DP_MTU) { 30145228Ssklower error = EINVAL; 30245228Ssklower goto out; 30345228Ssklower } 30445289Ssklower dppdma[2*unit].p_mem = cp = dp->dp_obuf; 30545163Ssklower while (m) { 30645163Ssklower struct mbuf *n; 30745163Ssklower bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 30845163Ssklower cp += m->m_len; 30945163Ssklower MFREE(m, n); m = n; 31045163Ssklower } 31145289Ssklower dppdma[2*unit].p_end = cp - 1; 31245163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE; 31345163Ssklower dp->dp_ostate = DPS_ACTIVE; 31445228Ssklower dp->dp_if.if_collisions--; 31545289Ssklower dp->dp_olen = len; 31645289Ssklower if (dp_log) { 31745289Ssklower register u_char *p = (u_char *)dp->dp_obuf; 31845289Ssklower log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n", 31945289Ssklower len, p[0], p[1], p[2], p[3], p[4]); 32045289Ssklower } 32145237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 32245237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 32345289Ssklower addr->dpclr = DP_XIE | DP_XE | dp_ilb; 32445289Ssklower addr->dptdsr = DP_XSM; 32545228Ssklower out: 32645228Ssklower return (error); 32745163Ssklower } 32845163Ssklower /* 32945163Ssklower * Receive done or error interrupt 33045163Ssklower */ 33145163Ssklower dprint(unit, pdma, addr) 33245163Ssklower register struct pdma *pdma; 33345163Ssklower register struct dpdevice *addr; 33445163Ssklower { 33545166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 33645237Ssklower short rdsr = addr->dprdsr, rcsr = pdma->p_arg; 33745163Ssklower 33845228Ssklower dpstat.rint++; 33945228Ssklower splx(dp->dp_ipl); 34045237Ssklower if (rdsr & DP_RGA) { 34145237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 34245237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 34345237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 34445237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 34545237Ssklower dpstat.rga++; 34645237Ssklower return; 34745237Ssklower } 34845166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */ 34945237Ssklower dpstat.rsm++; 35045237Ssklower pdma->p_mem = dp->dp_ibuf; 35145237Ssklower if (rcsr & DP_RDR) { 35245237Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF; 35345237Ssklower pdma->p_mem++; 35445237Ssklower } 35545166Ssklower dp->dp_flags &= ~DPF_FLUSH; 35645163Ssklower return; 35745163Ssklower } 35845166Ssklower if (rdsr & DP_REM) { /* Received End of Message */ 35945237Ssklower dpstat.rem++; 36045289Ssklower if (rcsr & DP_RDR) { 36145289Ssklower *(pdma->p_mem++) = rdsr; 36245289Ssklower dpstat.remchr++; 36345289Ssklower } 36445289Ssklower dp->dp_ilen = pdma->p_mem - dp->dp_ibuf; 36545166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 36645166Ssklower dp->dp_if.if_ierrors++; 36745228Ssklower } else 36845289Ssklower dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf); 36945228Ssklower pdma->p_mem = pdma->p_end; 37045228Ssklower dp->dp_flags &= ~ DPF_FLUSH; 37145228Ssklower return; 37245228Ssklower } 37345228Ssklower if (rdsr & DP_ROVR) { 37445289Ssklower dpstat.rovr++; 37545228Ssklower dp->dp_flags |= DPF_FLUSH; 37645228Ssklower return; 37745228Ssklower } 37845228Ssklower if (rcsr & DP_MSC) { 37945228Ssklower dpstat.mchange++; 38045228Ssklower if (0 == (rcsr & DP_DSR)) { 38145228Ssklower log(LOG_DEBUG, "dp%d: lost modem\n", unit); 38245237Ssklower /*dpdown(unit);*/ 38345163Ssklower } 38445163Ssklower return; 38545163Ssklower } 38645163Ssklower dp->dp_flags |= DPF_FLUSH; 38745163Ssklower if (pdma->p_mem != pdma->p_end) 38845289Ssklower log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit); 38945163Ssklower } 39045163Ssklower /* 39145163Ssklower * Transmit complete or error interrupt 39245163Ssklower */ 39345163Ssklower dpxint(unit, pdma, addr) 39445163Ssklower register struct pdma *pdma; 39545163Ssklower register struct dpdevice *addr; 39645163Ssklower { 39745166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 39845228Ssklower int s; 39945163Ssklower 40045228Ssklower splx(dp->dp_ipl); 40145228Ssklower dpstat.xint++; 40245163Ssklower if (addr->dptdsr & DP_XERR) { 40345289Ssklower log(LOG_DEBUG, "if_dp%d: data late\n", unit); 40445163Ssklower restart: 40545163Ssklower pdma->p_mem = dp->dp_obuf; 40645163Ssklower addr->dptdsr = DP_XSM; 40745228Ssklower dp->dp_if.if_oerrors++; 40845163Ssklower return; 40945163Ssklower } 41045163Ssklower switch (dp->dp_ostate) { 41145163Ssklower 41245163Ssklower case DPS_ACTIVE: 41345163Ssklower if (pdma->p_mem != pdma->p_end) { 41445289Ssklower log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit); 41545163Ssklower goto restart; 41645163Ssklower } 41745289Ssklower addr->dpsar = DP_IDLE|DP_SSLM; 41845289Ssklower addr->dpclr = DP_XE | DP_XIE | dp_ilb; 41945289Ssklower addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]); 42045289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 42145163Ssklower dp->dp_ostate = DPS_XEM; 42245163Ssklower break; 42345163Ssklower 42445163Ssklower case DPS_XEM: 42545289Ssklower dpstat.xem++; 42645228Ssklower dp->dp_if.if_opackets++; 42745289Ssklower dp->dp_ostate = DPS_IDLE; 42845163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 42945163Ssklower if (dp->dp_if.if_snd.ifq_len) 43045163Ssklower dpstart(&dp->dp_if); 43145163Ssklower else { 43245289Ssklower addr->dpsar = DP_IDLE|DP_SSLM; 43345289Ssklower addr->dpclr = DP_XE | dp_ilb; 43445289Ssklower addr->dptdsr = DP_XSM; 43545289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS; 43645163Ssklower } 43745163Ssklower break; 43845163Ssklower 43945163Ssklower default: 44045289Ssklower log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n"); 44145163Ssklower } 44245163Ssklower } 44345163Ssklower /* 44445163Ssklower * Routine to copy from device buffer into mbufs. 44545163Ssklower * 44645163Ssklower * Warning: This makes the fairly safe assumption that 44745163Ssklower * mbufs have even lengths. 44845163Ssklower */ 44945163Ssklower struct mbuf * 45045163Ssklower dpget(rxbuf, totlen, off, ifp) 45145163Ssklower caddr_t rxbuf; 45245163Ssklower int totlen, off; 45345163Ssklower struct ifnet *ifp; 45445163Ssklower { 45545163Ssklower register caddr_t cp; 45645163Ssklower register struct mbuf *m; 45745163Ssklower struct mbuf *top = 0, **mp = ⊤ 45845163Ssklower int len; 45945163Ssklower caddr_t packet_end; 46045163Ssklower 46145163Ssklower cp = rxbuf; 46245163Ssklower packet_end = cp + totlen; 46345163Ssklower if (off) { 46445163Ssklower off += 2 * sizeof(u_short); 46545163Ssklower totlen -= 2 *sizeof(u_short); 46645163Ssklower cp = rxbuf + off; 46745163Ssklower } 46845163Ssklower 46945163Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 47045163Ssklower if (m == 0) 47145163Ssklower return (0); 47245163Ssklower m->m_pkthdr.rcvif = ifp; 47345163Ssklower m->m_pkthdr.len = totlen; 47445163Ssklower m->m_len = MHLEN; 47545163Ssklower 47645163Ssklower while (totlen > 0) { 47745163Ssklower if (top) { 47845163Ssklower MGET(m, M_DONTWAIT, MT_DATA); 47945163Ssklower if (m == 0) { 48045163Ssklower m_freem(top); 48145163Ssklower return (0); 48245163Ssklower } 48345163Ssklower m->m_len = MLEN; 48445163Ssklower } 48545163Ssklower len = min(totlen, (packet_end - cp)); 48645163Ssklower if (len >= MINCLSIZE) { 48745163Ssklower MCLGET(m, M_DONTWAIT); 48845163Ssklower if (m->m_flags & M_EXT) 48945163Ssklower m->m_len = len = min(len, MCLBYTES); 49045163Ssklower else 49145163Ssklower len = m->m_len; 49245163Ssklower } else { 49345163Ssklower /* 49445163Ssklower * Place initial small packet/header at end of mbuf. 49545163Ssklower */ 49645163Ssklower if (len < m->m_len) { 49745163Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 49845163Ssklower m->m_data += max_linkhdr; 49945163Ssklower m->m_len = len; 50045163Ssklower } else 50145163Ssklower len = m->m_len; 50245163Ssklower } 50345163Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 50445163Ssklower *mp = m; 50545163Ssklower mp = &m->m_next; 50645163Ssklower totlen -= len; 50745163Ssklower cp += len; 50845163Ssklower if (cp == packet_end) 50945163Ssklower cp = rxbuf; 51045163Ssklower } 51145163Ssklower return (top); 51245163Ssklower } 51345163Ssklower 51445228Ssklower dpinput(ifp, len, buffer) 51545228Ssklower register struct ifnet *ifp; 51645163Ssklower caddr_t buffer; 51745163Ssklower { 51845163Ssklower register struct ifqueue *inq; 51945163Ssklower register struct mbuf *m; 52045228Ssklower extern struct ifqueue hdintrq, ipintrq; 52145289Ssklower int isr; 52245163Ssklower 52345228Ssklower ifp->if_ipackets++; 52445289Ssklower if (dp_log) { 52545289Ssklower register u_char *p = (u_char *)buffer; 52645289Ssklower log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n", 52745289Ssklower len, p[0], p[1], p[2], p[3], p[4]); 52845289Ssklower } 52945289Ssklower 53045228Ssklower { 53145228Ssklower register struct ifaddr *ifa = ifp->if_addrlist; 53245228Ssklower register u_char *cp = (u_char *)buffer; 53345228Ssklower 53445228Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 53545228Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 53645228Ssklower break; 53745228Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 53845228Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 53945228Ssklower protocol. for now, IP only. */ 54045228Ssklower buffer += 4; 54145228Ssklower len -= 4; 54245228Ssklower inq = &ipintrq; 54345289Ssklower isr = NETISR_IP; 54445228Ssklower } else { 54545228Ssklower inq = &hdintrq; 54645289Ssklower isr = NETISR_CCITT; 54745228Ssklower } 54845228Ssklower } 54945228Ssklower if (len <= 0) 55045163Ssklower return; 55145163Ssklower 55245163Ssklower m = dpget(buffer, len , 0, ifp); 55345163Ssklower if (m == 0) 55445163Ssklower return; 55545163Ssklower 55645163Ssklower if(IF_QFULL(inq)) { 55745163Ssklower IF_DROP(inq); 55845163Ssklower m_freem(m); 55945163Ssklower } else { 56045163Ssklower IF_ENQUEUE(inq, m); 56145289Ssklower schednetisr(isr); 56245163Ssklower } 56345163Ssklower } 56445163Ssklower 56545163Ssklower /* 56645163Ssklower * Process an ioctl request. 56745163Ssklower */ 56845163Ssklower dpioctl(ifp, cmd, data) 56945163Ssklower register struct ifnet *ifp; 57045163Ssklower int cmd; 57145163Ssklower caddr_t data; 57245163Ssklower { 57345163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 57445163Ssklower int s = splimp(), error = 0; 57545166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit]; 57645163Ssklower 57745228Ssklower dpstat.ioctl++; 57845163Ssklower switch (cmd) { 57945163Ssklower 58045163Ssklower case SIOCSIFADDR: 58145163Ssklower ifp->if_flags |= IFF_UP; 58245163Ssklower switch (ifa->ifa_addr->sa_family) { 58345228Ssklower case AF_INET: 58445228Ssklower ifp->if_output = dptestoutput; 58545163Ssklower default: 58645163Ssklower dpinit(ifp->if_unit); 58745163Ssklower break; 58845163Ssklower } 58945163Ssklower break; 59045228Ssklower #ifdef CCITT 59145228Ssklower case SIOCSIFCONF_X25: 59245228Ssklower ifp->if_flags |= IFF_UP; 59345228Ssklower ifp->if_output = x25_ifoutput; 59445228Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 59545228Ssklower if (error == 0) 59645228Ssklower dpinit(ifp->if_unit); 59745228Ssklower break; 59845228Ssklower #endif 59945163Ssklower 60045228Ssklower case SIOCSIFFLAGS: 60145228Ssklower if ((ifp->if_flags & IFF_UP) == 0 && 60245228Ssklower (ifp->if_flags & IFF_RUNNING)) 60345228Ssklower dpdown(ifp->if_unit); 60445228Ssklower else if (ifp->if_flags & IFF_UP && 60545228Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 60645228Ssklower dpinit(ifp->if_unit); 60745228Ssklower break; 60845163Ssklower 60945228Ssklower 61045163Ssklower default: 61145163Ssklower error = EINVAL; 61245163Ssklower } 61345163Ssklower splx(s); 61445163Ssklower return (error); 61545163Ssklower } 61645163Ssklower /* 61745163Ssklower * Reset a device and mark down. 61845163Ssklower * Flush output queue and drop queue limit. 61945163Ssklower */ 62045163Ssklower dpdown(unit) 62145236Ssklower int unit; 62245163Ssklower { 62345236Ssklower 62445163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 62545236Ssklower register struct dpdevice *addr = dp->dp_addr; 62645163Ssklower 62745228Ssklower dpstat.down++; 62845163Ssklower if_qflush(&dp->dp_if.if_snd); 62945236Ssklower dp->dp_flags = 0; 63045236Ssklower dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 63145236Ssklower 63245236Ssklower addr->dpclr = DP_CLR; 63345236Ssklower DELAY(1000); 63445236Ssklower addr->dpsar = 0; 63545236Ssklower addr->dprcsr = 0; 63645163Ssklower } 63745163Ssklower 63845163Ssklower /* 63945163Ssklower * Watchdog timeout to see that transmitted packets don't 64045163Ssklower * lose interrupts. The device has to be online (the first 64145163Ssklower * transmission may block until the other side comes up). 64245163Ssklower */ 64345163Ssklower dptimeout(unit) 64445163Ssklower int unit; 64545163Ssklower { 64645163Ssklower register struct dp_softc *dp; 64745163Ssklower 64845228Ssklower /* currently not armed */ 64945228Ssklower dpstat.timeout++; 65045163Ssklower dp = &dp_softc[unit]; 65145228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) { 65245228Ssklower dpstart(&dp->dp_if); 65345163Ssklower } 65445163Ssklower } 65545228Ssklower /* 65645228Ssklower * For debugging loopback activity. 65745228Ssklower */ 65845228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 65945228Ssklower int dp_louts; 66045228Ssklower 66145228Ssklower dptestoutput(ifp, m, dst, rt) 66245228Ssklower register struct ifnet *ifp; 66345228Ssklower register struct mbuf *m; 66445228Ssklower struct sockaddr *dst; 66545228Ssklower struct rtentry *rt; 66645228Ssklower { 66745228Ssklower /* 66845228Ssklower * Queue message on interface, and start output if interface 66945228Ssklower * not yet active. 67045228Ssklower */ 67145228Ssklower int s = splimp(), error = 0; 67245228Ssklower dp_louts++; 67345228Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 67445228Ssklower if (m == 0) { 67545228Ssklower splx(s); 67645228Ssklower return ENOBUFS; 67745228Ssklower } 67845228Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 67945228Ssklower if (IF_QFULL(&ifp->if_snd)) { 68045228Ssklower IF_DROP(&ifp->if_snd); 68145228Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 68245228Ssklower ifp->if_name, ifp->if_unit);*/ 68345228Ssklower m_freem(m); 68445228Ssklower error = ENOBUFS; 68545228Ssklower } else { 68645228Ssklower IF_ENQUEUE(&ifp->if_snd, m); 68745228Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 68845228Ssklower (*ifp->if_start)(ifp); 68945228Ssklower } 69045228Ssklower splx(s); 69145228Ssklower return (error); 69245228Ssklower } 69345228Ssklower 69445163Ssklower #endif 695