⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_apx.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -