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

📄 if_dmv.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
		if ((sc->sc_flag & (DMV_ALLOC | DMV_BMAPPED)) == (DMV_ALLOC | DMV_BMAPPED) && ( sc->sc_flag & DMV_RESTART) == 0 ) {			sc->sc_flag |= DMV_RESTART;			sc->sc_if.if_flags &= ~IFF_UP;			sc->sc_dmvcs.if_dstate = IFS_HALTING;			dmvrestart(sc->sc_if.if_unit);		}		break;	case SIOCDISABLBACK:	/*	 * place device out of loopback	 */		if ( ! dmvsuser() ) 			return(EACCES);		printf("dmv%d: internal loopback disable requested\n", ifp->if_unit);		ifp->if_flags &= ~IFF_LOOPBACK;		if ((sc->sc_flag & (DMV_ALLOC | DMV_BMAPPED)) == (DMV_ALLOC | DMV_BMAPPED) && ( sc->sc_flag & DMV_RESTART) == 0 ) {			sc->sc_flag |= DMV_RESTART;			sc->sc_if.if_flags &= ~IFF_UP;			sc->sc_dmvcs.if_dstate = IFS_HALTING;			dmvrestart(sc->sc_if.if_unit);		}		break;	case SIOCRDCTRS:	case SIOCRDZCTRS:		/*		 * reading and zeroing line counters		 */	{		u_char rqflg;		register struct ctrreq *ctr = (struct ctrreq *)data;		/* 		 * Since this code is not reentrant, only one process		 * can call it at any one time.		 */		if ( (sc->sc_ctrmask & DMV_MSK_BUSY) == DMV_MSK_BUSY )			return(EBUSY);		sc->sc_ctrmask = DMV_MSK_BUSY;		if ( cmd == SIOCRDZCTRS ) {			rqflg = DMV_CNTL_READZ;		} else 			rqflg = DMV_CNTL_READ;		/*		 * issue request for counters.		 */		dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, (rqflg | DMV_KEY_SELINT) );		dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, (rqflg | DMV_KEY_DEOUT) );		dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, (rqflg | DMV_KEY_DEIN) );		dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, (rqflg | DMV_KEY_LBERR) );		dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, (rqflg | DMV_KEY_RBERR) );		dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, (rqflg | DMV_KEY_SELTO) );		dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, (rqflg | DMV_KEY_REPTO) );		dmv_issue_ctl( sc, 0, 0, (rqflg | DMV_KEY_RSERR) );		dmv_issue_ctl( sc, 0, 0, (rqflg | DMV_KEY_LSERR) );		/*		 * wait for response from device.		 *		 * If on interrupt stack, call came from timer routine.		 * Return without sleep.  Call ifioctl later when done.		 */		if ( ! (movpsl() & PSL_IS))		{		    	while ( sc->sc_ctrmask != DMV_MSK_CMPLT )				sleep((caddr_t) &sc->sc_ctrmask, PZERO+1);		}		else 		{			dmv_instack[sc->sc_if.if_unit] = 1;                	error = EINVAL;			break;		}		/*		 * format counters		 */		ctr->ctr_type = CTR_DDCMP;		sc->sc_errctrs.ctr_ddcmp.dst_seconds = (time.tv_sec - sc->sc_ztime) > 0xfffe ? 0xffff : (time.tv_sec - sc->sc_ztime);		ctr->ctr_ddcmp = sc->sc_errctrs.ctr_ddcmp;		if ( cmd == SIOCRDZCTRS ) {			sc->sc_ztime = time.tv_sec;			sc->sc_errctrs.ctr_ddcmp.dst_bytercvd = 0;			sc->sc_errctrs.ctr_ddcmp.dst_bytesent = 0;			sc->sc_errctrs.ctr_ddcmp.dst_blockrcvd = 0;			sc->sc_errctrs.ctr_ddcmp.dst_blocksent = 0;		} 		sc->sc_ctrmask = 0;		break;	}	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		if ((ifp->if_flags & IFF_RUNNING) == 0)			dmvinit(ifp->if_unit); 		break;	case SIOCSIFDSTADDR:		if ((ifp->if_flags & IFF_RUNNING) == 0)			dmvinit(ifp->if_unit); 		break;		        default:                error = EINVAL;        }        splx(s);        return(error);}/* * Routines supporting UNIBUS 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 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. */dmv_ubainit(ifu, uban, hlen, nmr, bufres)	register struct dmvuba *ifu;	int uban, hlen, nmr;	struct dmvbufres *bufres;{	register caddr_t cp, dp;	register struct ifrw *ifrw;	register struct ifxmt *ifxp;	int i, ncl;	ncl = clrnd(nmr + (hlen? CLSIZE: 0)) / 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 - (hlen? (CLBYTES - hlen): 0);	else {		cp = bufres->buffers;		if (cp == 0)			return (0);		ifu->ifu_hlen = hlen;		ifu->ifu_uban = uban;		ifu->ifu_uba = uba_hd[uban].uh_uba;		dp = cp + (hlen? (CLBYTES - hlen): 0);		for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[bufres->nrcv]; ifrw++) {			ifrw->ifrw_addr = dp;			dp += ncl * CLBYTES;		}		for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[bufres->nxmt]; ifxp++) {			ifxp->x_ifrw.ifrw_addr = dp;			dp += ncl * CLBYTES;		}	}	/* allocate for receive ring */	for (ifrw = ifu->ifu_r; ifrw < &ifu->ifu_r[bufres->nrcv]; ifrw++) {		if (dmv_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[bufres->nxmt]; ifxp++) {		ifrw = &ifxp->x_ifrw;		if (dmv_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[bufres->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, bufres->ntot * ncl);	ifu->ifu_r[0].ifrw_addr = 0;	return(0);}/* * Setup either an 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. */staticdmv_ubaalloc(ifu, ifrw, nmr)	struct dmvuba *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) +(ifu->ifu_hlen? 1: 0)];	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 *dmv_get(ifu, ifrw, totlen, off0, dmv_header)	register struct dmvuba *ifu;	register struct ifrw *ifrw;	int totlen, off0, dmv_header;{	struct mbuf *top, **mp, *m;	int off = off0, len;	register caddr_t cp = ifrw->ifrw_addr;	register short hlen = 0;	if ( dmv_header )	{		hlen = ifu->ifu_hlen;		cp += 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 + hlen + off;		} else			len = totlen;		if (len >= CLBYTES) {			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;			/*			 * Switch pages mapped to Q-BUS with new page p,			 * as quick form of copy.  Remap Q-BUS 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 + hlen;				off = 0;				totlen = off0;			}		} else			totlen -= m->m_len;	}	return (top);bad:	m_freem(top);	return (0);}/* * 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. */dmvput(ifu, n, m)	struct dmvuba *ifu;	int n;	register struct mbuf *m;{	register struct mbuf *mp;	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;	while (m) {		dp = mtod(m, char *);		if (claligned(cp) && claligned(dp) && m->m_len == CLBYTES) {			struct pte *pte; int *ip;			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));			mp = m->m_next;			m->m_next = ifxp->x_xtofree;			ifxp->x_xtofree = m;			cp += m->m_len;		} else {			bcopy(mtod(m, caddr_t), cp, (unsigned)m->m_len);			cp += m->m_len;			MFREE(m, mp);		}		m = mp;	}	/*	 * 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.	 */	cc = cp - ifrw->ifrw_addr;	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;	return (cc);}/* * Restart after a fatal error. * Clear device and reinitialize. */dmvrestart(unit)	int unit;{	register struct dmv_softc *sc = &dmv_softc[unit];	register struct uba_device *ui = dmvinfo[unit];	register struct dmvdevice *addr;	register struct ifxmt *ifxp;	register int i;	register struct mbuf *m;	struct dmvuba *ifu;	addr = (struct dmvdevice *)ui->ui_addr;	ifu = &sc->sc_ifuba;	/*	 * Let the DMV finish the MCLR.  At 1 Mbit, it should do so	 * in about a max of 6.4 milliseconds with diagnostics enabled.	 */	addr->bsel1 = DMV_MCLR;	for (i = 100000; i && (addr->bsel1 & DMV_RUN) == 0; i--)		;	/* Did the timer expire or did the DMR finish? */	if ((addr->bsel1 & DMV_RUN) == 0) {		printf("dmv%d: Startup Diagnostics Test Failed\n", unit);		return;	}	/* purge send queue */	IF_DEQUEUE(&sc->sc_if.if_snd, m);	while (m) {		m_freem(m);		IF_DEQUEUE(&sc->sc_if.if_snd, m);	}        for (ifxp = ifu->ifu_w; ifxp < &ifu->ifu_w[sc->sc_bufres.nxmt]; ifxp++) {		if (ifxp->x_xtofree) {			(void) m_freem(ifxp->x_xtofree);			ifxp->x_xtofree = 0;		}	}	/* restart DMV */	dmvinit(unit);	sc->sc_flag &= ~DMV_RESTART;	sc->sc_if.if_collisions++;	/* why not? */}/* * Check to see that transmitted packets don't * lose interrupts.  The device has to be active. */dmvwatch(){        register struct uba_device *ui;	register struct dmv_softc *sc;	struct dmvdevice *addr;	register int i;	for (i = 0; i < nNDMV; i++) {		sc = &dmv_softc[i];		if ((sc->sc_flag & DMV_ACTIVE) == 0)			continue;        	if ((ui = dmvinfo[i]) == 0 || ui->ui_alive == 0)			continue;		if (sc->sc_oused) {			sc->sc_nticks++;			if (sc->sc_nticks > dmv_timeout) {				sc->sc_nticks = 0;        			addr = (struct dmvdevice *)ui->ui_addr;				printd("dmvwatch: dmv%d hung, bsel0 = 0x%x, bsel1 = 0x%x, bsel2 = 0x%x\n",				   i, addr->bsel0 & 0xff, addr->bsel1 & 0xff,				   addr->bsel2 & 0xff);				if (( sc->sc_flag & DMV_RESTART) == 0 ) {					sc->sc_flag |= DMV_RESTART;					sc->sc_if.if_flags &= ~IFF_UP;					sc->sc_dmvcs.if_dstate = IFS_HALTING;					dmvrestart(i);				}			}		}	}	timeout(dmvwatch, (caddr_t) 0, hz);}/* * Check to make sure requestor is priveleged.  suser is * called when not on interrupt stack or when  * there is a system process. */dmvsuser(){	if ( ! (movpsl() & PSL_IS))		return(suser());	return(1);}#endif

⌨️ 快捷键说明

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