145163Ssklower /* 245163Ssklower * Copyright (c) 1990 Regents of the University of California. 345163Ssklower * All rights reserved. 445163Ssklower * 545163Ssklower * %sccs.include.redist.c% 645163Ssklower * 7*45166Ssklower * @(#)if_dp.c 7.2 (Berkeley) 08/30/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" 3645163Ssklower #include "syslog.h" 3745163Ssklower #include "vmmac.h" 3845163Ssklower #include "errno.h" 3945163Ssklower #include "time.h" 4045163Ssklower #include "kernel.h" 4145163Ssklower 4245163Ssklower #include "../net/if.h" 4345163Ssklower #include "../net/netisr.h" 4445163Ssklower #include "../net/route.h" 4545163Ssklower 4645163Ssklower #include "../vax/cpu.h" 4745163Ssklower #include "../vax/mtpr.h" 48*45166Ssklower 4945163Ssklower #include "../vaxuba/pdma.h" 50*45166Ssklower #include "../vaxuba/ubavar.h" 5145163Ssklower 52*45166Ssklower #include "../netcitt/x25.h" 53*45166Ssklower 5445163Ssklower #include "if_dpreg.h" 5545163Ssklower 5645163Ssklower /* 5745163Ssklower * Driver information for auto-configuration stuff. 5845163Ssklower */ 5945163Ssklower int dpprobe(), dpattach(), dpinit(), dpioctl(), dprint(), dpxint(); 60*45166Ssklower int dpoutput(), dpreset(), dptimeout(), dpstart(), x25_ifoutput(); 6145163Ssklower 6245163Ssklower struct uba_device *dpinfo[NDP]; 6345163Ssklower 6445163Ssklower u_short dpstd[] = { 0 }; 6545163Ssklower struct uba_driver dpdriver = 6645163Ssklower { dpprobe, 0, dpattach, 0, dpstd, "dp", dpinfo }; 6745163Ssklower 6845163Ssklower /* 6945163Ssklower * Pdma structures for fast interrupts. 7045163Ssklower */ 7145163Ssklower struct pdma dppdma[2*NDP]; 7245163Ssklower 7345163Ssklower /* error reporting intervals */ 7445163Ssklower #define DPI_RPNBFS 50 7545163Ssklower #define DPI_RPDSC 1 7645163Ssklower #define DPI_RPTMO 10 7745163Ssklower #define DPI_RPDCK 10 7845163Ssklower 7945163Ssklower 8045163Ssklower /* 8145163Ssklower * DP software status per interface. 8245163Ssklower * 8345163Ssklower * Each interface is referenced by a network interface structure, 8445163Ssklower * dp_if, which the routing code uses to locate the interface. 8545163Ssklower * This structure contains the output queue for the interface, its address, ... 8645163Ssklower */ 8745163Ssklower struct dp_softc { 8845163Ssklower struct ifnet dp_if; /* network-visible interface */ 8945163Ssklower short dp_iused; /* input buffers given to DP */ 9045163Ssklower short dp_flags; /* flags */ 9145163Ssklower short dp_ostate; /* restarting, etc. */ 9245163Ssklower short dp_istate; /* not sure this is necessary */ 9345163Ssklower #define DPS_IDLE 0 9445163Ssklower #define DPS_RESTART 1 9545163Ssklower #define DPS_ACTIVE 2 9645163Ssklower #define DPS_XEM 3 /* transmitting CRC, etc. */ 9745163Ssklower /* flags */ 9845163Ssklower #define DPF_RUNNING 0x01 /* device initialized */ 9945163Ssklower #define DPF_ONLINE 0x02 /* device running (had a RDYO) */ 10045163Ssklower #define DPF_RESTART 0x04 /* software restart in progress */ 10145163Ssklower #define DPF_FLUSH 0x08 /* had a ROVR, flush ipkt when done */ 10245163Ssklower int dp_errors[4]; /* non-fatal error counters */ 10345163Ssklower #define dp_datck dp_errors[0] 10445163Ssklower #define dp_timeo dp_errors[1] 10545163Ssklower #define dp_nobuf dp_errors[2] 10645163Ssklower #define dp_disc dp_errors[3] 10745163Ssklower char dp_obuf[DP_MTU+8]; 108*45166Ssklower char dp_ibuf[DP_MTU+8]; 10945163Ssklower } dp_softc[NDP]; 11045163Ssklower 11145163Ssklower dpprobe(reg, ui) 11245163Ssklower caddr_t reg; 11345163Ssklower struct uba_device *ui; 11445163Ssklower { 11545163Ssklower register int br, cvec; 11645163Ssklower register struct dpdevice *addr = (struct dpdevice *)reg; 11745163Ssklower register int i; 11845163Ssklower 11945163Ssklower #ifdef lint 12045163Ssklower br = 0; cvec = br; br = cvec; 12145163Ssklower dprint(0); dpxint(0); 12245163Ssklower #endif 12345163Ssklower addr->dpclr = DP_CLR; 12445163Ssklower addr->dpclr = DP_XIE|DP_XE; 12545163Ssklower DELAY(100000); 12645163Ssklower addr->dpclr = 0; 12745163Ssklower return (1); 12845163Ssklower } 12945163Ssklower 13045163Ssklower /* 13145163Ssklower * Interface exists: make available by filling in network interface 13245163Ssklower * record. System will initialize the interface when it is ready 13345163Ssklower * to accept packets. 13445163Ssklower */ 13545163Ssklower dpattach(ui) 13645163Ssklower register struct uba_device *ui; 13745163Ssklower { 13845163Ssklower register struct dp_softc *dp = &dp_softc[ui->ui_unit]; 13945163Ssklower register struct pdma *pdp = &dppdma[ui->ui_unit*2]; 14045163Ssklower 14145163Ssklower dp->dp_if.if_unit = ui->ui_unit; 14245163Ssklower dp->dp_if.if_name = "dp"; 14345163Ssklower dp->dp_if.if_mtu = DP_MTU; 14445163Ssklower dp->dp_if.if_init = dpinit; 14545163Ssklower dp->dp_if.if_output = x25_ifoutput; 14645163Ssklower dp->dp_if.if_start = dpstart; 14745163Ssklower dp->dp_if.if_ioctl = dpioctl; 14845163Ssklower dp->dp_if.if_reset = dpreset; 14945163Ssklower dp->dp_if.if_watchdog = dptimeout; 15045163Ssklower dp->dp_if.if_flags = IFF_POINTOPOINT; 15145163Ssklower 15245163Ssklower 15345163Ssklower pdp->p_addr = (struct dzdevice *)ui->ui_addr; 15445163Ssklower pdp->p_arg = (int)dp; 15545163Ssklower pdp->p_fcn = dpxint; 15645163Ssklower pdp->p_mem = pdp->p_end = dp->dp_obuf; 15745163Ssklower pdp++; 15845163Ssklower pdp->p_addr = (struct dzdevice *)ui->ui_addr; 15945163Ssklower pdp->p_arg = (int)dp; 16045163Ssklower pdp->p_fcn = dprint; 161*45166Ssklower pdp->p_mem = pdp->p_end = dp->dp_ibuf; 16245163Ssklower 16345163Ssklower if_attach(&dp->dp_if); 16445163Ssklower } 16545163Ssklower 16645163Ssklower /* 16745163Ssklower * Reset of interface after UNIBUS reset. 16845163Ssklower * If interface is on specified UBA, reset its state. 16945163Ssklower */ 17045163Ssklower dpreset(unit, uban) 17145163Ssklower int unit, uban; 17245163Ssklower { 17345163Ssklower register struct uba_device *ui; 17445163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 17545163Ssklower register struct dpdevice *addr; 17645163Ssklower 17745163Ssklower if (unit >= NDP || (ui = dpinfo[unit]) == 0 || ui->ui_alive == 0 || 17845163Ssklower ui->ui_ubanum != uban) 17945163Ssklower return; 18045163Ssklower printf(" dp%d", unit); 181*45166Ssklower dp->dp_flags = 0; 18245163Ssklower dp->dp_if.if_flags &= ~IFF_RUNNING; 183*45166Ssklower addr = (struct dpdevice *)ui->ui_addr; 18445163Ssklower addr->dpclr = DP_CLR; 18545163Ssklower addr->dpsar = 0; 18645163Ssklower addr->dprcsr = 0; 18745163Ssklower dpinit(unit); 18845163Ssklower } 18945163Ssklower 19045163Ssklower /* 19145163Ssklower * Initialization of interface. 19245163Ssklower */ 19345163Ssklower dpinit(unit) 19445163Ssklower int unit; 19545163Ssklower { 19645163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 19745163Ssklower register struct uba_device *ui = dpinfo[unit]; 19845163Ssklower register struct dpdevice *addr; 19945163Ssklower register struct ifnet *ifp = &dp->dp_if; 20045163Ssklower struct ifaddr *ifa; 20145163Ssklower int base; 20245163Ssklower int s; 20345163Ssklower 20445163Ssklower addr = (struct dpdevice *)ui->ui_addr; 20545163Ssklower 20645163Ssklower /* 20745163Ssklower * Check to see that an address has been set. 20845163Ssklower */ 20945163Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 21045163Ssklower if (ifa->ifa_addr->sa_family != AF_LINK) 21145163Ssklower break; 21245163Ssklower if (ifa == (struct ifaddr *) 0) 21345163Ssklower return; 21445163Ssklower 21545163Ssklower s = spl5(); 21645163Ssklower dp->dp_iused = 0; 21745163Ssklower dp->dp_istate = dp->dp_ostate = DPS_IDLE; 21845163Ssklower dppdma[2*unit+1].p_end = 219*45166Ssklower dppdma[2*unit+1].p_mem = dp->dp_ibuf; 22045163Ssklower /* enable receive interrupt; CTS comming up will trigger it also */ 22145163Ssklower addr->dpsar = DP_CHRM | 0x7E; /* 7E is the flag character */ 22245163Ssklower addr->dpclr = 0; 22345163Ssklower addr->dprcsr = DP_RIE | DP_DTR | DP_RE; 22445163Ssklower splx(s); 22545163Ssklower } 22645163Ssklower 22745163Ssklower /* 22845163Ssklower * Start output on interface. Get another datagram 22945163Ssklower * to send from the interface queue and map it to 23045163Ssklower * the interface before starting output. 23145163Ssklower * 23245163Ssklower */ 23345163Ssklower dpstart(ifp) 23445163Ssklower struct ifnet *ifp; 23545163Ssklower { 23645163Ssklower int s, unit = ifp->if_unit; 23745163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 238*45166Ssklower register struct dpdevice *addr = 239*45166Ssklower (struct dpdevice *)(dpinfo[unit]->ui_addr); 24045163Ssklower register struct mbuf *m; 24145163Ssklower register char *cp; 24245163Ssklower char *cplim; 24345163Ssklower 24445163Ssklower /* 24545163Ssklower * If already doing output, go away and depend on transmit 24645163Ssklower * complete or error. 24745163Ssklower */ 24845163Ssklower s = splimp(); 24945163Ssklower if (dp->dp_if.if_flags & IFF_OACTIVE) { 25045163Ssklower splx(s); 25145163Ssklower return (0); 25245163Ssklower } 25345163Ssklower IF_DEQUEUE(&dp->dp_if.if_snd, m); 25445163Ssklower if (m == 0) 25545163Ssklower return (0); 25645163Ssklower if ((m->m_flags | M_PKTHDR) == 0 || m->m_pkthdr.len > DP_MTU) 25745163Ssklower return (EINVAL); 25845163Ssklower s = spl5(); 25945163Ssklower dppdma[2*unit].p_mem = cp = dp->dp_obuf; 26045163Ssklower while (m) { 26145163Ssklower struct mbuf *n; 26245163Ssklower bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); 26345163Ssklower cp += m->m_len; 26445163Ssklower MFREE(m, n); m = n; 26545163Ssklower } 26645163Ssklower if (cp == dp->dp_obuf) 26745163Ssklower return (0); 26845163Ssklower dppdma[2*unit].p_end = cp; 26945163Ssklower addr->dpclr = DP_XE | DP_XIE; 27045163Ssklower addr->dptdsr = DP_XSM; 27145163Ssklower dp->dp_if.if_flags |= IFF_OACTIVE; 27245163Ssklower dp->dp_ostate = DPS_ACTIVE; 27345163Ssklower splx(s); 27445163Ssklower return (0); 27545163Ssklower } 27645163Ssklower /* 27745163Ssklower * Receive done or error interrupt 27845163Ssklower */ 27945163Ssklower dprint(unit, pdma, addr) 28045163Ssklower register struct pdma *pdma; 28145163Ssklower register struct dpdevice *addr; 28245163Ssklower { 283*45166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 284*45166Ssklower short rdsr = addr->dprdsr; 28545163Ssklower 286*45166Ssklower if (rdsr & DP_ROVR) { 28745163Ssklower dp->dp_flags |= DPF_FLUSH; 28845163Ssklower return; 28945163Ssklower } 290*45166Ssklower if (rdsr & DP_RSM) { /* Received Start of Message */ 291*45166Ssklower dp->dp_ibuf[0] = rdsr & DP_RBUF; 29245163Ssklower pdma->p_mem = dp->dp_ibuf + 1; 293*45166Ssklower dp->dp_flags &= ~DPF_FLUSH; 29445163Ssklower return; 29545163Ssklower } 296*45166Ssklower if (rdsr & DP_REM) { /* Received End of Message */ 297*45166Ssklower if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { 298*45166Ssklower dp->dp_if.if_ierrors++; 29945163Ssklower pdma->p_mem = dp->dp_ibuf; 30045163Ssklower dp->dp_flags &= ~ DPF_FLUSH; 30145163Ssklower return; 30245163Ssklower } 30345163Ssklower dpinput(dp, pdma->p_mem - dp->dp_ibuf, dp->dp_ibuf); 30445163Ssklower return; 30545163Ssklower } 30645163Ssklower dp->dp_flags |= DPF_FLUSH; 30745163Ssklower if (pdma->p_mem != pdma->p_end) 308*45166Ssklower log("dp%d: unexplained receiver interrupt\n", unit); 30945163Ssklower } 31045163Ssklower 31145163Ssklower /* 31245163Ssklower * Transmit complete or error interrupt 31345163Ssklower */ 31445163Ssklower dpxint(unit, pdma, addr) 31545163Ssklower register struct pdma *pdma; 31645163Ssklower register struct dpdevice *addr; 31745163Ssklower { 318*45166Ssklower register struct dp_softc *dp = &dp_softc[unit]; 31945163Ssklower 32045163Ssklower if (addr->dptdsr & DP_XERR) { 32145163Ssklower log("if_dp%d: data late\n", unit); 32245163Ssklower restart: 32345163Ssklower pdma->p_mem = dp->dp_obuf; 32445163Ssklower addr->dptdsr = DP_XSM; 32545163Ssklower return; 32645163Ssklower } 32745163Ssklower switch (dp->dp_ostate) { 32845163Ssklower 32945163Ssklower case DPS_ACTIVE: 33045163Ssklower if (pdma->p_mem != pdma->p_end) { 33145163Ssklower log("if_dp%d: misc error in dpxint\n"); 33245163Ssklower goto restart; 33345163Ssklower } 33445163Ssklower addr->dptdsr = DP_XEM; 33545163Ssklower dp->dp_ostate = DPS_XEM; 33645163Ssklower break; 33745163Ssklower 33845163Ssklower case DPS_XEM: 33945163Ssklower dp->dp_if.if_flags &= ~IFF_OACTIVE; 34045163Ssklower if (dp->dp_if.if_snd.ifq_len) 34145163Ssklower dpstart(&dp->dp_if); 34245163Ssklower else { 34345163Ssklower addr->dpclr = 0; 34445163Ssklower dp->dp_ostate = DPS_IDLE; 34545163Ssklower } 34645163Ssklower break; 34745163Ssklower 34845163Ssklower default: 34945163Ssklower log("if_dp%d: impossible state in dpxint\n"); 35045163Ssklower } 35145163Ssklower } 35245163Ssklower /* 35345163Ssklower * Routine to copy from device buffer into mbufs. 35445163Ssklower * 35545163Ssklower * Warning: This makes the fairly safe assumption that 35645163Ssklower * mbufs have even lengths. 35745163Ssklower */ 35845163Ssklower struct mbuf * 35945163Ssklower dpget(rxbuf, totlen, off, ifp) 36045163Ssklower caddr_t rxbuf; 36145163Ssklower int totlen, off; 36245163Ssklower struct ifnet *ifp; 36345163Ssklower { 36445163Ssklower register caddr_t cp; 36545163Ssklower register struct mbuf *m; 36645163Ssklower struct mbuf *top = 0, **mp = ⊤ 36745163Ssklower int len; 36845163Ssklower caddr_t packet_end; 36945163Ssklower 37045163Ssklower cp = rxbuf; 37145163Ssklower packet_end = cp + totlen; 37245163Ssklower if (off) { 37345163Ssklower off += 2 * sizeof(u_short); 37445163Ssklower totlen -= 2 *sizeof(u_short); 37545163Ssklower cp = rxbuf + off; 37645163Ssklower } 37745163Ssklower 37845163Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 37945163Ssklower if (m == 0) 38045163Ssklower return (0); 38145163Ssklower m->m_pkthdr.rcvif = ifp; 38245163Ssklower m->m_pkthdr.len = totlen; 38345163Ssklower m->m_len = MHLEN; 38445163Ssklower 38545163Ssklower while (totlen > 0) { 38645163Ssklower if (top) { 38745163Ssklower MGET(m, M_DONTWAIT, MT_DATA); 38845163Ssklower if (m == 0) { 38945163Ssklower m_freem(top); 39045163Ssklower return (0); 39145163Ssklower } 39245163Ssklower m->m_len = MLEN; 39345163Ssklower } 39445163Ssklower len = min(totlen, (packet_end - cp)); 39545163Ssklower if (len >= MINCLSIZE) { 39645163Ssklower MCLGET(m, M_DONTWAIT); 39745163Ssklower if (m->m_flags & M_EXT) 39845163Ssklower m->m_len = len = min(len, MCLBYTES); 39945163Ssklower else 40045163Ssklower len = m->m_len; 40145163Ssklower } else { 40245163Ssklower /* 40345163Ssklower * Place initial small packet/header at end of mbuf. 40445163Ssklower */ 40545163Ssklower if (len < m->m_len) { 40645163Ssklower if (top == 0 && len + max_linkhdr <= m->m_len) 40745163Ssklower m->m_data += max_linkhdr; 40845163Ssklower m->m_len = len; 40945163Ssklower } else 41045163Ssklower len = m->m_len; 41145163Ssklower } 41245163Ssklower bcopy(cp, mtod(m, caddr_t), (u_int)len); 41345163Ssklower *mp = m; 41445163Ssklower mp = &m->m_next; 41545163Ssklower totlen -= len; 41645163Ssklower cp += len; 41745163Ssklower if (cp == packet_end) 41845163Ssklower cp = rxbuf; 41945163Ssklower } 42045163Ssklower return (top); 42145163Ssklower } 42245163Ssklower 42345163Ssklower dpinput(dp, len, buffer) 424*45166Ssklower register struct dp_softc *dp; 42545163Ssklower caddr_t buffer; 42645163Ssklower { 42745163Ssklower register struct ifnet *ifp = &dp->dp_if; 42845163Ssklower register struct ifqueue *inq; 42945163Ssklower register struct mbuf *m; 43045163Ssklower extern struct ifqueue hdintrq; 43145163Ssklower 43245163Ssklower if(len <= 0 || ifp->if_addrlist == 0) 43345163Ssklower return; 43445163Ssklower 43545163Ssklower m = dpget(buffer, len , 0, ifp); 43645163Ssklower if (m == 0) 43745163Ssklower return; 43845163Ssklower ifp->if_ipackets++; 43945163Ssklower 44045163Ssklower /* Only AF_CCITT makes sense at this point */ 44145163Ssklower inq = &hdintrq; 44245163Ssklower 44345163Ssklower if(IF_QFULL(inq)) { 44445163Ssklower IF_DROP(inq); 44545163Ssklower m_freem(m); 44645163Ssklower } else { 44745163Ssklower IF_ENQUEUE(inq, m); 448*45166Ssklower schednetisr(NETISR_CCITT); 44945163Ssklower } 45045163Ssklower } 45145163Ssklower 45245163Ssklower /* 45345163Ssklower * Process an ioctl request. 45445163Ssklower */ 45545163Ssklower dpioctl(ifp, cmd, data) 45645163Ssklower register struct ifnet *ifp; 45745163Ssklower int cmd; 45845163Ssklower caddr_t data; 45945163Ssklower { 46045163Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 46145163Ssklower int s = splimp(), error = 0; 462*45166Ssklower struct dp_softc *dp = &dp_softc[ifp->if_unit]; 46345163Ssklower 46445163Ssklower switch (cmd) { 46545163Ssklower 46645163Ssklower case SIOCSIFADDR: 46745163Ssklower ifp->if_flags |= IFF_UP; 46845163Ssklower switch (ifa->ifa_addr->sa_family) { 46945163Ssklower #ifdef CCITT 47045163Ssklower case AF_CCITT: 471*45166Ssklower error = hd_ctlinput(PRC_IFUP, (caddr_t)&ifa->ifa_addr); 47245163Ssklower if (error == 0) 47345163Ssklower dpinit(ifp->if_unit); 47445163Ssklower break; 47545163Ssklower #endif 47645163Ssklower case SIOCSIFFLAGS: 47745163Ssklower if ((ifp->if_flags & IFF_UP) == 0 && 47845163Ssklower (dp->dp_flags & DPF_RUNNING)) 47945163Ssklower dpdown(ifp->if_unit); 48045163Ssklower else if (ifp->if_flags & IFF_UP && 48145163Ssklower (dp->dp_flags & DPF_RUNNING) == 0) 48245163Ssklower dpinit(ifp->if_unit); 48345163Ssklower break; 48445163Ssklower 48545163Ssklower default: 48645163Ssklower dpinit(ifp->if_unit); 48745163Ssklower break; 48845163Ssklower } 48945163Ssklower break; 49045163Ssklower 49145163Ssklower /* case SIOCSIFFLAGS: ... */ 49245163Ssklower 49345163Ssklower default: 49445163Ssklower error = EINVAL; 49545163Ssklower } 49645163Ssklower splx(s); 49745163Ssklower return (error); 49845163Ssklower } 49945163Ssklower /* 50045163Ssklower * Reset a device and mark down. 50145163Ssklower * Flush output queue and drop queue limit. 50245163Ssklower */ 50345163Ssklower dpdown(unit) 50445163Ssklower int unit; 50545163Ssklower { 50645163Ssklower register struct dp_softc *dp = &dp_softc[unit]; 50745163Ssklower register struct ifxmt *ifxp; 508*45166Ssklower register struct dpdevice *addr = (struct dpdevice *)dpinfo[unit]->ui_addr; 50945163Ssklower 510*45166Ssklower dp->dp_flags &= ~(DPF_RUNNING | DPF_ONLINE); 51145163Ssklower addr->dpclr = DP_CLR; 51245163Ssklower addr->dpclr = 0; 51345163Ssklower 51445163Ssklower if_qflush(&dp->dp_if.if_snd); 51545163Ssklower } 51645163Ssklower 51745163Ssklower /* 51845163Ssklower * Watchdog timeout to see that transmitted packets don't 51945163Ssklower * lose interrupts. The device has to be online (the first 52045163Ssklower * transmission may block until the other side comes up). 52145163Ssklower */ 52245163Ssklower dptimeout(unit) 52345163Ssklower int unit; 52445163Ssklower { 52545163Ssklower register struct dp_softc *dp; 52645163Ssklower struct dpdevice *addr; 52745163Ssklower 52845163Ssklower dp = &dp_softc[unit]; 529*45166Ssklower if (dp->dp_flags & DPF_ONLINE) { 53045163Ssklower addr = (struct dpdevice *)(dpinfo[unit]->ui_addr); 53145163Ssklower dpstart(unit); 53245163Ssklower } 53345163Ssklower } 53445163Ssklower #endif 535