145163Ssklower /* 245163Ssklower * Copyright (c) 1990 Regents of the University of California. 345163Ssklower * All rights reserved. 445163Ssklower * 545163Ssklower * %sccs.include.redist.c% 645163Ssklower * 7*50166Ssklower * @(#)if_dp.c 7.9 (Berkeley) 06/27/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" 4448964Ssklower #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(); 65*50166Ssklower int dpoutput(), dpreset(), dptimeout(), dpstart(), dptestoutput(); 66*50166Ssklower int x25_ifoutput(), x25_rtrequest(); 6745163Ssklower 6845163Ssklower struct uba_device *dpinfo[NDP]; 6945163Ssklower 7045163Ssklower u_short dpstd[] = { 0 }; 7145163Ssklower struct uba_driver dpdriver = 7245163Ssklower { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo }; 7345163Ssklower 7445163Ssklower /* 7545163Ssklower * Pdma structures for fast interrupts. 7645163Ssklower */ 7745163Ssklower struct pdma dppdma[2*NDP]; 7845163Ssklower 7945163Ssklower /* 8045163Ssklower * DP software status per interface. 8145163Ssklower * 8245163Ssklower * Each interface is referenced by a network interface structure, 8345163Ssklower * dp_if, which the routing code uses to locate the interface. 8445163Ssklower * This structure contains the output queue for the interface, its address, ... 8545163Ssklower */ 8645163Ssklower struct dp_softc { 8745163Ssklower struct ifnet dp_if; /* network-visible interface */ 8845228Ssklower int dp_ipl; 8945236Ssklower struct dpdevice *dp_addr; /* dpcsr address */ 9045163Ssklower short dp_iused; /* input buffers given to DP */ 9145163Ssklower short dp_flags; /* flags */ 9245228Ssklower #define DPF_RUNNING 0x01 /* device initialized */ 9345228Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 9445228Ssklower #define DPF_RESTART 0x04 /* software restart in progress */ 9545228Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 96*50166Ssklower #define DPF_X25UP 0x10 /* XXX -- someday we'll do PPP also */ 9745163Ssklower short dp_ostate; /* restarting, etc. */ 9845163Ssklower short dp_istate; /* not sure this is necessary */ 9945163Ssklower #define DPS_IDLE 0 10045163Ssklower #define DPS_RESTART 1 10145163Ssklower #define DPS_ACTIVE 2 10245163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */ 10345289Ssklower short dp_olen; /* length of last packet sent */ 10445289Ssklower short dp_ilen; /* length of last packet recvd */ 10545163Ssklower char dp_obuf[DP_MTU+8]; 10645166Ssklower char dp_ibuf[DP_MTU+8]; 10745163Ssklower } dp_softc[NDP]; 10845163Ssklower 10945289Ssklower /* 11045289Ssklower * Debug info 11145289Ssklower */ 11245289Ssklower struct dpstat { 11345289Ssklower long start; 11445289Ssklower long nohdr; 11545289Ssklower long init; 11645289Ssklower long rint; 11745289Ssklower long xint; 11845289Ssklower long reset; 11945289Ssklower long ioctl; 12045289Ssklower long down; 12145289Ssklower long mchange; 12245289Ssklower long timeout; 12345289Ssklower long rsm; 12445289Ssklower long rem; 12545289Ssklower long remchr; 12645289Ssklower long rga; 12745289Ssklower long xem; 12845289Ssklower long rovr; 12945289Ssklower } dpstat; 13045289Ssklower 13145289Ssklower short dp_ilb = 0; 13248964Ssklower short dp_log = 0; 13345289Ssklower 13445289Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 13545289Ssklower int dp_sizes[] = { 13645289Ssklower sizeof(dp_softc[0]), sizeof(struct ifnet), 13745289Ssklower _offsetof(struct dp_softc, dp_obuf[0]), 13845289Ssklower _offsetof(struct dp_softc, dp_ibuf[0]), 13945289Ssklower }; 14045289Ssklower 14145163Ssklower dpprobe(reg, ui) 14245163Ssklower caddr_t reg; 14345163Ssklower struct uba_device *ui; 14445163Ssklower { 14545163Ssklower register int br, cvec; 14645163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg; 14745236Ssklower register int unit = ui->ui_unit; 14845163Ssklower 14945163Ssklower #ifdef lint 15045163Ssklower br = 0; cvec = br; br = cvec; 15145163Ssklower dprint(0); dpxint(0); 15245163Ssklower #endif 15345228Ssklower (void) spl6(); 15445163Ssklower addr->dpclr = DP_CLR; 15545163Ssklower addr->dpclr = DP_XIE|DP_XE; 15645163Ssklower DELAY(100000); 15745236Ssklower dp_softc[unit].dp_ipl = br = qbgetpri(); 15845236Ssklower dp_softc[unit].dp_addr = addr; 15945163Ssklower addr->dpclr = 0; 16045228Ssklower if (cvec && cvec != 0x200){ 16145228Ssklower cvec -= 4; 16245228Ssklower } 16345163Ssklower return (1); 16445163Ssklower } 16545163Ssklower 16645163Ssklower /* 16745163Ssklower * Interface exists: make available by filling in network interface 16845163Ssklower * record. System will initialize the interface when it is ready 16945163Ssklower * to accept packets. 17045163Ssklower */ 17145163Ssklower dpattach(ui) 17245163Ssklower register struct uba_device *ui; 17345163Ssklower { 17445163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 17545163Ssklower 17645163Ssklower dp->dp_if.if_unit = ui->ui_unit; 17745163Ssklower dp->dp_if.if_name = "dp"; 17845163Ssklower dp->dp_if.if_mtu = DP_MTU; 17945163Ssklower dp->dp_if.if_init = dpinit; 18045163Ssklower dp->dp_if.if_output = x25_ifoutput; 18148964Ssklower dp->dp_if.if_type = IFT_X25; 18248964Ssklower dp->dp_if.if_hdrlen = 5; 18348964Ssklower dp->dp_if.if_addrlen = 8; 18445163Ssklower dp->dp_if.if_start = dpstart; 18545163Ssklower dp->dp_if.if_ioctl = dpioctl; 18645163Ssklower dp->dp_if.if_reset = dpreset; 18745163Ssklower dp->dp_if.if_watchdog = dptimeout; 18845228Ssklower dp->dp_if.if_flags = 0; 18945163Ssklower if_attach(&dp->dp_if); 19045163Ssklower } 19145163Ssklower 19245163Ssklower /* 19345163Ssklower * Reset of interface after UNIBUS reset. 19445163Ssklower * If interface is on specified UBA, reset its state. 19545163Ssklower */ 19645163Ssklower dpreset(unit, uban) 19745163Ssklower int unit, uban; 19845163Ssklower { 19945163Ssklower register struct uba_device *ui; 20045163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 20145163Ssklower register struct dpdevice *addr; 20245163Ssklower 20345228Ssklower dpstat.reset++; 20445163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 20545163Ssklower ui->ui_ubanum != uban) 20645163Ssklower return; 20745236Ssklower dpdown(unit); 20845236Ssklower dpinit(unit); 20945163Ssklower printf(" dp%d", unit); 21045163Ssklower } 21145163Ssklower 21245163Ssklower /* 21345163Ssklower * Initialization of interface. 21445163Ssklower */ 21545163Ssklower dpinit(unit) 21645163Ssklower int unit; 21745163Ssklower { 21845163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 21945163Ssklower register struct dpdevice *addr; 22045228Ssklower register struct ifaddr *ifa; 22145228Ssklower register struct pdma *pdp = &dppdma[unit*2]; 22245228Ssklower int base, s; 22345163Ssklower 22445228Ssklower dpstat.init++; 22545163Ssklower /* 22645163Ssklower * Check to see that an address has been set. 22745163Ssklower */ 22845228Ssklower for (ifa = dp->dp_if.if_addrlist; ifa; ifa = ifa->ifa_next) 22945163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 23045163Ssklower break; 23145163Ssklower if (ifa == (struct ifaddr *) 0) 23245163Ssklower return; 23345163Ssklower 23445236Ssklower addr = dp->dp_addr; 23545228Ssklower s = splimp(); 23645163Ssklower dp->dp_iused = 0; 23745163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE; 23845228Ssklower dp->dp_if.if_flags |= IFF_RUNNING; 23945228Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 24045228Ssklower 24145228Ssklower pdp->p_addr = addr; 24245228Ssklower pdp->p_fcn = dpxint; 24345228Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf; 24445228Ssklower pdp++; 24545228Ssklower pdp->p_addr = addr; 24645228Ssklower pdp->p_fcn = dprint; 24745228Ssklower /* force initial interrupt to come to dprint */ 24845228Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf + DP_MTU + 8; 24945228Ssklower 25045228Ssklower addr->dpclr = DP_CLR; 25145289Ssklower DELAY(5000); 25245237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 25345237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 25445237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 25545289Ssklower addr->dpclr = DP_XE | dp_ilb; 25645289Ssklower addr->dptdsr = DP_XSM; 25745237Ssklower /* enable receiver, receive interrupt, DTR, RTS */ 25845228Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 25945228Ssklower dpstart(&dp->dp_if); 26045163Ssklower splx(s); 26145163Ssklower } 26245163Ssklower 26345163Ssklower /* 26445163Ssklower * Start output on interface. Get another datagram 26545163Ssklower * to send from the interface queue and map it to 26645163Ssklower * the interface before starting output. 26745163Ssklower * 26845163Ssklower */ 26945163Ssklower dpstart(ifp) 27045163Ssklower struct ifnet *ifp; 27145163Ssklower { 27245228Ssklower int s, unit = ifp->if_unit, error = 0, len; 27345163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 27445237Ssklower register struct dpdevice *addr = dp->dp_addr; 27545163Ssklower register struct mbuf *m; 27645163Ssklower register char *cp; 27745163Ssklower char *cplim; 27845163Ssklower 27945163Ssklower /* 28045163Ssklower * If already doing output, go away and depend on transmit 28145163Ssklower * complete or error. 28245163Ssklower */ 28345228Ssklower dpstat.start++; 28445236Ssklower if ((dp->dp_if.if_flags & IFF_OACTIVE) || 28545289Ssklower (dp->dp_if.if_flags & IFF_RUNNING) == 0) 28645228Ssklower goto out; 28745163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m); 28845163Ssklower if (m == 0) 28945228Ssklower goto out; 29045228Ssklower dp->dp_if.if_collisions++; 29145228Ssklower if (m->m_flags & M_PKTHDR) 29245228Ssklower len = m->m_pkthdr.len; 29345228Ssklower else { 29445228Ssklower struct mbuf *m0 = m; 29545228Ssklower for (len = 0; m; m = m->m_next) 29645228Ssklower len += m->m_len; 29745228Ssklower m = m0; 29845228Ssklower dpstat.nohdr++; 29945228Ssklower } 30045289Ssklower if (len < 2) 30145228Ssklower goto out; 30245228Ssklower if (len > DP_MTU) { 30345228Ssklower error = EINVAL; 30445228Ssklower goto out; 30545228Ssklower } 30645289Ssklower dppdma[2*unit].p_mem = cp = dp->dp_obuf; 30745163Ssklower while (m) { 30845163Ssklower struct mbuf *n; 30945163Ssklower bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 31045163Ssklower cp += m->m_len; 31145163Ssklower MFREE(m, n); m = n; 31245163Ssklower } 31345289Ssklower dppdma[2*unit].p_end = cp - 1; 31445163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE; 31545163Ssklower dp->dp_ostate = DPS_ACTIVE; 31645228Ssklower dp->dp_if.if_collisions--; 31745289Ssklower dp->dp_olen = len; 31845289Ssklower if (dp_log) { 31945289Ssklower register u_char *p = (u_char *)dp->dp_obuf; 32045289Ssklower log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n", 32145289Ssklower len, p[0], p[1], p[2], p[3], p[4]); 32245289Ssklower } 32345237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 32445237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 32545289Ssklower addr->dpclr = DP_XIE | DP_XE | dp_ilb; 32645289Ssklower addr->dptdsr = DP_XSM; 32745228Ssklower out: 32845228Ssklower return (error); 32945163Ssklower } 33045163Ssklower /* 33145163Ssklower * Receive done or error interrupt 33245163Ssklower */ 33345163Ssklower dprint(unit, pdma, addr) 33445163Ssklower register struct pdma *pdma; 33545163Ssklower register struct dpdevice *addr; 33645163Ssklower { 33745166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 33845237Ssklower short rdsr = addr->dprdsr, rcsr = pdma->p_arg; 33945163Ssklower 34045228Ssklower dpstat.rint++; 34145228Ssklower splx(dp->dp_ipl); 34245237Ssklower if (rdsr & DP_RGA) { 34345237Ssklower /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), 34445237Ssklower CRC = CCIIT, initially all ones, 2nd addr = 0 */ 34545237Ssklower addr->dpsar = DP_SSLM | DP_IDLE; 34645237Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 34745237Ssklower dpstat.rga++; 34845237Ssklower return; 34945237Ssklower } 35045166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */ 35145237Ssklower dpstat.rsm++; 35245237Ssklower pdma->p_mem = dp->dp_ibuf; 35345237Ssklower if (rcsr & DP_RDR) { 35445237Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF; 35545237Ssklower pdma->p_mem++; 35645237Ssklower } 35745166Ssklower dp->dp_flags &= ~DPF_FLUSH; 35845163Ssklower return; 35945163Ssklower } 36045166Ssklower if (rdsr & DP_REM) { /* Received End of Message */ 36145237Ssklower dpstat.rem++; 36245289Ssklower if (rcsr & DP_RDR) { 36345289Ssklower *(pdma->p_mem++) = rdsr; 36445289Ssklower dpstat.remchr++; 36545289Ssklower } 36645289Ssklower dp->dp_ilen = pdma->p_mem - dp->dp_ibuf; 36745166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 36845166Ssklower dp->dp_if.if_ierrors++; 36945228Ssklower } else 37045289Ssklower dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf); 37145228Ssklower pdma->p_mem = pdma->p_end; 37245228Ssklower dp->dp_flags &= ~ DPF_FLUSH; 37345228Ssklower return; 37445228Ssklower } 37545228Ssklower if (rdsr & DP_ROVR) { 37645289Ssklower dpstat.rovr++; 37745228Ssklower dp->dp_flags |= DPF_FLUSH; 37845228Ssklower return; 37945228Ssklower } 38045228Ssklower if (rcsr & DP_MSC) { 38145228Ssklower dpstat.mchange++; 38245228Ssklower if (0 == (rcsr & DP_DSR)) { 38345228Ssklower log(LOG_DEBUG, "dp%d: lost modem\n", unit); 38445237Ssklower /*dpdown(unit);*/ 38545163Ssklower } 38645163Ssklower return; 38745163Ssklower } 38845163Ssklower dp->dp_flags |= DPF_FLUSH; 38945163Ssklower if (pdma->p_mem != pdma->p_end) 39045289Ssklower log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit); 39145163Ssklower } 39245163Ssklower /* 39345163Ssklower * Transmit complete or error interrupt 39445163Ssklower */ 39545163Ssklower dpxint(unit, pdma, addr) 39645163Ssklower register struct pdma *pdma; 39745163Ssklower register struct dpdevice *addr; 39845163Ssklower { 39945166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 40045228Ssklower int s; 40145163Ssklower 40245228Ssklower splx(dp->dp_ipl); 40345228Ssklower dpstat.xint++; 40445163Ssklower if (addr->dptdsr & DP_XERR) { 40545289Ssklower log(LOG_DEBUG, "if_dp%d: data late\n", unit); 40645163Ssklower restart: 40745163Ssklower pdma->p_mem = dp->dp_obuf; 40845163Ssklower addr->dptdsr = DP_XSM; 40945228Ssklower dp->dp_if.if_oerrors++; 41045163Ssklower return; 41145163Ssklower } 41245163Ssklower switch (dp->dp_ostate) { 41345163Ssklower 41445163Ssklower case DPS_ACTIVE: 41545163Ssklower if (pdma->p_mem != pdma->p_end) { 41645289Ssklower log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit); 41745163Ssklower goto restart; 41845163Ssklower } 41945289Ssklower addr->dpsar = DP_IDLE|DP_SSLM; 42045289Ssklower addr->dpclr = DP_XE | DP_XIE | dp_ilb; 42145289Ssklower addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]); 42245289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; 42345163Ssklower dp->dp_ostate = DPS_XEM; 42445163Ssklower break; 42545163Ssklower 42645163Ssklower case DPS_XEM: 42745289Ssklower dpstat.xem++; 42845228Ssklower dp->dp_if.if_opackets++; 42945289Ssklower dp->dp_ostate = DPS_IDLE; 43045163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 43145163Ssklower if (dp->dp_if.if_snd.ifq_len) 43245163Ssklower dpstart(&dp->dp_if); 43345163Ssklower else { 43445289Ssklower addr->dpsar = DP_IDLE|DP_SSLM; 43545289Ssklower addr->dpclr = DP_XE | dp_ilb; 43645289Ssklower addr->dptdsr = DP_XSM; 43745289Ssklower addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS; 43845163Ssklower } 43945163Ssklower break; 44045163Ssklower 44145163Ssklower default: 44245289Ssklower log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n"); 44345163Ssklower } 44445163Ssklower } 44545163Ssklower /* 44645163Ssklower * Routine to copy from device buffer into mbufs. 44745163Ssklower * 44845163Ssklower * Warning: This makes the fairly safe assumption that 44945163Ssklower * mbufs have even lengths. 45045163Ssklower */ 45145163Ssklower struct mbuf * 45245163Ssklower dpget(rxbuf, totlen, off, ifp) 45345163Ssklower caddr_t rxbuf; 45445163Ssklower int totlen, off; 45545163Ssklower struct ifnet *ifp; 45645163Ssklower { 45745163Ssklower register caddr_t cp; 45845163Ssklower register struct mbuf *m; 45945163Ssklower struct mbuf *top = 0, **mp = ⊤ 46045163Ssklower int len; 46145163Ssklower caddr_t packet_end; 46245163Ssklower 46345163Ssklower cp = rxbuf; 46445163Ssklower packet_end = cp + totlen; 46545163Ssklower if (off) { 46645163Ssklower off += 2 * sizeof(u_short); 46745163Ssklower totlen -= 2 *sizeof(u_short); 46845163Ssklower cp = rxbuf + off; 46945163Ssklower } 47045163Ssklower 47145163Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 47245163Ssklower if (m == 0) 47345163Ssklower return (0); 47445163Ssklower m->m_pkthdr.rcvif = ifp; 47545163Ssklower m->m_pkthdr.len = totlen; 47645163Ssklower m->m_len = MHLEN; 47745163Ssklower 47845163Ssklower while (totlen > 0) { 47945163Ssklower if (top) { 48045163Ssklower MGET(m, M_DONTWAIT, MT_DATA); 48145163Ssklower if (m == 0) { 48245163Ssklower m_freem(top); 48345163Ssklower return (0); 48445163Ssklower } 48545163Ssklower m->m_len = MLEN; 48645163Ssklower } 48745163Ssklower len = min(totlen, (packet_end - cp)); 48845163Ssklower if (len >= MINCLSIZE) { 48945163Ssklower MCLGET(m, M_DONTWAIT); 49045163Ssklower if (m->m_flags & M_EXT) 49145163Ssklower m->m_len = len = min(len, MCLBYTES); 49245163Ssklower else 49345163Ssklower len = m->m_len; 49445163Ssklower } else { 49545163Ssklower /* 49645163Ssklower * Place initial small packet/header at end of mbuf. 49745163Ssklower */ 49845163Ssklower if (len < m->m_len) { 49945163Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 50045163Ssklower m->m_data += max_linkhdr; 50145163Ssklower m->m_len = len; 50245163Ssklower } else 50345163Ssklower len = m->m_len; 50445163Ssklower } 50545163Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 50645163Ssklower *mp = m; 50745163Ssklower mp = &m->m_next; 50845163Ssklower totlen -= len; 50945163Ssklower cp += len; 51045163Ssklower if (cp == packet_end) 51145163Ssklower cp = rxbuf; 51245163Ssklower } 51345163Ssklower return (top); 51445163Ssklower } 51545163Ssklower 51645228Ssklower dpinput(ifp, len, buffer) 51745228Ssklower register struct ifnet *ifp; 51845163Ssklower caddr_t buffer; 51945163Ssklower { 52045163Ssklower register struct ifqueue *inq; 52145163Ssklower register struct mbuf *m; 52245228Ssklower extern struct ifqueue hdintrq, ipintrq; 52345289Ssklower int isr; 52445163Ssklower 52545228Ssklower ifp->if_ipackets++; 52645289Ssklower if (dp_log) { 52745289Ssklower register u_char *p = (u_char *)buffer; 52845289Ssklower log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n", 52945289Ssklower len, p[0], p[1], p[2], p[3], p[4]); 53045289Ssklower } 53145289Ssklower 53245228Ssklower { 53345228Ssklower register struct ifaddr *ifa = ifp->if_addrlist; 53445228Ssklower register u_char *cp = (u_char *)buffer; 53545228Ssklower 53645228Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 53745228Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 53845228Ssklower break; 53945228Ssklower if (cp[0] == 0xff && cp[1] == 0x3) { 54045228Ssklower /* This is a UI HDLC Packet, so we'll assume PPP 54145228Ssklower protocol. for now, IP only. */ 54245228Ssklower buffer += 4; 54345228Ssklower len -= 4; 54445228Ssklower inq = &ipintrq; 54545289Ssklower isr = NETISR_IP; 54645228Ssklower } else { 54745228Ssklower inq = &hdintrq; 54845289Ssklower isr = NETISR_CCITT; 54945228Ssklower } 55045228Ssklower } 55145228Ssklower if (len <= 0) 55245163Ssklower return; 55345163Ssklower 55445163Ssklower m = dpget(buffer, len , 0, ifp); 55545163Ssklower if (m == 0) 55645163Ssklower return; 55745163Ssklower 55845163Ssklower if(IF_QFULL(inq)) { 55945163Ssklower IF_DROP(inq); 56045163Ssklower m_freem(m); 56145163Ssklower } else { 56245163Ssklower IF_ENQUEUE(inq, m); 56345289Ssklower schednetisr(isr); 56445163Ssklower } 56545163Ssklower } 56645163Ssklower 56745163Ssklower /* 56845163Ssklower * Process an ioctl request. 56945163Ssklower */ 57045163Ssklower dpioctl(ifp, cmd, data) 57145163Ssklower register struct ifnet *ifp; 57245163Ssklower int cmd; 57345163Ssklower caddr_t data; 57445163Ssklower { 57545163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 57645163Ssklower int s = splimp(), error = 0; 57745166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit]; 57845163Ssklower 57945228Ssklower dpstat.ioctl++; 58045163Ssklower switch (cmd) { 58145228Ssklower case SIOCSIFCONF_X25: 58245228Ssklower ifp->if_flags |= IFF_UP; 58345228Ssklower error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); 58445228Ssklower if (error == 0) 58545228Ssklower dpinit(ifp->if_unit); 58645228Ssklower break; 58745163Ssklower 588*50166Ssklower case SIOCSIFADDR: 589*50166Ssklower ifa->ifa_rtrequest = x25_rtrequest; 590*50166Ssklower break; 591*50166Ssklower 59245228Ssklower case SIOCSIFFLAGS: 59345228Ssklower if ((ifp->if_flags & IFF_UP) == 0 && 59445228Ssklower (ifp->if_flags & IFF_RUNNING)) 59545228Ssklower dpdown(ifp->if_unit); 59645228Ssklower else if (ifp->if_flags & IFF_UP && 59745228Ssklower (ifp->if_flags & IFF_RUNNING) == 0) 59845228Ssklower dpinit(ifp->if_unit); 59945228Ssklower break; 60045163Ssklower 60145228Ssklower 60245163Ssklower default: 60345163Ssklower error = EINVAL; 60445163Ssklower } 60545163Ssklower splx(s); 60645163Ssklower return (error); 60745163Ssklower } 60845163Ssklower /* 60945163Ssklower * Reset a device and mark down. 61045163Ssklower * Flush output queue and drop queue limit. 61145163Ssklower */ 61245163Ssklower dpdown(unit) 61345236Ssklower int unit; 61445163Ssklower { 61545236Ssklower 61645163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 61745236Ssklower register struct dpdevice *addr = dp->dp_addr; 61845163Ssklower 61945228Ssklower dpstat.down++; 62045163Ssklower if_qflush(&dp->dp_if.if_snd); 62145236Ssklower dp->dp_flags = 0; 62245236Ssklower dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 62345236Ssklower 62445236Ssklower addr->dpclr = DP_CLR; 62545236Ssklower DELAY(1000); 62645236Ssklower addr->dpsar = 0; 62745236Ssklower addr->dprcsr = 0; 62845163Ssklower } 62945163Ssklower 63045163Ssklower /* 63145163Ssklower * Watchdog timeout to see that transmitted packets don't 63245163Ssklower * lose interrupts. The device has to be online (the first 63345163Ssklower * transmission may block until the other side comes up). 63445163Ssklower */ 63545163Ssklower dptimeout(unit) 63645163Ssklower int unit; 63745163Ssklower { 63845163Ssklower register struct dp_softc *dp; 63945163Ssklower 64045228Ssklower /* currently not armed */ 64145228Ssklower dpstat.timeout++; 64245163Ssklower dp = &dp_softc[unit]; 64345228Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) { 64445228Ssklower dpstart(&dp->dp_if); 64545163Ssklower } 64645163Ssklower } 64745228Ssklower /* 64845228Ssklower * For debugging loopback activity. 64945228Ssklower */ 65045228Ssklower static char pppheader[4] = { -1, 3, 0, 0x21 }; 65145228Ssklower int dp_louts; 65245228Ssklower 65345228Ssklower dptestoutput(ifp, m, dst, rt) 65445228Ssklower register struct ifnet *ifp; 65545228Ssklower register struct mbuf *m; 65645228Ssklower struct sockaddr *dst; 65745228Ssklower struct rtentry *rt; 65845228Ssklower { 65945228Ssklower /* 66045228Ssklower * Queue message on interface, and start output if interface 66145228Ssklower * not yet active. 66245228Ssklower */ 66345228Ssklower int s = splimp(), error = 0; 66445228Ssklower dp_louts++; 66545228Ssklower M_PREPEND(m, sizeof pppheader, M_DONTWAIT); 66645228Ssklower if (m == 0) { 66745228Ssklower splx(s); 66845228Ssklower return ENOBUFS; 66945228Ssklower } 67045228Ssklower bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); 67145228Ssklower if (IF_QFULL(&ifp->if_snd)) { 67245228Ssklower IF_DROP(&ifp->if_snd); 67345228Ssklower /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", 67445228Ssklower ifp->if_name, ifp->if_unit);*/ 67545228Ssklower m_freem(m); 67645228Ssklower error = ENOBUFS; 67745228Ssklower } else { 67845228Ssklower IF_ENQUEUE(&ifp->if_snd, m); 67945228Ssklower if ((ifp->if_flags & IFF_OACTIVE) == 0) 68045228Ssklower (*ifp->if_start)(ifp); 68145228Ssklower } 68245228Ssklower splx(s); 68345228Ssklower return (error); 68445228Ssklower } 68545228Ssklower 68645163Ssklower #endif 687