📄 if_apx.c
字号:
register struct apc_mem *apc; struct apx_softc *apx;{ register struct apc_mem *apcbase = apx->apx_dmem; register int i;#define LOWADDR(e) (((u_long)&(apcbase->e)) & 0xffff)#define HIADDR(e) ((((u_long)&(apcbase->e)) >> 16) & 0xff)#define SET_SGAE(d, f, a) {(d).lo = LOWADDR(a); (d).f_hi = (f) | HIADDR(a);}#define SET_SGDX(d, f, a, b) \ {SET_SGAE((d).sgdx_ae, f, a); (d).sgdx_mcnt = (d).sgdx_bcnt = (b);} apx->apx_txnum = apx->apx_rxnum = apx->apx_txcnt = 0; bzero((caddr_t)apc, ((caddr_t)(&apc->apc_rxmd[0])) - (caddr_t)apc); apc->apc_mode = 0x0108; /* 2 flag spacing, leave addr & ctl, do CRC16 */ apc->apc_sgop = apx->apx_modes.apm_sgop; SET_SGAE(apx->apx_csr23, SG_UIE | SG_PROM, apc_mode); SET_SGAE(apc->apc_rxdd, SG_RLEN, apc_rxmd[0]); i = SG_TLEN | ((apx->apx_modes.apm_txwin)<< 8); SET_SGAE(apc->apc_txdd, i, apc_txmd[0]); SET_SGAE(apc->apc_stdd, 0, apc_sgsb); SET_SGDX(apc->apc_rxtid, SG_OWN, apc_rxidbuf[0], -SGMTU); SET_SGDX(apc->apc_txtid, 0, apc_txidbuf[0], 0); for (i = 0; i < SGRBUF; i++) SET_SGDX(apc->apc_rxmd[i], SG_OWN, apc_rbuf[i][0], -SGMTU) for (i = 0; i < SGTBUF; i++) SET_SGDX(apc->apc_txmd[i], 0, apc_tbuf[i][0], 0)}/* * Start output on interface. Get another datagram to send * off of the interface queue, and copy it to the interface * before starting the output. */apxstart(ifp) struct ifnet *ifp;{ register struct apx_softc *apx = &apx_softc[ifp->if_unit]; register struct sgdx *dx; struct apc_mem *apc = apx->apx_hmem; struct mbuf *m; int len; if ((ifp->if_flags & IFF_RUNNING) == 0) return (0); do { dx = apc->apc_txmd + apx->apx_txnum; if (dx->sgdx_flags & SG_OWN) return (0); IF_DEQUEUE(&ifp->if_snd, m); if (m == 0) return (0); len = min(m->m_pkthdr.len, SGMTU); m_copydata(m, 0, len, apc->apc_tbuf[apx->apx_txnum]); m_freem(m); dx->sgdx_mcnt = -len; dx->sgdx_flags = (SG_OWN|SG_TUI|SG_SLF|SG_ELF) | (0xff & dx->sgdx_flags); SG_WCSR(apx, 0, SG_INEA | SG_TDMD); DELAY(20); if (++apx->apx_txnum >= SGTBUF) apx->apx_txnum = 0; } while (++apx->apx_txcnt < SGTBUF); apx->apx_txcnt = SGTBUF; /* in case txcnt > SGTBUF by mistake */ ifp->if_flags |= IFF_OACTIVE; return (0);}voidapxintr(){ register struct apx_softc *apx; int reply; apxstat.anyint++; for (apx = apx_softc + NAPX + NAPX; --apx >= apx_softc;) { if (apx->apx_flags & APXF_CHIPHERE) /* Try to turn off interrupt cause */ while ((reply = SG_RCSR(apx, 0)) & 0xff) { SG_WCSR(apx, 0, SG_INEA | 0xfe); if (reply & (SG_MERR|SG_TUR|SG_ROR)) { apxerror(apx, "mem, rx, or tx error", reply); apxinit(apx->apx_if.if_unit); break; } if (reply & SG_RINT) apxrint(apx); if (reply & SG_TINT) apxtint(apx); if (reply & SG_PINT) apxstat.pint++; } }}voidapxtint(apx) register struct apx_softc *apx;{ register struct apc_mem *apc = apx->apx_hmem; int i, loopcount = 0; apxstat.tint++; do { if ((i = apx->apx_txnum - apx->apx_txcnt) < 0) i += SGTBUF; if (apc->apc_txmd[i].sgdx_flags & SG_OWN) { if (loopcount) break; apxstat.txnull++; return; } loopcount++; apx->apx_if.if_flags &= ~IFF_OACTIVE; } while (--apx->apx_txcnt > 0); apxstart(&apx->apx_if);}voidapxrint(apx) register struct apx_softc *apx;{ register struct apc_mem *apc = apx->apx_hmem; register struct sgdx *dx = apc->apc_rxmd + apx->apx_rxnum; int i = 0;#define SGNEXTRXMD \dx = ++apx->apx_rxnum == SGRBUF ? &apc->apc_rxmd[apx->apx_rxnum = 0] : dx + 1; apxstat.rint++; /* * Out of sync with hardware, should never happen? */ while (dx->sgdx_flags & SG_OWN) { apxstat.rxnrdy++; if (++i == SGRBUF) { apxstat.rxnull++; return; } SGNEXTRXMD; } /* * Process all buffers with valid data */ while ((dx->sgdx_flags & SG_OWN) == 0) { if ((dx->sgdx_flags & (SG_SLF|SG_ELF)) != (SG_SLF|SG_ELF)) { /* * Find the end of the packet so we synch up. * We throw the data away. */ apxerror(apx, "chained buffer", dx->sgdx_flags); do { apxstat.rx2big++; dx->sgdx_bcnt = 0; dx->sgdx_flags = SG_OWN | (0xff&dx->sgdx_flags); SGNEXTRXMD; } while (!(dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF))); /* * If search terminated without successful completion * we reset the hardware (conservative). */ if ((dx->sgdx_flags & (SG_OWN|SG_SLF|SG_ELF)) != SG_ELF) { apxreset(apx->apx_if.if_unit); return; } } else apxinput(&apx->apx_if, apc->apc_rbuf[apx->apx_rxnum], -dx->sgdx_mcnt); dx->sgdx_bcnt = 0; dx->sgdx_flags = SG_OWN | (0xff & dx->sgdx_flags); SGNEXTRXMD; }}voidapxinput(ifp, buffer, len) register struct ifnet *ifp; caddr_t buffer;{ extern struct ifqueue hdintrq, ipintrq; register struct ifqueue *inq; register u_char *cp = (u_char *)buffer; struct mbuf *m, *m_devget(); int isr; ifp->if_ipackets++; if ((ifp->if_flags & IFF_UP) == 0) { apxstat.nxpctd++; return; } 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 {#ifdef CCITT inq = &hdintrq; isr = NETISR_CCITT; } if (len <= 0) {#endif return; } m = m_devget(buffer, len, 0, ifp, (void (*)())0); if (m == 0) return; if(IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else { apxstat.queued++; IF_ENQUEUE(inq, m); schednetisr(isr); }}/* * Process an ioctl request. */apxioctl(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 apx_softc *apx = &apx_softc[ifp->if_unit]; switch (cmd) { case SIOCSIFADDR:#ifdef CCITT ifa->ifa_rtrequest = x25_rtrequest; break; case SIOCSIFCONF_X25: ifp->if_output = x25_ifoutput; ifp->if_flags |= IFF_UP; error = hd_ctlinput(PRC_IFUP, ifa->ifa_addr); if (error == 0) apxinit(ifp->if_unit);#endif break; case SIOCSIFFLAGS: if (((ifp->if_flags & IFF_UP) == 0 && (ifp->if_flags & IFF_RUNNING)) || (ifp->if_flags & IFF_UP) && (ifp->if_flags & IFF_RUNNING) == 0) apxinit(ifp->if_unit); break; case SIOCSIFMODE: if ((ifp->if_flags & IFF_UP) == 0) apx->apx_modes = *(struct apc_modes *)data; else default: error = EINVAL; } splx(s); return (error);}apxerror(apx, msg, data) register struct apx_softc *apx; char *msg;{ log(LOG_WARNING, "apc%d: %s, stat=0x%x\n", apx->apx_if.if_unit, msg, data);}/* * For debugging loopback activity. */apxoutput(ifp, m, dst, rt)register struct ifnet *ifp;register struct mbuf *m;struct sockaddr *dst;struct rtentry *rt;{ int s = splimp(), error = 0; static char pppheader[4] = { -1, 3, 0, 0x21 }; /* * Queue message on interface, and start output if interface * not yet active. */ ifp->if_opackets++; 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); 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 /* NAPX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -