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

📄 if_qe.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
	register struct qe_softc *sc = qe_softc[unit];	register struct uba_device *ui = qeinfo[unit];#ifdef vax	register struct qedevice *addr = (struct qedevice *)ui->ui_addr;#endif vax#ifdef mips	volatile struct qedevice *addr = (struct qedevice *)ui->ui_addr;#endif mips	register struct ifnet *ifp = &sc->is_if;	register int i;	int s;	/* address not known */	/* DECnet must set this somewhere to make device happy */	if (ifp->if_addrlist == (struct ifaddr *)0)			return;	if (ifp->if_flags & IFF_RUNNING)		return;	/*	 * map the communications area onto the device 	 */	sc->rringaddr = (struct qe_ring *)((int)qballoc(0,		sc->rring, sizeof(struct qe_ring)*(nNTOT+2),0)&mask);	sc->tringaddr = sc->rringaddr+nNRCV+1;	sc->setupaddr =	qballoc(0, sc->setup_pkt, sizeof(sc->setup_pkt), 0) & mask;	/*	 * init buffers and maps	 */	if (qe_ubainit(&sc->qeuba, ui->ui_ubanum,	    sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE), sc->buffers,unit) == 0) { 		printf("qe%d: can't initialize\n", unit);		sc->is_if.if_flags &= ~IFF_UP;		return;	}	/*	 * Init the buffer descriptors and indexes for each of the lists and	 * loop them back to form a ring.	 */	for( i = 0 ; i < nNRCV ; i++ ){		qeinitdesc( &sc->rring[i],			sc->qeuba.ifu_r[i].ifrw_info & mask, MAXPACKETSIZE);		sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;		sc->rring[i].qe_valid = 1;	}	qeinitdesc( &sc->rring[i], NULL, 0 );	sc->rring[i].qe_addr_lo = (short)sc->rringaddr;	sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16);	sc->rring[i].qe_chain = 1;	sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;	sc->rring[i].qe_valid = 1;	for( i = 0 ; i <= nNXMT ; i++ )		qeinitdesc( &sc->tring[i], NULL, 0 );	i--;	sc->tring[i].qe_addr_lo = (short)sc->tringaddr;	sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16);	sc->tring[i].qe_chain = 1;	sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET;	sc->tring[i].qe_valid = 1;	sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;	/*	 * Take the interface out of reset, program the vector, 	 * enable interrupts, and tell the world we are up.	 */	s = splimp();	addr->qe_vector = (u_short)sc->qe_intvec;	sc->addr = (struct qedevice *) addr;	if ( ifp->if_flags & IFF_LOOPBACK )		addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ELOOP;	else		addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP;	addr->qe_rcvlist_lo = (short)sc->rringaddr;	addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16);	ifp->if_flags |= IFF_UP | IFF_RUNNING;	ifp->if_flags &= ~IFF_OACTIVE;	qesetup( sc );	qestart( unit );	sc->ztime = time.tv_sec;	splx( s );} /* * Start output on interface. * */qestart(unit)	int unit;{	register struct qe_softc *sc = qe_softc[unit];	register struct qedevice *addr;	register struct qe_ring *rp;	register int index;	struct mbuf *m;	int buf_addr, len, s;	struct uba_device *ui = qeinfo[unit];	 	s = splimp();	addr = (struct qedevice *)ui->ui_addr;	/*	 * The deqna doesn't look at anything but the valid bit	 * to determine if it should transmit this packet. If you have	 * a ring and fill it the device will loop indefinately on the	 * packet and continue to flood the net with packets until you	 * break the ring. For this reason we never queue more than n-1	 * packets in the transmit ring. 	 *	 * The microcoders should have obeyed their own defination of the	 * flag and status words, but instead we have to compensate.	 */	for( index = sc->tindex; 		sc->tring[index].qe_valid == 0 && sc->nxmit < (nNXMT-1) ;		sc->tindex = index = ++index % nNXMT){		rp = &sc->tring[index];		if( sc->setupqueued ) {			buf_addr = sc->setupaddr;			len = 128;			rp->qe_setup = 1;			sc->setupqueued = 0;		} else {			IF_DEQUEUE(&sc->is_if.if_snd, m);			if( m == 0 ){				splx(s);				return;			}			buf_addr = sc->qeuba.ifu_w[index].x_ifrw.ifrw_info;			len = qeput(&sc->qeuba, index, m);		}		/*		 *  Does buffer end on odd byte ? 		 */		if( len & 1 ) {			len++;			rp->qe_odd_end = 1;		}#ifdef  IFF_PROMISC		if (rp->qe_setup && (sc->is_if.if_flags & IFF_PROMISC)) {			len |= QE_PROMISCUOUS;		}#endif  IFF_PROMISC#ifdef  IFF_ALLMULTI		if (rp->qe_setup && (sc->is_if.if_flags & IFF_ALLMULTI))			len |= QE_MULTICAST;#endif  IFF_ALLMULTI		rp->qe_buf_len = -(len/2);		buf_addr &= mask;		rp->qe_flag = rp->qe_status1 = QE_NOTYET;		rp->qe_addr_lo = (short)buf_addr;		rp->qe_addr_hi = (short)(buf_addr >> 16);		rp->qe_eomsg = 1;		rp->qe_flag = rp->qe_status1 = QE_NOTYET;		rp->qe_valid = 1;		sc->nxmit++;		sc->is_if.if_flags |= IFF_OACTIVE;		/*		 * If the watchdog time isn't running kick it.		 */		sc->timeout=1;		if( !qewatchrun++ ) 			timeout(qewatch,0,QE_TIMEO);					/*		 * See if the xmit list is invalid.		 */		if( (addr->qe_csr & QE_XL_INVALID) && (rp->qe_status1 == QE_NOTYET)) {			buf_addr = (int)(sc->tringaddr+index);			addr->qe_xmtlist_lo = (short)buf_addr;			addr->qe_xmtlist_hi = (short)(buf_addr >> 16);		}	}	splx( s );} /* * Ethernet interface interrupt processor */qeintr(unit)	int unit;{	register struct qe_softc *sc = qe_softc[unit];#ifdef vax	struct qedevice *addr = (struct qedevice *)qeinfo[unit]->ui_addr;#endif vax#ifdef mips	volatile struct qedevice *addr = (struct qedevice *)qeinfo[unit]->ui_addr;#endif mips	int s, buf_addr;	u_short csr;	s = splimp();	csr = addr->qe_csr;	addr->qe_csr = csr;	if( csr & QE_RCV_INT ) 		qerint( unit );	if( csr & QE_XMIT_INT )		qetint( unit );	if( csr & QE_NEX_MEM_INT )		{		if ( qe_show_restarts ) 			mprintf("qe%d: non-existant memory  \n", unit);		qerestart( sc );  	}	if( addr->qe_csr & QE_RL_INVALID && sc->rring[sc->rindex].qe_status1 == QE_NOTYET ) {		buf_addr = (int)&sc->rringaddr[sc->rindex];		addr->qe_rcvlist_lo = (short)buf_addr;		addr->qe_rcvlist_hi = (short)(buf_addr >> 16);	}	if( addr->qe_csr & QE_XL_INVALID && sc->tring[sc->otindex].qe_status1 == QE_NOTYET && sc->nxmit > 0 ) {		buf_addr = (int)&sc->tringaddr[sc->otindex];		addr->qe_xmtlist_lo = (short)buf_addr;		addr->qe_xmtlist_hi = (short)(buf_addr >> 16);	}	splx( s );} /* * Ethernet interface transmit interrupt. */qetint(unit)	int unit;{	register struct qe_softc *sc = qe_softc[unit];	register struct qe_ring *rp;	register struct ifrw *ifrw;	register struct ifxmt *ifxp;	register struct ether_header *eh;	register int status1, setupflag;	short len;	sc->qe_rl_invalid = 0; /* dallas */#ifdef mips 	/*	 * Flush the cache for the transmit ring descriptor	 */ 	clean_dcache(PHYS_TO_K0(svtophy(&sc->tring[0])), sizeof(struct qe_ring)* nNXMT);  #endif mips 	while( sc->otindex != sc->tindex && sc->tring[sc->otindex].qe_status1 != QE_NOTYET && sc->nxmit > 0 ) {		/*		 * Save the status words from the descriptor so that it can		 * be released.		 */		rp = &sc->tring[sc->otindex];		status1 = rp->qe_status1;		setupflag = rp->qe_setup;		len = (-rp->qe_buf_len) * 2;		if( rp->qe_odd_end )			len++;		/*		 * Init the buffer descriptor		 */		bzero( rp, sizeof(struct qe_ring));		if( --sc->nxmit == 0 ) {			sc->timeout = 0;			sc->is_if.if_flags &= ~IFF_OACTIVE;		}		if( !setupflag ) {			/*			 * Do some statistics.			 */			sc->is_if.if_opackets++;			sc->is_if.if_collisions += ( status1 & QE_CCNT ) >> 4;			/*			 * Accumulate DECnet statistics			 */			if (status1 & QE_CCNT) {				if (((status1 & QE_CCNT) >> 4) == 1) {					if (sc->ctrblk.est_single != 0xffffffff)						sc->ctrblk.est_single++;				} else {					if (sc->ctrblk.est_multiple != 0xffffffff)						sc->ctrblk.est_multiple++;				}			}			if (status1 & QE_FAIL)				if (sc->ctrblk.est_collis != 0xffff)					sc->ctrblk.est_collis++;			if( status1 & QE_ERROR ) { 				sc->is_if.if_oerrors++;				if (sc->ctrblk.est_sendfail != 0xffff)					sc->ctrblk.est_sendfail++;				sc->ctrblk.est_sendfail_bm = 0;				if (status1 & QE_ABORT)					sc->ctrblk.est_sendfail_bm |= 1;				if (status1 & (QE_NOCAR | QE_LOSS))					sc->ctrblk.est_sendfail_bm |= 2;							} else {                                /*                                 * Accumulate statistics for DECnet                                 */                                sc->ctrblk.est_bytesent += len;                                if (sc->ctrblk.est_bloksent !=                                    (unsigned) 0xffffffff)                                        sc->ctrblk.est_bloksent++;			}			/*			 * If this was a broadcast packet loop it			 * back because the hardware can't hear it's own			 * transmits and the rwho deamon expects to see them.			 * This code will have to be expanded to include multi-			 * cast if the same situation developes.			 */			ifxp = &sc->qeuba.ifu_w[sc->otindex];			ifrw = &sc->qeuba.ifu_w[sc->otindex].x_ifrw;			eh = (struct ether_header *)ifrw->ifrw_addr;                        /*                         * Accumulate statistics for DECnet                         */			if(eh->ether_dhost[0] & 1) {				sc->ctrblk.est_mbytesent += len;			if (sc->ctrblk.est_mbloksent != (unsigned) 0xffffffff)				sc->ctrblk.est_mbloksent++;			}/* * This is a Kludge to do a fast check to see if the ethernet * address is all 1's, the ethernet broadcast addr, and loop the * packet back. */			if((!(bcmp(eh->ether_dhost,qe_multi,6))) || (sc->is_if.if_flags & IFF_PFCOPYALL)) {				qeread(sc, ifrw, len, ifxp->x_xtofree);				ifxp->x_xtofree =0;			}else if( ifxp->x_xtofree ) {				m_freem( ifxp->x_xtofree );				ifxp->x_xtofree = 0;			}		}		sc->otindex = ++sc->otindex % nNXMT;	}	if (!(sc->is_if.if_flags & IFF_OACTIVE))		qestart( unit );} /* * Ethernet interface receiver interrupt. * 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. */qerint(unit)	int unit;{	register struct qe_softc *sc = qe_softc[unit];	register struct ifnet *ifp = &sc->is_if;	register struct qe_ring *rp;	register int last;	u_short status1, status2;	short len;	int bufaddr;	struct ether_header *eh;	/*	 * Traverse the receive ring looking for packets to pass back.	 * The search is complete when we find a descriptor not in use.	 *	 * As in the transmit case the deqna doesn't honor it's own protocols	 * so there exists the possibility that the device can beat us around	 * the ring. The proper way to guard against this is to insure that	 * there is always at least one invalid descriptor. We chose instead	 * to make the ring large enough to minimize the problem. With a ring	 * size of 4 we haven't been able to see the problem. To be safe we	 * doubled that to 8.	 *	 */#ifdef mips 	/*	 * Flush the cache for the receive ring descriptor	 */	clean_dcache(PHYS_TO_K0(svtophy(&sc->rring[0])), sizeof(struct qe_ring)* nNRCV);  #endif mips 	for( last = sc->rindex; sc->rring[sc->rindex].qe_status1 != QE_NOTYET ;	     last = sc->rindex = ++sc->rindex % nNRCV ){		rp = &sc->rring[sc->rindex];		status1 = rp->qe_status1;		status2 = rp->qe_status2;		bzero( rp, sizeof(struct qe_ring));		/* Discard chained packets */		while( (status1 & QE_MASK) == QE_MASK ) {			last = ++last % nNRCV;			rp = &sc->rring[last];			status1 = rp->qe_status1;			bzero( rp, sizeof(struct qe_ring));			if ((status1 & QE_MASK) != QE_MASK) {				if (status1 == QE_NOTYET)					/* Should NEVER happen */					panic("qe: chained packet");				else					goto drop;			}		}		len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)); 		if( ! (ifp->if_flags & IFF_LOOPBACK) ) {			if( status1 & QE_ERROR ) {				if (status1 & QE_RUNT )					qe_runt++;				if ((status1 & QE_DISCARD) && 					(status1&(QE_OVF|QE_CRCERR|QE_FRAME))){					/* A real error */					ifp->if_ierrors++;					ifp->if_ipackets++;  					/* Bump up receive fails */                                        if (sc->ctrblk.est_recvfail != 0xffff)					sc->ctrblk.est_recvfail++;                                        /* Clear previous bitmask; set bits */					sc->ctrblk.est_recvfail_bm = 0;					if (status1 & QE_OVF) {						sc->ctrblk.est_recvfail_bm |= 4;#if     NPACKETFILTER > 0						sc->qe_ed.ess_missed++;#endif  NPACKETFILTER					}					if (status1 & QE_CRCERR)						sc->ctrblk.est_recvfail_bm |= 1;					if (status1 & QE_FRAME)						sc->ctrblk.est_recvfail_bm |= 2;				}			} else {				/*				 * We don't process setup packets.				 */				if( !(status1 & QE_ESETUP) ) {						len += 60;

⌨️ 快捷键说明

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