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

📄 if_ln.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
			lninit(ifp->if_unit);			return;		}		/*		 * Find the index of the last descriptor in this		 * packet (LN_OWN clear and LN_ENP set). If cannot		 * find it then Lance is still working.		 */		ring_cnt=1;		while (((rp->ln_flag &		         (LN_RT_ERR|LN_OWN|LN_ENP)) == 0) &&			 (ring_cnt++ <= nLNNRCV)) {			index = ++index % nLNNRCV;			lnsw->ln_cpyin(sc, sc->rring[index],&rp->ln_flag,				       sizeof(u_char),(u_long)&rp->ln_flag - (u_long)rp);		}		/*		 * more than one; re-init the descriptors involved and		 * ignore this packet. (May have to bump up DECnet counters).		 */		if (ring_cnt > 1) {			/*			 * Went all the way around, wait			 */			if (ring_cnt > nLNNRCV) {				if (lndebug)					mprintf("ln%d: recv ring_cnt exceeded\n",unit);				break;			}			/*			 * "free" up the descriptors, but really just use			 * them over again.  Give them back to the Lance			 * using the same local RAM buffers. IF ERROR INFO.			 * IS SET, WAIT!			 */			if (!(rp->ln_flag & LN_RT_ERR)) {				lnsw->ln_setflag(sc->rring[first], LN_OWN);				while ( first != index ) {					first = ++first % nLNNRCV;					lnsw->ln_setflag(sc->rring[first], LN_OWN);				}				if (lndebug)					mprintf("ln%d: chained receive packet dropped\n",unit);				continue;			}		}		/*		 * Is it a valid descriptor, ie.		 * we own the descriptor (LN_OWN==0),		 * and end of packet (ENP) set?		 */		if ( (rp->ln_flag & ~LN_STP) == LN_ENP) {			lnsw->ln_cpyin(sc, sc->rring[index],&rp->ln_flag2,				       sizeof(u_short),(u_long)&rp->ln_flag2 - (u_long)rp);			/* len here includes the 4 CRC bytes */			len = (rp->ln_flag2 & LN_MCNT);			lnread(sc, sc->rlbuf[index], len-4, 0, index);			/*			 * If we're on an architecture which provides DMA,			 * re-initialize the descriptor to get a new buf.			 */			if (lnsw->ln_dodma)				lnsw->lninitdesc (sc, sc->rring[index],					&sc->rlbuf[index], LNNOALLOC,index);			/*			 * "free" up the descriptors. Turn ownership back			 * back to LANCE.			 */			lnsw->ln_setflag(sc->rring[first], LN_OWN);		/*		 * else Not a good packet sequence, check for receiver errors		 */		} else if ((flag = rp->ln_flag) & LN_RT_ERR){			sc->is_if.if_ierrors++;			if (flag & (LN_OFLO | LN_CRC | LN_FRAM | LN_RBUFF)) {				if (lndebug)					mprintf("ln%d: recv err %02x\n",unit, flag&0xff);				if (sc->ctrblk.est_recvfail != 0xffff) {					sc->ctrblk.est_recvfail++;					if (flag & LN_OFLO) {						sc->ctrblk.est_recvfail_bm |= 4;#if NPACKETFILTER > 0                                           	sc->is_ed.ess_missed++;#endif NPACKETFILTER > 0					}					if (flag & LN_CRC) {				    		sc->ctrblk.est_recvfail_bm |= 1;					}					if (flag & LN_FRAM) {					    	sc->ctrblk.est_recvfail_bm |= 2;					}					if (flag & LN_RBUFF) {				    		; /* causes LN_OFLO to be set */					}				}			} else {				if (lndebug)					mprintf("ln%d: stray recv err %02x\n",unit,flag&0xff);			}			/*			 * "free" up the descriptors, but really just use			 * them over again.  Give them back to the Lance			 * using the same pre-allocated mbufs.			 */			lnsw->ln_setflag(sc->rring[first], LN_OWN);			while ( first != index ) {				first = ++first % nLNNRCV;				/* give away */				lnsw->ln_setflag(sc->rring[first], LN_OWN);			}		} else {			/*  else:			 *   - not a good packet, 			 *   - not an error situation,			 *			 * This can happen if we beat the Lance to the			 * end of a valid list of receive buffers -- the			 * Lance hasn't relinquished the last buffer (one			 * with ENP set) or we just found a buffer still			 * owned by Lance, without finding the ENP bit.			 * In either case, just return.  We can pick up			 * the unfinished chain on the next interrupt.			 */                        smp_unlock(&sc->lk_ln_softc);			return;		}	}        smp_unlock(&sc->lk_ln_softc);}/* * Start output on interface. * *//* SMP - call with device lock already set.  us.  */lnstart(unit)int	unit;{	register struct ln_softc *sc = ln_softc[unit];	register struct mbuf *m;	register int dp; 	/* data buffer pointer */	register struct ln_ring *rp = &sc->ln_ring;	register struct lnsw *lnsw = sc->lnsw;	int tlen;	int index;	register struct ifnet *ifp = &sc->is_if;        /* s = splimp(); */  /* SMP */	for (index = sc->tindex;	     sc->nxmit < (nLNNXMT - 1);	     sc->tindex = index = ++index % nLNNXMT) {		/*		 * Dequeue the transmit request, if any.		 */		IF_DEQUEUE(&sc->is_if.if_snd, m);		if (m == 0) {			return;		/* Nothing on the queue	*/		}			/*		 * "lnput" pads out anything less than "MINDATA" with NULL's		 */		tlen = lnput(sc, index, m);		dp = lnsw->ln_svtolance(sc->tlbuf[index]);		rp->ln_buf_len = -(tlen) | 0xf000;		rp->ln_addr_lo = (short)dp & 0xffff;		rp->ln_addr_hi =			         (short)(((int)dp >> 16) & 0xff);		rp->ln_flag = ( LN_STP | LN_OWN | LN_ENP);		lnsw->ln_cpyout(rp,sc->tring[index],sizeof(struct ln_ring),0);		sc->ln_rap = LN_CSR0;		sc->ln_rdp = ( LN_TDMD | LN_INEA );		sc->nxmit++;		ifp->if_flags |= IFF_OACTIVE;		/*		 * Accumulate statistics for DECnet		 */		if ((sc->ctrblk.est_bytesent + tlen) > sc->ctrblk.est_bytesent)			sc->ctrblk.est_bytesent += tlen;		if (sc->ctrblk.est_bloksent != (unsigned)0xffffffff)			sc->ctrblk.est_bloksent++;		sc->is_if.if_timer = 5;	}}/* * Process an ioctl request. */lnioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ln_softc *sc = ln_softc[ifp->if_unit];	register struct ln_initb *initb = &sc->ln_initb;	register int i;	struct ifreq *ifr = (struct ifreq *)data;	struct ifdevea *ifd = (struct ifdevea *)data;	struct ctrreq *ctr = (struct ctrreq *)data;	struct protosw *pr;	struct ifaddr *ifa = (struct ifaddr *)data;	int bitpos;		/* top 6 bits of crc = bit in multicast mask */	u_short newmask[4];	/* new value of multicast address mask */	int j = -1, s, error=0;	s = splimp();	switch (cmd) {	case SIOCENABLBACK:		if (lndebug>1) printf("SIOCENABLBACK ");		printf("ln: internal loopback requested\n");                smp_lock(&sc->lk_ln_softc, LK_RETRY);		/* set external loopback */		initb->ln_mode &= ~LN_INTL;		initb->ln_mode |= LN_LOOP;                smp_unlock(&sc->lk_ln_softc);		lnrestart( ifp );		ifp->if_flags |= IFF_LOOPBACK;		lninit( ifp->if_unit );		break; 	case SIOCDISABLBACK:		if (lndebug>1) printf("SIOCDISABLBACK ");		printf("ln: internal loopback disable requested\n");                smp_lock(&sc->lk_ln_softc, LK_RETRY);		/* disable external loopback */		initb->ln_mode &= ~LN_INTL;		initb->ln_mode &= ~LN_LOOP;                smp_unlock(&sc->lk_ln_softc);		lnrestart( ifp );		ifp->if_flags &= ~IFF_LOOPBACK;		lninit( ifp->if_unit );		break; 	case SIOCRPHYSADDR:		/*		 * read default hardware address.		 */		if (lndebug>1) printf("SIOCRPHYSADDR ");                smp_lock(&sc->lk_ln_softc, LK_RETRY);		bcopy(sc->is_addr, ifd->current_pa, 6);		for ( i=0 ; i<6 ; i++ ) {			ifd->default_pa[i] =			(u_char)((sc->ln_narom[i]>>sc->lnsw->ln_na_align)&0xff);		}                smp_unlock(&sc->lk_ln_softc);		break; 	case SIOCSPHYSADDR:		if (lndebug>1) printf("SIOCSPHYSADDR ");                smp_lock(&sc->lk_ln_softc, LK_RETRY);		bcopy(ifr->ifr_addr.sa_data, sc->is_addr, 6);#ifdef NPACKETFILTER > 0                pfilt_newaddress(sc->is_ed.ess_enetunit, sc->is_addr);#endif NPACKETFILTER > 0		/*		 * fill in the initb station address, and restart.		 */		for (i=j=0; i < 3; i++, j += 2) {			initb->ln_sta_addr[i] = 				(short)(sc->is_addr[j]&0xff);			initb->ln_sta_addr[i] |= 				(short)((sc->is_addr[j+1]&0xff)<<8);		}	        smp_unlock(&sc->lk_ln_softc);		if (ifp->if_flags & IFF_RUNNING) {			lnrestart(ifp);			lninit(ifp->if_unit);		} else {			lnrestart(ifp);		}		break;	case SIOCDELMULTI:	case SIOCADDMULTI:                smp_lock(&sc->lk_ln_softc, LK_RETRY);		if (cmd == SIOCDELMULTI) {			if (lndebug>1) printf("SIOCDELMULTI ");			for (i = 0; i < sc->nmulti; i++)				if (bcmp(&sc->multi[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) {					if (--sc->muse[i] == 0) {						bcopy(ln_sunused_multi,&sc->multi[i],MULTISIZE);					}					if (lnshowmulti) printf("%d deleted.\n",i);				}		} else {			if (lndebug>1) printf("SIOCADDMULTI ");			for (i = 0; i < sc->nmulti; i++) {				if (bcmp(&sc->multi[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) {					sc->muse[i]++;					if (lnshowmulti) printf("already using index %d\n", i);                			smp_unlock(&sc->lk_ln_softc);					goto done;				}				if (bcmp(&sc->multi[i],ln_sunused_multi,MULTISIZE) == 0)					j = i;			}			/*			 * j is initialized to -1; if j > 0, then			 * represents the last valid unused location			 * in the multicast table.			 */			if (j == -1) {				if (sc->nmulti == nLNMULTI) {					printf("ln: SIOCADDMULTI failed, multicast list full: %d\n",nLNMULTI);					error = ENOBUFS;                			smp_unlock(&sc->lk_ln_softc);					goto done;				} else {					j = sc->nmulti++;				}			}			bcopy(ifr->ifr_addr.sa_data, &sc->multi[j], MULTISIZE);			sc->muse[j]++;			if (lnshowmulti)				printf("added index %d.\n", j);		}		/*		 * Recalculate all current multimask crc/bits		 * and reload multimask info.		 *		 * For each currently used multicast address,		 * calculate CRC, save top 6 bits, load		 * appropriate mask bit into newmask[i]		 */		for (i=0; i<4; i++)			newmask[i] = 0x0000;		for (i=0; i<sc->nmulti; i++) {			if (sc->muse[i] == 0)				continue;			/* returns 32-bit crc in global variable _ln_crc */			ln_docrc(&sc->multi[i], 0, sc);			bitpos = ((unsigned int)sc->ln_crc >> 26) & 0x3f;			if (lnshowmulti)				printf("crc=%x, bit=%d.\n",sc->ln_crc,bitpos);			/* 0-15 */			if (bitpos >= 0 && bitpos < 16)				newmask[0] |= (1 << (bitpos - 0));			/* 16-31 */			else if (bitpos < 32)				newmask[1] |= (1 << (bitpos - 16));			/* 32-47 */			else if (bitpos < 48)				newmask[2] |= (1 << (bitpos - 32));			/* 48-63 */			else if (bitpos < 64)				newmask[3] |= (1 << (bitpos - 48));			else {				if (lndebug || lnshowmulti)					printf("ln: bad crc, bitpos=%d.\n", bitpos);			}		}		i = 0;		for (i = 0; i < 4; i++)			initb->ln_multi_mask[i] =			                           newmask[i] & 0xffff;		if (lnshowmulti) {		    printf("new 64-bit multimask= %04x %04x %04x %04x\n",			newmask[0], newmask[1], newmask[2], newmask[3]);		}                smp_unlock(&sc->lk_ln_softc);		if (ifp->if_flags & IFF_RUNNING) {			lnrestart(ifp);			lninit(ifp->if_unit);		} else {			lnrestart(ifp);		}		break;	case SIOCRDCTRS:	case SIOCRDZCTRS:		if (lndebug>1) printf("SIOCRDCTRS ");		ctr->ctr_ether = sc->ctrblk;		ctr->ctr_type = CTR_ETHER;		ctr->ctr_ether.est_seconds = (time.tv_sec - sc->ztime) > 0xfffe ? 0xffff : (time.tv_sec - sc->ztime);		if (cmd == SIOCRDZCTRS) {			if (lndebug>1) printf("SIOCRDZCTRS ");                	smp_lock(&sc->lk_ln_softc, LK_RETRY); 			sc->ztime = time.tv_sec;			bzero(&sc->ctrblk, sizeof(struct estat));                	smp_unlock(&sc->lk_ln_softc); 		}		break;	case SIOCSIFADDR:		if (lndebug>1) printf("SIOCSIFADDR ");		if (!(ifp->if_flags & IFF_RUNNING)) {			lninit(ifp->if_unit);			ifp->if_flags |= IFF_UP;		}		switch(ifa->ifa_addr.sa_family) {#ifdef INET		case AF_INET:			((struct arpcom *)ifp)->ac_ipaddr =				IA_SIN(ifa)->sin_addr;			/*			 * DISABLE			 */			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);			break;#endif		default:			if (pr=iffamily_to_proto(ifa->ifa_addr.sa_family)) {				error = (*pr->pr_ifioctl)(ifp, cmd, data);			}			break;		}		break;        case SIOCSIFFLAGS:		if (lndebug > 1) printf("SIOCSIFFLAGS ");		/*		 * If promisuous mode is enabled/disabled restart		 * to change LANCE mode	 	 */                smp_lock(&sc->lk_ln_softc, LK_RETRY);		if ((ifp->if_flags & IFF_PROMISC) &&		    !(initb->ln_mode & LN_PROM)) {			/* should be in promiscuous mode */			initb->ln_mode |= LN_PROM;		} else if (!(ifp->if_flags & IFF_PROMISC)) {			/* should not be in promiscuous mode */			initb->ln_mode &= ~LN_PROM;		}                 smp_unlock(&sc->lk_ln_softc); 		if (ifp->if_flags & IFF_RUNNING) {			lnrestart(ifp);			lninit(ifp->if_unit);		} else {			lnrestart(ifp);		}		break;	default:		error = EINVAL;	}done:	splx(s);	return (error);}/* * Calculate 32-bit CRC (AUTODIN-II) for the given 48-bit * multicast address.  The CRC table must first be initialized * for the vax crc instruction to work.  The crc is returned in * variable ln_crc. */ln_docrc(addr, flag, sc)	struct ln_multi *addr;	int flag;

⌨️ 快捷键说明

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