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

📄 if_de.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
		ds->ds_nxmit = nxmit;		ds->ds_if.if_flags |= IFF_OACTIVE;		if (ds->ds_flags & DSF_RUNNING)			addr->pclow = PCSR0_INTE|CMD_PDMD;	}	else if (ds->ds_nxmit == NXMT) {  /* LSC002 */		/*		 * poke device if we have something to send and 		 * transmit ring is full. 		 */		if (dedebug) { 			rp = &ds->ds_xrent[0];			mprintf("did not xmt: %d, %d, %d, flag0=%x, flag1=%x\n", ds->ds_xindex, ds->ds_nxmit, ds->ds_xfree, rp++->r_flags, rp->r_flags);		}		if (ds->ds_flags & DSF_RUNNING)			addr->pclow = PCSR0_INTE|CMD_PDMD;	}		}/* * Command done interrupt. */deintr(unit)	int unit;{	struct uba_device *ui = deinfo[unit];	register struct dedevice *addr = (struct dedevice *)ui->ui_addr;	register struct de_softc *ds = &de_softc[unit];	register struct de_ring *rp;	register struct ifxmt *ifxp;	short csr0;	int s;	s = splimp(); /* SMP */	smp_lock(&ds->lk_de_softc, LK_RETRY);	/* save flags right away - clear out interrupt bits */	csr0 = addr->pcsr0;	addr->pchigh = csr0 >> 8;	/*	 *   Error condition interrupts. No recovery attempted - just	 * printf and leave the interface alone.	 */	if (csr0 & PCSR0_FATI)		printf ("de%d: unsolicited state change, csr0=%b, csr1=0x%04x\n",			 unit, csr0, PCSR0_BITS, addr->pcsr1);	if (csr0 & PCSR0_SERI)		mprintf ("de%d: status error, csr0=%b\n",		         unit, csr0, PCSR0_BITS);	/*	 * if receive, put receive buffer on mbuf	 * and hang the request again	 */	if ((ds->ds_rrent[ds->ds_rindex].r_flags & RFLG_OWN) == 0)		derecv(unit);	/*	 * Poll transmit ring and check status.	 * Be careful about loopback requests.	 * Then free buffer space and check for	 * more transmit requests.	 */	for ( ; ds->ds_nxmit > 0; ds->ds_nxmit--) {		rp = &ds->ds_xrent[ds->ds_xindex];		if (rp->r_flags & XFLG_OWN)			break;		ds->ds_if.if_opackets++;		ifxp = &ds->ds_deuba.ifu_w[ds->ds_xindex];		/* check for unusual conditions */		if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {			if (rp->r_flags & XFLG_ERRS) {				/* output error */				ds->ds_if.if_oerrors++;				if (dedebug)			printf("de%d: oerror, flags=%b tdrerr=%b (len=%d)\n",				    unit, rp->r_flags, XFLG_BITS,				    rp->r_tdrerr, XERR_BITS, rp->r_slen);			} else { /* no oerrors */				if (rp->r_flags & XFLG_ONE) {				    /* one collision */				    ds->ds_if.if_collisions++;				    } else if (rp->r_flags & XFLG_MORE) {				            /* more than one collision */				            ds->ds_if.if_collisions += 2;	/* guess */				    }/*001*/			    if ( ((rp->r_flags & XFLG_MTCH) && !(ds->ds_if.if_flags & IFF_LOOPBACK)) || (ds->ds_if.if_flags & IFF_PFCOPYALL) ) {				/* received our own packet */				ds->ds_if.if_ipackets++;				if (dedebug)					mprintf("de%d: loop\n", unit);				deread(ds, &ifxp->x_ifrw,				    rp->r_slen - sizeof (struct ether_header),					ifxp->x_xtofree);				ifxp->x_xtofree = 0;				}			} /* end else no oerrors */		}		if (ifxp->x_xtofree) {			m_freem(ifxp->x_xtofree);			ifxp->x_xtofree = 0;		}		/* check if next transmit buffer also finished */		ds->ds_xindex++;		if (ds->ds_xindex == NXMT)			ds->ds_xindex = 0;	}	if (!(ds->ds_nxmit)) {		ds->ds_if.if_flags &= ~IFF_OACTIVE;		destart(unit);	}	/*	 * This may have happened for EITHER a user or system buffer	 * unavailable. In both cases, need to turn on interrupts and	 * tell the interface that receive buffers have been freed up.	 * The "de0: buffer unavailable" printf has been removed since	 * the counter block already records system and user buffer unavail.	 */	if (csr0 & PCSR0_RCBI)		addr->pclow = PCSR0_INTE|CMD_PDMD;	smp_unlock(&ds->lk_de_softc);	splx(s);}/* * Ethernet interface receiver interface. * If input error just drop packet. * Otherwise purge input buffered data path and examine  * packet to determine type.  If can't determine length * from type, then have to drop packet.  Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */derecv(unit)	int unit;{	register struct de_softc *ds = &de_softc[unit];	register struct ifnet *ifp = &ds->ds_if;	register struct de_ring *rp;	register struct ether_header *eh;	int len;	rp = &ds->ds_rrent[ds->ds_rindex];	while ((rp->r_flags & RFLG_OWN) == 0) {		ds->ds_if.if_ipackets++;		if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)			UBAPURGE(ds->ds_deuba.ifu_uba,			ds->ds_deuba.ifu_r[ds->ds_rindex].ifrw_bdp,			ds->ds_deuba.ifu_uban);		len = (rp->r_lenerr&RERR_MLEN) - sizeof (struct ether_header)			- 4;	/* don't forget checksum! */                if( ! (ifp->if_flags & IFF_LOOPBACK) ) {		/* 		 * check for errors 		 *		 * Added Bit test RERR_OVRN <bit 12>, message overrun error		 * This bit is always zero for the DEUNA so no additional test		 * are needed.		 */		    if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC))		        || (rp->r_flags&(RFLG_STP|RFLG_ENP)) != (RFLG_STP|RFLG_ENP) 		        || (rp->r_lenerr & (RERR_OVRN|RERR_BUFL|RERR_UBTO|RERR_NCHN)) ||		        len < ETHERMIN || len > ETHERMTU) {		  	    ds->ds_if.if_ierrors++;			    if (dedebug)			     printf("de%d: ierror, flags=%b lenerr=%b (len=%d)\n",				unit, rp->r_flags, RFLG_BITS, rp->r_lenerr,				RERR_BITS, len);		    } else{			deread(ds, &ds->ds_deuba.ifu_r[ds->ds_rindex], len, 0);			}                } else {                        eh = (struct ether_header *)ds->ds_deuba.ifu_r[ds->ds_rindex].ifrw_addr;                        if ( bcmp(eh->ether_dhost, ds->ds_addr, 6) == NULL ){                                deread(ds, &ds->ds_deuba.ifu_r[ds->ds_rindex], len, 0);			}                }		/* hang the receive buffer again */		rp->r_lenerr = 0;		rp->r_flags = RFLG_OWN;		/* check next receive buffer */		ds->ds_rindex++;		if (ds->ds_rindex == NRCV)			ds->ds_rindex = 0;		rp = &ds->ds_rrent[ds->ds_rindex];	}}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */deread(ds, ifrw, len, swloop)	register struct de_softc *ds;	struct ifrw *ifrw;	int len;	struct mbuf *swloop;{	struct ether_header *eh, swloop_eh;    	struct mbuf *m, *swloop_tmp1, *swloop_tmp2;	struct protosw *pr;	int off, resid;	struct ifqueue *inq;	/*	 * Deal with trailer protocol: if type is 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;		}	} else 		eh = (struct ether_header *)ifrw->ifrw_addr;	eh->ether_type = ntohs((u_short)eh->ether_type);#define	dedataaddr(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(*dedataaddr(eh, off, u_short *));			resid = ntohs(*(dedataaddr(eh, 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; deget 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 = deget(&ds->ds_deuba, ifrw, len, off);	}	if (m == 0)		return;	if (off) {		m->m_off += 2 * sizeof (u_short);		m->m_len -= 2 * sizeof (u_short);	}		/* Dispatch this packet */	net_read(&(ds->ds_ed), eh, m, len, (swloop != NULL), (off != 0));}/* * Routines supporting UNIBUS network interfaces. *//* * Init UNIBUS for interface on uban whose headers of size hlen are to * end on a page boundary.  We allocate a UNIBUS map register for the page * with the header, and nmr more UNIBUS map registers for i/o on the adapter, * doing this for each receive and transmit buffer.  We also * allocate page frames in the mbuffer pool for these pages. */de_ubainit(ifu, uban, hlen, nmr)	register struct deuba *ifu;	int uban, hlen, nmr;{	register caddr_t cp, dp;	register struct ifrw *ifrw;	register struct ifxmt *ifxp;	int i, ncl;	ncl = clrnd(nmr + CLSIZE) / CLSIZE;	if (ifu->ifu_r[0].ifrw_addr)		/*		 * If the first read buffer has a non-zero		 * address, it means we have already allocated core		 */		cp = ifu->ifu_r[0].ifrw_addr - (CLBYTES - hlen);	else {		cp = m_clalloc(NTOT * ncl, MPG_SPACE);		if (cp == 0)			return (0);		ifu->ifu_hlen = hlen;		ifu->ifu_uban = uban;		ifu->ifu_uba = uba_hd[uban].uh_uba;		dp = cp + CLBYTES - hlen;		for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {			ifrw->ifrw_addr = dp;			dp += ncl * CLBYTES;		}		for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {			ifxp->x_ifrw.ifrw_addr = dp;			dp += ncl * CLBYTES;		}	}	/* allocate for receive ring */	for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++) {		if (de_ubaalloc(ifu, ifrw, nmr) == 0) {			struct ifrw *rw;			for (rw = ifu->ifu_r; rw < ifrw; rw++)				ubarelse(ifu->ifu_uban, &rw->ifrw_info);			goto bad;		}	}	/* and now transmit ring */	for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[NXMT]; ifxp++) {		ifrw = &ifxp->x_ifrw;		if (de_ubaalloc(ifu, ifrw, nmr) == 0) {			struct ifxmt *xp;			for (xp = ifu->ifu_w; xp < ifxp; xp++)				ubarelse(ifu->ifu_uban, &xp->x_ifrw.ifrw_info);			for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[NRCV]; ifrw++)				ubarelse(ifu->ifu_uban, &ifrw->ifrw_info);			goto bad;		}		for (i = 0; i < nmr; i++)			ifxp->x_map[i] = ifrw->ifrw_mr[i];		ifxp->x_xswapd = 0;	}	return (1);bad:	m_pgfree(cp, NTOT * ncl);	ifu->ifu_r[0].ifrw_addr = 0;	return(0);}/* * Setup either a ifrw structure by allocating UNIBUS map registers, * possibly a buffered data path, and initializing the fields of * the ifrw structure to minimize run-time overhead. */staticde_ubaalloc(ifu, ifrw, nmr)	struct deuba *ifu;	register struct ifrw *ifrw;	int nmr;{	register int info;	info =	    uballoc(ifu->ifu_uban, ifrw->ifrw_addr, nmr*NBPG + ifu->ifu_hlen,	        ifu->ifu_flags);	if (info == 0)		return (0);	ifrw->ifrw_info = info;	ifrw->ifrw_bdp = UBAI_BDP(info);	ifrw->ifrw_proto = UBAMR_MRV | (UBAI_BDP(info) << UBAMR_DPSHIFT);	ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[UBAI_MR(info) + 1];	return (1);}/* * Pull read data off a interface. * Len is length of data, with local net header stripped. * Off is non-zero if a trailer protocol was used, and * gives the offset of the trailer information. * We copy the trailer information and then all the normal * data into mbufs.  When full cluster sized units are present * on the interface on cluster boundaries we can get them more * easily by remapping, and take advantage of this here. */struct mbuf *deget(ifu, ifrw, totlen, off0)	register struct deuba *ifu;	register struct ifrw *ifrw;	int totlen, off0;{	struct mbuf *top, **mp, *m;	int off = off0, len;	register caddr_t cp = ifrw->ifrw_addr + ifu->ifu_hlen;	top = 0;	mp = &top;	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) { /* For now only 1 cluster */				      /* May ultimately fix mapping */			struct mbuf *p;			struct pte *cpte, *ppte;			int x, *ip, i;			MCLGET(m, p);			if (p == 0)				goto nopage;			len = m->m_len = CLBYTES;			if (!claligned(cp))				goto copy;			/* faster just to copy in SMP case since 			   we would have to sync up TB's */			if (smp)				goto copy;			/*			 * Switch pages mapped to UNIBUS with new page p,			 * as quick form of copy.  Remap UNIBUS and invalidate.			 */			cpte = &kmempt[mtocl(cp)];			ppte = &kmempt[mtocl(p)];			x = btop(cp - ifrw->ifrw_addr);			ip = (int *)&ifrw->ifrw_mr[x];			for (i = 0; i < CLSIZE; i++) {				struct pte t;				t = *ppte; *ppte++ = *cpte; *cpte = t;				*ip++ =				    cpte++->pg_pfnum|ifrw->ifrw_proto;				mtpr(TBIS, cp);				cp += NBPG;				mtpr(TBIS, (caddr_t)p);				p += NBPG / sizeof (*p);			}			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;

⌨️ 快捷键说明

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