📄 if_dp.c
字号:
m = m0; dpstat.nohdr++; } if (len < 2) goto out; if (len > DP_MTU) { error = EINVAL; goto out; } dppdma[2*unit].p_mem = cp = dp->dp_obuf; while (m) { struct mbuf *n; bcopy(mtod(m, caddr_t), (caddr_t)cp, m->m_len); cp += m->m_len; MFREE(m, n); m = n; } dppdma[2*unit].p_end = cp - 1; dp->dp_if.if_flags |= IFF_OACTIVE; dp->dp_ostate = DPS_ACTIVE; dp->dp_if.if_collisions--; dp->dp_olen = len; if (dp_log) { register u_char *p = (u_char *)dp->dp_obuf; log(LOG_DEBUG, "dpoutput(%d):%x %x %x %x %x\n", len, p[0], p[1], p[2], p[3], p[4]); } addr->dpsar = DP_SSLM | DP_IDLE; addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; addr->dpclr = DP_XIE | DP_XE | dp_ilb; addr->dptdsr = DP_XSM;out: return (error);}/* * Receive done or error interrupt */dprint(unit, pdma, addr)register struct pdma *pdma;register struct dpdevice *addr;{ register struct dp_softc *dp = &dp_softc[unit]; short rdsr = addr->dprdsr, rcsr = pdma->p_arg; dpstat.rint++; splx(dp->dp_ipl); if (rdsr & DP_RGA) { /* DP_ATA = 0, DP_CHRM = 0, DP_SSLM = 1, (enable aborts), CRC = CCIIT, initially all ones, 2nd addr = 0 */ addr->dpsar = DP_SSLM | DP_IDLE; addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; dpstat.rga++; return; } if (rdsr & DP_RSM) { /* Received Start of Message */ dpstat.rsm++; pdma->p_mem = dp->dp_ibuf; if (rcsr & DP_RDR) { dp->dp_ibuf[0] = rdsr & DP_RBUF; pdma->p_mem++; } dp->dp_flags &= ~DPF_FLUSH; return; } if (rdsr & DP_REM) { /* Received End of Message */ dpstat.rem++; if (rcsr & DP_RDR) { *(pdma->p_mem++) = rdsr; dpstat.remchr++; } dp->dp_ilen = pdma->p_mem - dp->dp_ibuf; if (rdsr & DP_REC || dp->dp_flags & DPF_FLUSH) { dp->dp_if.if_ierrors++; } else dpinput(&dp->dp_if, dp->dp_ilen, dp->dp_ibuf); pdma->p_mem = pdma->p_end; dp->dp_flags &= ~ DPF_FLUSH; return; } if (rdsr & DP_ROVR) { dpstat.rovr++; dp->dp_flags |= DPF_FLUSH; return; } if (rcsr & DP_MSC) { dpstat.mchange++; if (0 == (rcsr & DP_DSR)) { log(LOG_DEBUG, "dp%d: lost modem\n", unit); /*dpdown(unit);*/ } return; } dp->dp_flags |= DPF_FLUSH; if (pdma->p_mem != pdma->p_end) log(LOG_DEBUG, "dp%d: unexplained receiver interrupt\n", unit);}/* * Transmit complete or error interrupt */dpxint(unit, pdma, addr)register struct pdma *pdma;register struct dpdevice *addr;{ register struct dp_softc *dp = &dp_softc[unit]; int s; splx(dp->dp_ipl); dpstat.xint++; if (addr->dptdsr & DP_XERR) { log(LOG_DEBUG, "if_dp%d: data late\n", unit); restart: pdma->p_mem = dp->dp_obuf; addr->dptdsr = DP_XSM; dp->dp_if.if_oerrors++; return; } switch (dp->dp_ostate) { case DPS_ACTIVE: if (pdma->p_mem != pdma->p_end) { log(LOG_DEBUG, "if_dp%d: misc error in dpxint\n", unit); goto restart; } addr->dpsar = DP_IDLE|DP_SSLM; addr->dpclr = DP_XE | DP_XIE | dp_ilb; addr->dptdsr = DP_XEM | (0xff & pdma->p_mem[0]); addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR | DP_RTS; dp->dp_ostate = DPS_XEM; break; case DPS_XEM: dpstat.xem++; dp->dp_if.if_opackets++; dp->dp_ostate = DPS_IDLE; dp->dp_if.if_flags &= ~IFF_OACTIVE; if (dp->dp_if.if_snd.ifq_len) dpstart(&dp->dp_if); else { addr->dpsar = DP_IDLE|DP_SSLM; addr->dpclr = DP_XE | dp_ilb; addr->dptdsr = DP_XSM; addr->dprcsr = DP_RIE | DP_MIE | DP_RE | DP_DTR|DP_RTS; } break; default: log(LOG_DEBUG, "if_dp%d: impossible state in dpxint\n"); }}dpinput(ifp, len, buffer)register struct ifnet *ifp;caddr_t buffer;{ register struct ifqueue *inq; register struct mbuf *m; extern struct ifqueue hdintrq, ipintrq; int isr; extern struct mbuf *m_devget(); ifp->if_ipackets++; if (dp_log) { register u_char *p = (u_char *)buffer; log(LOG_DEBUG, "dpinput(%d):%x %x %x %x %x\n", len, p[0], p[1], p[2], p[3], p[4]); } { register struct ifaddr *ifa = ifp->if_addrlist; register u_char *cp = (u_char *)buffer; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if (ifa->ifa_addr->sa_family != AF_LINK) break; if (cp[0] == 0xff && cp[1] == 0x3) { /* This is a UI HDLC Packet, so we'll assume PPP protocol. for now, IP only. */ buffer += 4; len -= 4; inq = &ipintrq; isr = NETISR_IP; } else { inq = &hdintrq; isr = NETISR_CCITT; } } if (len <= 0) return; m = m_devget(buffer, len , 0, ifp, 0); if (m == 0) return; if(IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else { IF_ENQUEUE(inq, m); schednetisr(isr); }}/* * Process an ioctl request. */dpioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ register struct ifaddr *ifa = (struct ifaddr *)data; int s = splimp(), error = 0; struct dp_softc *dp = &dp_softc[ifp->if_unit]; dpstat.ioctl++; switch (cmd) { case SIOCSIFCONF_X25: ifp->if_flags |= IFF_UP; error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); if (error == 0) dpinit(ifp->if_unit); break; case SIOCSIFADDR: ifa->ifa_rtrequest = x25_rtrequest; break; case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && (ifp->if_flags & IFF_RUNNING)) dpdown(ifp->if_unit); else if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) dpinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error);}/* * Reset a device and mark down. * Flush output queue and drop queue limit. */dpdown(unit)int unit;{ register struct dp_softc *dp = &dp_softc[unit]; register struct dpdevice *addr = dp->dp_addr; dpstat.down++; if_qflush(&dp->dp_if.if_snd); dp->dp_flags = 0; dp->dp_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); addr->dpclr = DP_CLR; DELAY(1000); addr->dpsar = 0; addr->dprcsr = 0;}/* * Watchdog timeout to see that transmitted packets don't * lose interrupts. The device has to be online (the first * transmission may block until the other side comes up). */dptimeout(unit) int unit;{ register struct dp_softc *dp; /* currently not armed */ dpstat.timeout++; dp = &dp_softc[unit]; if (dp->dp_if.if_flags & IFF_OACTIVE) { dpstart(&dp->dp_if); }}/* * For debugging loopback activity. */static char pppheader[4] = { -1, 3, 0, 0x21 };int dp_louts;dptestoutput(ifp, m, dst, rt)register struct ifnet *ifp;register struct mbuf *m;struct sockaddr *dst;struct rtentry *rt;{ /* * Queue message on interface, and start output if interface * not yet active. */ int s = splimp(), error = 0; dp_louts++; M_PREPEND(m, sizeof pppheader, M_DONTWAIT); if (m == 0) { splx(s); return ENOBUFS; } bcopy(pppheader, mtod(m, caddr_t), sizeof pppheader); if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); /* printf("%s%d: HDLC says OK to send but queue full, may hang\n", ifp->if_name, ifp->if_unit);*/ m_freem(m); error = ENOBUFS; } else { IF_ENQUEUE(&ifp->if_snd, m); if ((ifp->if_flags & IFF_OACTIVE) == 0) (*ifp->if_start)(ifp); } splx(s); return (error);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -