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

📄 if_qe.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifdef mips 					/*					 * Flush the cache memory for the					 * receiver ring buffer					 */					clean_dcache(PHYS_TO_K0(svtophy(sc->qeuba.ifu_r[sc->rindex].ifrw_addr)),len);#endif mips					qeread(sc, &sc->qeuba.ifu_r[sc->rindex],						len - sizeof(struct ether_header),0);				}			}		} else {#ifdef mips 			/*			 * Flush the cache memory for the			 * receiver ring buffer			 */			clean_dcache(PHYS_TO_K0(svtophy(sc->qeuba.ifu_r[sc->rindex].ifrw_addr)),len);#endif mips			eh = (struct ether_header *)sc->qeuba.ifu_r[sc->rindex].ifrw_addr;			if ( bcmp(eh->ether_dhost, sc->is_addr, 6) == NULL )					qeread(sc, &sc->qeuba.ifu_r[sc->rindex],						len - sizeof(struct ether_header),0);		}		/*		 * Return the buffer(s) to the ring. Only have multiple		 * buffers on chained packets.		 */drop:		bufaddr = sc->qeuba.ifu_r[sc->rindex].ifrw_info & mask;		rp->qe_buf_len = -((MAXPACKETSIZE)/2);		rp->qe_addr_lo = (short)bufaddr;		rp->qe_addr_hi = (short)((int)bufaddr >> 16);		rp->qe_flag = rp->qe_status1 = QE_NOTYET;		rp->qe_valid = 1;		if (sc->rindex != last) {			sc->rindex = ++sc->rindex % nNRCV;			goto drop;		}	}}/* * Process an ioctl request. */qeioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	struct qe_softc *sc = qe_softc[ifp->if_unit];	struct uba_device *ui = qeinfo[ifp->if_unit];	struct qedevice *addr = (struct qedevice *)ui->ui_addr;	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 i,j = -1,s = splimp(), error = 0;	switch (cmd) {	case SIOCENABLBACK:		printf("qe%d: internal loopback enable requested\n", ifp->if_unit);                ifp->if_flags |= IFF_LOOPBACK;#ifdef notdef		if((ifp->if_flags |= IFF_LOOPBACK) & IFF_RUNNING)			if_rtinit(ifp, -1);#endif		qerestart( sc );		break; 	case SIOCDISABLBACK:		printf("qe%d: internal loopback disable requested\n", ifp->if_unit);                ifp->if_flags &= ~IFF_LOOPBACK;#ifdef notdef		if((ifp->if_flags &= ~IFF_LOOPBACK) & IFF_RUNNING)			if_rtinit(ifp, -1);#endif		qerestart( sc );		qeinit( ifp->if_unit );		break; 	case SIOCRPHYSADDR:		bcopy(sc->is_addr, ifd->current_pa, 6);		for( i = 0; i < 6; i++ )			ifd->default_pa[i] = (u_char)addr->qe_sta_addr[i];		break; 	case SIOCSPHYSADDR:		bcopy(ifr->ifr_addr.sa_data,sc->is_addr,MULTISIZE);#if     NPACKETFILTER > 0		pfilt_newaddress(sc->qe_ed.ess_enetunit, sc->is_addr);#endif  NPACKETFILTER > 0		for ( i = 0; i < 6; i++ )			sc->setup_pkt[i][1] = sc->is_addr[i];		if (ifp->if_flags & IFF_RUNNING) {			qesetup( sc );		}		qeinit(ifp->if_unit);		break;	case SIOCDELMULTI:	case SIOCADDMULTI:		if (cmd == SIOCDELMULTI) {			for (i = 0; i < NMULTI; i++)				if (bcmp(&sc->multi[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) {					if (--sc->muse[i] == 0)						bcopy(qunused_multi,&sc->multi[i],MULTISIZE);				}		} else {			for (i = 0; i < NMULTI; i++) {				if (bcmp(&sc->multi[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) {					sc->muse[i]++;					goto done;				}				if (bcmp(&sc->multi[i],qunused_multi,MULTISIZE) == 0)					j = i;			}			if (j == -1) {				printf("qe%d: SIOCADDMULTI failed, multicast list full: %d\n",ui->ui_unit,NMULTI);				error = ENOBUFS;				goto done;			}			bcopy(ifr->ifr_addr.sa_data, &sc->multi[j], MULTISIZE);			sc->muse[j]++;		}		for ( i = 0; i < 6; i++ )			sc->setup_pkt[i][1] = sc->is_addr[i];		if (ifp->if_flags & IFF_RUNNING) {			qesetup( sc );		}		break;	case SIOCRDCTRS:	case SIOCRDZCTRS:		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) {			sc->ztime = time.tv_sec;			bzero(&sc->ctrblk, sizeof(struct estat));			qe_runt = 0;		}		break;	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		qeinit(ifp->if_unit);		switch(ifa->ifa_addr.sa_family) {#ifdef INET		case AF_INET:			((struct arpcom *)ifp)->ac_ipaddr =				IA_SIN(ifa)->sin_addr;			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;#ifdef  IFF_PROMISC     /* IFF_ALLMULTI and NPACKETFILTER, as well */	case SIOCSIFFLAGS:		/* 		* Run a setup packet in case things have changed; 		* someone may be trying to turn on (or off) promiscuous 		* mode, for example. 		*/		if (ifp->if_flags & IFF_RUNNING)			qesetup(sc);		break;#endif  IFF_PROMISC	default:		error = EINVAL;	}done:	splx(s);	return (error);} /* * Initialize a ring descriptor with mbuf allocation side effects */qeinitdesc( rp, buf, len )	register struct qe_ring *rp;	char *buf; 			/* mapped address	*/	short len;{	/*	 * clear the entire descriptor	 */	bzero( rp, sizeof(struct qe_ring));	if( len ) {		rp->qe_buf_len = (short)(-(len/2));		rp->qe_addr_lo = (short)buf;		rp->qe_addr_hi = (short)((int)buf >> 16);	}}/* * Build a setup packet - the physical address will already be present * in first column. */qesetup( sc )struct qe_softc *sc;{	int i, j, offset = 0, next = 3;	/*	 * Copy the target address to the rest of the entries in this row.	 */	 for ( j = 0; j < 6 ; j++ )		for ( i = 2 ; i < 8 ; i++ )			sc->setup_pkt[j][i] = sc->setup_pkt[j][1];	/*	 * Duplicate the first half.	 */	bcopy(sc->setup_pkt, sc->setup_pkt[8], 64);	/*	 * Fill in the broadcast address.	 */	for ( i = 0; i < 6 ; i++ )		sc->setup_pkt[i][2] = 0xff;	/*	 * If the device structure is available fill in the multicast address	 * in the rest of the setup packet.	 */	for ( i = 0; i < NMULTI; i++ ) {		if (bcmp(&sc->multi[i],qunused_multi,MULTISIZE) != 0) {			for ( j = 0; j < 6; j++ )				sc->setup_pkt[offset+j][next] = sc->multi[i].qm_char[j];			if (++next == 8) {				next = 1;				offset = 8;			}		}	}	sc->setupqueued++;}/* * Routines supporting Q-BUS network interfaces. *//* * Init Q-BUS for interface on uban whose headers of size hlen are to * end on a page boundary.  We allocate a Q-BUS map register for the page * with the header, and nmr more Q-BUS 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. */qe_ubainit(ifu, uban, hlen, nmr, mptr,unit)	register struct qeuba *ifu;	int uban, hlen, nmr,unit;	char *mptr;{	register caddr_t cp, dp;	register struct ifrw *ifrw;	register struct ifxmt *ifxp;	int i, ncl, flag, X_info, R_info, T_info;	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 = mptr;		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[nNRCV]; ifrw++) {			ifrw->ifrw_addr = dp;			ifrw->ifrw_info = 0;			dp += MAXPACKETSIZE + CLBYTES;		}		for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[nNXMT]; ifxp++) {			ifxp->x_ifrw.ifrw_addr = dp;			dp += MAXPACKETSIZE;		}	}	/* allocate for receive ring */	for (ifrw = ifu->ifu_r, flag=0; ifrw < &ifu->ifu_r[nNRCV]; ifrw++, flag++) {		if((qe_ubaalloc(ifu, ifrw, nmr*2, -1, unit)) == 0) 			goto release;	}	/* and now transmit ring */	for (ifxp = ifu->ifu_w, flag=0; ifxp < &ifu->ifu_w[nNXMT]; ifxp++, flag++) {		ifrw = &ifxp->x_ifrw;		T_info=qe_ubaalloc(ifu, ifrw, (nmr * nNXMT) + nNXMT, flag,unit);		if( flag == 0) X_info = T_info;		if (T_info == 0) {			if(flag > 0)				qbarelse(ifu->ifu_uban, &X_info);			goto release;		}		for (i = 0; i < nmr; i++)			ifxp->x_map[i] = ifrw->ifrw_mr[i];		ifxp->x_xswapd = 0;	}	return (1);release:	for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[nNRCV]; ifrw) {		if(ifrw->ifrw_info)			qbarelse(ifu->ifu_uban, &ifrw->ifrw_info);	}	m_pgfree(cp, nNTOT * ncl);	ifu->ifu_r[0].ifrw_addr = 0;	return(0);}/* * This routine sets up the buffers and maps to the Q-bus.  The  * mapping is the same as the UNIBUS, ie 496 map registers.  The flag * input must be zero on the first call, this maps the memory.  Successive * calls (flags is non-zero) breaks the mapped area up into buffers  * and sets up ifrw structures. * Setup either a ifrw structure by allocating Q-BUS map registers, * possibly a buffered data path, and initializing the fields of * the ifrw structure to minimize run-time overhead. */qe_ubaalloc(ifu, ifrw, nmr, do_alloc,unit)	struct qeuba *ifu;	register struct ifrw *ifrw;	int nmr;	int do_alloc, unit;{	static int info=0;	static int ubai;	static int numubai;	int rinfo;	register int nbpg;	if(do_alloc == 0)	{		info = qballoc(ifu->ifu_uban, ifrw->ifrw_addr,				nmr*NBPG , ifu->ifu_flags);		if (info == 0){			return (0);		}		ubai=QBAI_MR(info);		numubai=QBAI_NMR(info);		numubai *= 8;	} else if(do_alloc == -1) {		info = qballoc(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 = 0;		ifrw->ifrw_proto = UBAMR_MRV ;		ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[QBAI_MR(info) + 1];		return(1);	}		/* micro vax 1 is contigus phy. mem */	if(uba_hd[ifu->ifu_uban].uba_type & UBAUVI)	{		ifrw->ifrw_info = info;		ifrw->ifrw_bdp = 0;		ifrw->ifrw_proto = UBAMR_MRV ;		ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[UBAI_MR(info) + 1];		rinfo = info;		info = info + (((int)((MAXPACKETSIZE+(NBPG - 1))/NBPG)+1) * NBPG);		return(rinfo);	}			info = (info & ~(0xfffffe00));	/* 	 * using the same QBUS mapping register for transmit buffer on both VAX	 * and MIPS architecture 	 */#ifdef vax	nbpg=NBPG;#else 	nbpg=512;#endif 	/*         * The number of mapping registers ( info<30:22> ) will not affect the         * mapping at all.         */	info = info | (ubai << 9) | (((int)((MAXPACKETSIZE + (nbpg - 1))/nbpg)+1) << 22);	ifrw->ifrw_info = info;	ifrw->ifrw_bdp = 0;	ifrw->ifrw_proto = UBAMR_MRV ;	ifrw->ifrw_mr = &ifu->ifu_uba->uba_map[QBAI_MR(info) + 1];	if(numubai >= (int)((MAXPACKETSIZE + (nbpg - 1))/nbpg))	{		numubai = numubai - ((int)((MAXPACKETSIZE + (nbpg - 1))/nbpg));		ubai = ubai + ((int)((MAXPACKETSIZE + (nbpg - 1))/nbpg));	}	else	{		return (0);	}	return (info);}/* * 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. */#define pgaligned(x) (((int)(x)&(NBPG-1)) == 0)struct mbuf *qeget(ifu, ifrw, totlen, off0)	register struct qeuba *ifu;	register struct ifrw *ifrw;	int totlen, off0;{	struct mbuf *top, **mp, *m, *p;	int off = off0, len, tlen=0;	register caddr_t cp = ifrw->ifrw_addr + ifu->ifu_hlen;	top = 0;	mp = &top;#ifdef mips/* use bcopy instead of switch the page */	MGET(m, M_DONTWAIT, MT_DATA);	if (m == 0)

⌨️ 快捷键说明

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