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

📄 if_ln.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	}			while (totlen > 0) {		MGET(m, M_DONTWAIT, MT_DATA);		if (m == 0) {			m_freem(top);			m_freem(tp);			return (0);		}		len = totlen;		if (len >= 512) {					struct mbuf *p;			MCLGET(m, p);			if (p == 0)				goto nopage;			m->m_len = len;				goto copy;		}nopage:		m->m_len = MIN(MLEN, len);		m->m_off = MMINOFF;copy:		lrbptr = lnsw->ln_cpyinb(sc, lrbptr,			mtod(m, caddr_t),(unsigned)m->m_len, 0);next_m:		*mp = m;		mp = &m->m_next;		totlen -= m->m_len;	}		*mp = tp;	#ifdef mips	wbflush();#endif	return (top);}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */lnread(sc, rlbuf, len, swloop, index)	register struct ln_softc *sc;	register char *rlbuf;	int len,index;	struct mbuf *swloop;{	register struct ether_header *eptr, eh;	register struct lnsw *lnsw = sc->lnsw;	/* ptr to switch struct */    	struct mbuf *m, *swloop_tmp1;	struct protosw *pr;	int off, resid;	struct ifqueue *inq;	/*	 * 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) {		eptr = mtod(swloop, struct ether_header *);		eh = *eptr;		eptr = &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;		}	} else {		if ( lnsw->ln_dodma && (m= sc->rmbuf[index]) &&sc->dma[index] ) {                      	eptr = mtod(m, struct ether_header *);                       	m->m_off += sizeof( struct ether_header );		} else {				if ( lnsw->ln_dodma && !m ) 	 			/* Couldn't get an mbuf */				return;			eptr = &eh;			rlbuf = lnsw->ln_cpyinb(sc, rlbuf, eptr, sizeof(struct ether_header), 0);		}		/*		 * Done with ether_header; drop len		 */		len -= sizeof(struct ether_header);	} 	if (!(sc->is_if.if_flags & IFF_PROMISC) ) { 	/*	 * Make sure our multicast address filter doesn't hand us	 * up something that doesn't belong to us!	 */	  if ((eptr->ether_dhost[0] & 1) && (bcmp ((caddr_t)eptr->ether_dhost,	          (caddr_t)etherbroadcastaddr,MULTISIZE))) {	    int i;	    for (i = 0; i < sc->nmulti; i++) {		if (sc->muse[i] &&		    !(bcmp (&sc->multi[i],eptr->ether_dhost,MULTISIZE)))			break;	    }	    if (i == sc->nmulti ) { 			if ( lnsw->ln_dodma ) 				m_freem(sc->rmbuf[index]);			return;			}		}	}	sc->is_if.if_ipackets++;	eptr->ether_type = ntohs((u_short)eptr->ether_type);	if ((eptr->ether_type >= ETHERTYPE_TRAIL &&	    eptr->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)) {		off = (eptr->ether_type - ETHERTYPE_TRAIL) * 512;		if (off >= ETHERMTU) {			if ( lnsw->ln_dodma ) 				m_freem(sc->rmbuf[index]);			return;		/* sanity */		}		if (swloop) {			struct mbuf *mprev, *m0 = swloop;			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;			eptr->ether_type = ntohs( *mtod(swloop, u_short *));			m = m_copy(swloop, 0, M_COPYALL);			m_freem(swloop);		} else {		 	if(m = lnsw->lnget(sc, rlbuf, len, off, index)) {		     		eptr->ether_type =					ntohs( *mtod(m, u_short *));					resid = ntohs( *(mtod(m, u_short *)+1));				if (off + resid > len) {					if ( lnsw->ln_dodma ) 						m_freem(sc->rmbuf[index]);					 return;		/* sanity */					}				len = off + resid;			}				else /* can't get mbuf */				return;		}	} else {		off = 0;	/*	 * Pull packet off interface.  Off is nonzero if packet	 * has trailing header; lnget 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 {			if(lnsw->ln_dodma && sc->dma[index])				m->m_len = len;			else				m = lnsw->lnget(sc, rlbuf, len, off, index);		}	}	if (m == 0) {		return;	}	if (off) {		m->m_off += 2 * sizeof (u_short);		m->m_len -= 2 * sizeof (u_short);	}	/*	 * Bump up 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->ctrblk.est_bytercvd += len ;	if (sc->ctrblk.est_blokrcvd != (unsigned) 0xffffffff)		sc->ctrblk.est_blokrcvd++;	if( eptr->ether_dhost[0] & 1 ) {		sc->ctrblk.est_mbytercvd += len ;		if (sc->ctrblk.est_mblokrcvd != (unsigned) 0xffffffff)			sc->ctrblk.est_mblokrcvd++;	}        /* Dispatch this packet */	/* is_ed really is ifp alias arpcom alias ether_driver... */        net_read(&(sc->is_ed), eptr, m, len, (swloop != NULL), (off != 0));}/* * lntint hasn't been called in a while, so restart chip, * and reset timer. */lnwatch(unit)int unit;{	register struct ln_softc *sc = ln_softc[unit]; 	register struct ifnet *ifp = &sc->is_if;	int s;	s=splimp();        smp_lock(&sc->lk_ln_softc, LK_RETRY);	ifp->if_timer = 0;	sc->ln_debug.trfull++;		smp_unlock(&sc->lk_ln_softc);	lnrestart(ifp);	lninit(ifp->if_unit);	splx(s);}/* * Allocate a chunk of local RAM buffer. Since we never * give Local RAM buffer memory back, we'll just step up the * byte-count on a per-unit basis. (16 bits on 32 bit boundary) */caddr_tln_alloc16 (sc, size, align)	register struct ln_softc *sc;	int size;	int align;{	register int tmpoff = sc->lrb_offset;	register int tmpoff1;	/*	 * Start out on the first "align" boundary	 */	if (align) {		tmpoff1 = svtolance16(sc->ln_lrb) + tmpoff;		while ((tmpoff1&((align*2))) &&			tmpoff < LN_LRB_SIZE)			{ 			tmpoff += ((tmpoff1&0x01) ? 3 : 1);			tmpoff1 += ((tmpoff1&0x01) ? 3 : 1);		}	}	if ((int)LRBADDR(tmpoff,size) < LN_LRB_SIZE) {		sc->lrb_offset = (int)LRBADDR(tmpoff,size);		return ((caddr_t)((int)sc->ln_lrb + tmpoff));	}	else		return (0);}/* * Allocate a chunk of local RAM buffer. Since we never * give Local RAM buffer memory back, we'll just step up the * byte-count on a per-unit basis. (32 bits wide) */caddr_tln_alloc32 (sc, size, align)	register struct ln_softc *sc;	int size;	int align;{	register int tmpoff = sc->lrb_offset;	register int tmpoff1 ; 	/*	 * Start out on the first "align" boundary	 */	if (align) {		tmpoff1 = svtolance32(sc->ln_lrb) + tmpoff ;			while ((tmpoff1&(align)) && tmpoff < LN_LRB_SIZE)			{			tmpoff++;			tmpoff1++ ;		}	}	if ((int)(tmpoff+size) < LN_LRB_SIZE) {		sc->lrb_offset = (int)(tmpoff+size);		return ((caddr_t)((int)sc->ln_lrb + tmpoff));	}	else		return (0);}caddr_tln_alloc4x4 (sc, size, align)	register struct ln_softc *sc;	int size;	int align;{	register int tmpoff = sc->lrb_offset;	register int tmpoff1 ; 	/* Alloc routine for buffers only.  Each buffer has 4 good words	 * followed by 4 unused words, then 4 good, etc.  To save space,	 * use the 4 unused words for the next buffer to be alloc'd, thus	 * they will be alternating.	 */	if (sc->rring[0] == NULL)	  /* allocing the 1st one */		align = LN_OCTA_ALIGN;	/*	 * Start out on the first octaword aligned boundary	 */	if (align) {		tmpoff1 = sc->lnsw->ln_svtolance(sc->ln_lrb) +tmpoff ;			while ((tmpoff1&(align)) && tmpoff < LN_LRB_SIZE)			{			tmpoff++;			tmpoff1++ ;		}	}	if (((int)sc->ln_lrb + tmpoff) & 0x10)	/* 5th bit set */		sc->lrb_offset = (int)(tmpoff+16);/* next time use altrn space */	else		if ((int)(tmpoff+(size * 2)) < LN_LRB_SIZE) 			sc->lrb_offset = (int)(tmpoff + (size * 2) - 16); 		else return (0);	return ((caddr_t)((int)sc->ln_lrb + tmpoff));}/* * Zero "len" bytes of Local RAM buffer */ln_bzero16 (addr, len)	register char *addr;	register int len;{	register int i;	register caddr_t lrbptr =  addr;	if (len) {		if ((u_long)lrbptr & 0x01) {			*(u_long *)(lrbptr - 1) &= (u_short)0xff;			lrbptr +=3;			len--;		}		for (i = 0; i < (len - 1); i += sizeof(u_short)) {			*(u_long *)lrbptr = (u_short)0;			lrbptr += sizeof(u_long);		}		if (i != len)			*(u_long *)lrbptr &= (u_short)0xff00;	}}/* * Zero "len" bytes of Local RAM buffer */ln_bzero32 (addr, len)	register char *addr;	register int len;{	if (len) 		bzero(addr, len);}ln_bzero4x4 (addr, len )	register char *addr;	register int len;{	register tmp1;	register caddr_t lrbptr = addr;	register end4word;	int i;	/* bzero routine for ring buffers only */	if ((u_long) lrbptr & 0xf) {	/* start on a 4 word boundary */		end4word = (0x10 - ((u_long)lrbptr & 0xf));		tmp1 = ((len > end4word) ? end4word : len);		bzero(lrbptr, tmp1);		len -= tmp1;                lrbptr += tmp1;                if (((u_long)lrbptr & 0xf) == 0)                        lrbptr += 0x10;	}	/* bzero in 4 word boundaries, skipping every 4 words */	tmp1 = (len >> 4);	for (i=0; i < tmp1; i++) {		bzero(lrbptr,16);		lrbptr += 32;	}	len -= (tmp1 << 4);	/* now the left over */	if (len) 		bzero(lrbptr, len);}/* * Convert a system virtual address to the appropriate addressing * scheme as seen by the LANCE chip for a 32 bit wide buffer.  */svtolance32 (virt)	caddr_t	virt;{	register int off, phy,base ;	phy = (int)(svtophy(virt));	off = phy & (LN_LRB_SIZE-1);	/* Byte offset from base of LRB */        base = ((phy & ~(LN_LRB_SIZE-1)) & 0xffffff); /* LRB base addr. */	return (off+base);}/* * Convert a system virtual address to the appropriate addressing * scheme as seen by the LANCE chip for a 16 bit wide buffer. */svtolance16 (virt)	caddr_t	virt;{	register int off, phy, tmp;	phy = (int)(svtophy(virt));	off = phy & (LN_LRB_SIZE-1);	/* Byte offset from base of LRB */	tmp = off/2;	return ((off == tmp*2) ? tmp : tmp+1);}/* * Specialized "bcopy" to move len bytes from * 16-bit wide by 32-bit aligned local RAM buffer. * Loop does up to 32 short-word moves in a single * shot until the buffer is depleted. Off is non-zero * if we wish to begin copying off-many bytes beyond * "from". */caddr_tln_cpyin16(sc,from,to,len,off)struct ln_softc *sc;caddr_t from;caddr_t to;int len, off;{	register caddr_t lrbptr = LRBADDR(from, off);	register caddr_t dp = to;	register int tmp0, tmp1;	tmp0 = (unsigned)len;	if (sc->lnsw->ln_dma) 	  /* no read thru caching */		clean_dcache(PHYS_TO_K0(svtophy(lrbptr)),len*2);	if ((u_long)lrbptr & 0x01) {		/* Start LRB on even short-word boundary */		*dp++ = *lrbptr;		lrbptr += 3;		tmp0--;	}	while (tmp0) {		switch (tmp1 = (tmp0 >> 1)) {		default:		case 32:			tmp1 = 32;			*(u_short *)(dp+62) = *(u_long *)(lrbptr+124);		case 31:			*(u_short *)(dp+60) = *(u_long *)(lrbptr+120);		case 30:			*(u_short *)(dp+58) = *(u_long *)(lrbptr+116);		case 29:			*(u_short *)(dp+56) = *(u_long 

⌨️ 快捷键说明

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