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

📄 if_qe.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
		return(0);	if (totlen > MLEN) {		MCLGET(m, p);		if (p == 0) {			m_freem(m);			return(0);		}	}	if (off) {		/* crunch trailer */		off = totlen - off0;		bcopy(cp, (mtod(m, caddr_t) + off), off0);		cp += off0;		bcopy(cp, mtod(m, caddr_t), off);	} else {		bcopy(cp, mtod(m, caddr_t), totlen);	}	m->m_len = totlen;	return (m);#endif mips#ifdef vax	while (totlen > 0) {		MGET(m, M_DONTWAIT, MT_DATA);		if (m == 0)			goto bad;		if (off) {			len = totlen - off;			cp = ifrw->ifrw_addr + ifu->ifu_hlen + off;		} else			len = totlen;		if (len >= CLBYTES) {			struct mbuf *p;			struct pte *cpte, *ppte;			int x, *ip, i, swt=2;			caddr_t dp, tcp;			MCLGET(m, p);			if (p == 0)				goto nopage;			m->m_len = len;			if((uba_hd[ifu->ifu_uban].uba_type & UBAUVI)						|| !pgaligned(cp))				goto copy;		        if(len > CLBYTES)				swt = 4;			/*			 * Switch pages mapped to Q-BUS with new page p,			 * as quick form of copy.  Remap Q-BUS and invalidate.			 */			dp = mtod(m, caddr_t);			tcp = cp;			cpte = &kmempt[mtocl(cp)];			ppte = &kmempt[mtocl(p)];			x = btop(cp - ifrw->ifrw_addr);			ip = (int *)&ifrw->ifrw_mr[x];			/* Keep pages contiguous */			for (i = 0; i < swt; i++) {				struct pte t;				t = *ppte; *ppte++ = *cpte; *cpte = t;				*ip++ =				    cpte++->pg_pfnum|ifrw->ifrw_proto;				mtpr(TBIS, tcp);				tcp += NBPG;				mtpr(TBIS, dp);				dp += NBPG;			}			cp += len;			goto nocopy;		}nopage:		m->m_len = MIN(MLEN, len);		m->m_off = MMINOFF;copy:		bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len);		cp += m->m_len;nocopy:		*mp = m;		mp = &m->m_next;		if (off) {			/* sort of an ALGOL-W style for statement... */			off += m->m_len;			if (off == totlen) {				cp = ifrw->ifrw_addr + ifu->ifu_hlen;				off = 0;				totlen = off0;			}		} else			totlen -= m->m_len;	}	return (top);bad:	m_freem(top);	return (0);#endif vax}/* * Map a chain of mbufs onto a network interface * in preparation for an i/o operation. * The argument chain of mbufs includes the local network * header which is copied to be in the mapped, aligned * i/o space. */int qe_showput = 0;qeput(ifu, n, m)	struct qeuba *ifu;	int n;	register struct mbuf *m;{	register caddr_t cp;	register struct ifxmt *ifxp;	register struct ifrw *ifrw;	register int i;	int xswapd = 0;	int x, cc, t;	caddr_t dp;	ifxp = &ifu->ifu_w[n];	ifrw = &ifxp->x_ifrw;	cp = ifrw->ifrw_addr;	ifxp->x_xtofree = m;#ifdef vax	while (m) {		dp = mtod(m, char *);			if((uba_hd[ifu->ifu_uban].uba_type & UBAUVI) == 0				&& claligned(cp) && claligned(dp) &&				m->m_len == CLBYTES) {			struct pte *pte; int *ip;		if(qe_showput)			cprintf("qeput %x %x %d\n", cp, dp, m->m_len);			pte = &kmempt[mtocl(dp)];			x = btop(cp - ifrw->ifrw_addr);			ip = (int *)&ifrw->ifrw_mr[x];			for (i = 0; i < CLSIZE; i++)				*ip++ =				    ifrw->ifrw_proto | pte++->pg_pfnum;			xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT));			cp += m->m_len;		} else {		if(qe_showput)			cprintf("qeput_slow %x %x %d\n", cp, dp, m->m_len);			bcopy(dp, cp, (unsigned)m->m_len);			cp += m->m_len;		}		m = m->m_next;	}	/*	 * Pad out short transmits with NULL's	 */	if ((cc = cp - ifrw->ifrw_addr) < MINDATA) {		bzero(cp, MINDATA - cc);		cc = MINDATA;	}	/*	 * Xswapd is the set of clusters we just mapped out.  Ifxp->x_xswapd	 * is the set of clusters mapped out from before.  We compute	 * the number of clusters involved in this operation in x.	 * Clusters mapped out before and involved in this operation	 * should be unmapped so original pages will be accessed by the device.	 */	x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT;	ifxp->x_xswapd &= ~xswapd;	while (i = ffs(ifxp->x_xswapd)) {		i--;		if (i >= x)			break;		ifxp->x_xswapd &= ~(1<<i);		i *= CLSIZE;		for (t = 0; t < CLSIZE; t++) {			ifrw->ifrw_mr[i] = ifxp->x_map[i];			i++;		}	}	ifxp->x_xswapd |= xswapd;#endif vax/* use bcopy instead of swapping the page */ #ifdef mips	while (m) {		dp = mtod(m, char *);		if(qe_showput)			cprintf("qeput_slow %x %x %d\n", cp, dp, m->m_len);		bcopy(dp, cp, (unsigned)m->m_len);		cp += m->m_len;		m = m->m_next;	}	/*	 * Pad out short transmits with NULL's	 */	if ((cc = cp - ifrw->ifrw_addr) < MINDATA) {		bzero(cp, MINDATA - cc);		cc = MINDATA;	}#endif mips	return (cc);}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */qeread(sc, ifrw, len, swloop)	register struct qe_softc *sc;	struct ifrw *ifrw;	int len;	struct mbuf *swloop;{	struct ether_header *eh, swloop_eh,eh1;    	struct mbuf *m, *swloop_tmp1, *swloop_tmp2;	struct protosw *pr;	int off, resid;	struct ifqueue *inq;	static int qe_drop_no=0;	/*	 * Deal with trailer protocol: if type is INET trailer	 * get true type from first 16-bit word past data.	 * Remember that type was trailer by setting off.	 */	if (swloop) {		eh = mtod(swloop, struct ether_header *);		swloop_eh = *eh;		eh = &swloop_eh;		if ( swloop->m_len > sizeof(struct ether_header))			m_adj(swloop, sizeof(struct ether_header));		else {			MFREE(swloop, swloop_tmp1);			if ( ! swloop_tmp1 )				return;			else				swloop = swloop_tmp1;		}	}	eh = (struct ether_header *)ifrw->ifrw_addr;		/* try to aviod the assignment problem due to instruction	pipelines */	eh1 = *eh;	eh1.ether_type = ntohs((u_short)eh->ether_type);	eh = &eh1;#define	qedataaddr(eh, off, type)	((type)(((caddr_t)((eh)+1)+(off))))	if ((eh->ether_type >= ETHERTYPE_TRAIL &&	    eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) 		) {			off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;		if (off >= ETHERMTU)			return;		/* sanity */		if (swloop) {			struct mbuf *mprev, *m0 = swloop;/* need to check this against off */			mprev = m0;			while (swloop->m_next){/*real header at end of chain*/				mprev = swloop;				swloop = swloop->m_next;			}			/* move to beginning of chain */			mprev->m_next = 0;			swloop->m_next = m0;			eh->ether_type = ntohs( *mtod(swloop, u_short *));		} else {		        eh->ether_type = ntohs(*(qedataaddr((struct ether_header *)ifrw->ifrw_addr,off, u_short *)));		        resid = ntohs(*(qedataaddr((struct ether_header *)ifrw->ifrw_addr,off+2, u_short *)));			if (off + resid > len)			     return;		/* sanity */			len = off + resid;		}	} else {		off = 0;	}	if (len == 0)		return;	/*	 * Pull packet off interface.  Off is nonzero if packet	 * has trailing header; qeget will then force this header	 * information to be at the front, but we still have to drop	 * the type and length which are at the front of any trailer data.	 */	if (swloop) {		m = m_copy(swloop, 0, M_COPYALL);		m_freem(swloop);	} else {		m = qeget(&sc->qeuba, ifrw, len, off);	}	if (m == 0)		return;	if (off) {		m->m_off += 2 * sizeof (u_short);		m->m_len -= 2 * sizeof (u_short);	}	/*	 * Bump up input packets and DECnet counters. Input packets for	 * "netstat" include ALL directed, multicast, and error inputs.	 * For DECnet, only error-free input packets are counted. See the	 * DEUNA User's Guide for a breakdown of the counters.	 */	sc->is_if.if_ipackets++;	sc->ctrblk.est_bytercvd += len ;	if (sc->ctrblk.est_blokrcvd != (unsigned) 0xffffffff)		sc->ctrblk.est_blokrcvd++;	if( eh->ether_dhost[0] & 1 ) {		sc->ctrblk.est_mbytercvd += len  ;		if (sc->ctrblk.est_mblokrcvd != (unsigned) 0xffffffff)			sc->ctrblk.est_mblokrcvd++;	}	/* Dispatch this packet */	net_read(&(sc->qe_ed), eh, m, len, (swloop != NULL), (off != 0));}/* * Watchdog timer routine. There is a condition in the hardware that * causes the board to lock up under heavy load. This routine detects * the hang up and restarts the device. */qewatch(){	register struct qe_softc *sc;	register int i;#ifdef mips	volatile struct qedevice *addr; /* dallas */#endif mips#ifdef vax	register struct qedevice *addr; /* dallas */#endif vax	register int s;			/* dallas */	int inprogress=0;	for( i=0 ; i<nNQE ; i++ ) {		sc = qe_softc[i];		addr = sc->addr; /* dallas */		if( sc->timeout ) {			if( ++sc->timeout > 3 ) {				/*				 * Check for the reason the transmit timed out				 */				if( addr->qe_csr & QE_RL_INVALID) {					/*					 * Transmit timed out because no recv					 * buffers available, so must now					 * process the recv ring.  Set a fail					 * safe just in case we have been					 * here before, cleared in qetint().					 */					if (sc->qe_rl_invalid)						qerestart( sc );					else {						++sc->qe_rl_invalid;						sc->timeout = 0;						timeout( qewatch, 0, QE_TIMEO);							s = splimp();						qerint( i );						splx( s ); 					}				} else					qerestart( sc );			} else 				inprogress++;		}	}	if( inprogress ){		timeout(qewatch, 0, QE_TIMEO);		qewatchrun++;	} else		qewatchrun=0;}/* * Restart for board lockup problem. */int qe_restarts;qerestart( sc )	register struct qe_softc *sc;{	register struct ifnet *ifp = &sc->is_if;#ifdef mips	volatile struct qedevice *addr = sc->addr;#endif mips#ifdef vax 	register struct qedevice *addr = sc->addr;#endif vax	register struct qe_ring *rp;	register int i;	register struct ifxmt *ifxp;	int s;	/* dallas */	qe_restarts++;	s = splimp();	/* Raise our priority so when we reset it does not			 * interrupt us while we are fooling with the rings.			 */	addr->qe_csr = QE_RESET;	sc->timeout = 0;	qesetup( sc );        addr->qe_csr &= ~QE_RESET;	for(i = 0, rp = sc->tring; i<nNXMT ; rp++, i++ ){		rp->qe_flag = rp->qe_status1 = QE_NOTYET;		rp->qe_valid = 0;		ifxp = &sc->qeuba.ifu_w[i];		if( ifxp->x_xtofree ) {			m_freem( ifxp->x_xtofree );			ifxp->x_xtofree = 0;		}	}	sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;	if ( ifp->if_flags & IFF_LOOPBACK )		addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ELOOP;	else		addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP;	ifp->if_flags &= ~IFF_OACTIVE;	addr->qe_rcvlist_lo = (short)sc->rringaddr;	addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16);	for( i = 0 ; sc != qe_softc[i] ; i++ )		;	qestart( i );	splx( s );	/* dallas */	if (qe_show_restarts)		printf("qerestart: restarted qe%d %d\n", i, qe_restarts);	else		mprintf("qerestart: restarted qe%d %d\n", i, qe_restarts);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -