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

📄 if_qe.c

📁 open bsd vax module -if function
💻 C
📖 第 1 页 / 共 2 页
字号:
	addr->qe_rcvlist_lo = (short)sc->rringaddr;	addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16);	ifp->if_flags |= IFF_UP | IFF_RUNNING;	sc->qe_flags |= QEF_RUNNING;	qesetup( sc );	(void) qestart( ifp );	sc->qe_if.if_timer = QESLOWTIMEOUT;	/* Start watchdog */	splx( s );}/* * Start output on interface. * */qestart(ifp)	struct ifnet *ifp;{	int unit =  ifp->if_unit;	struct uba_device *ui = qeinfo[unit];	register struct qe_softc *sc = &qe_softc[unit];	register struct qedevice *addr;	register struct qe_ring *rp;	register index;	struct mbuf *m;	int buf_addr, len, s;	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 < (NXMT-1) ;		sc->tindex = index = ++index % NXMT){		rp = &sc->tring[index];		if( sc->setupqueued ) {			buf_addr = sc->setupaddr;			len = 128;			rp->qe_setup = 1;			sc->setupqueued = 0;		} else {			IF_DEQUEUE(&sc->qe_if.if_snd, m);			if( m == 0 ){				splx(s);				return (0);			}			buf_addr = sc->qe_ifw[index].ifw_info;			len = if_ubaput(&sc->qe_uba, &sc->qe_ifw[index], m);		}		if( len < MINDATA )			len = MINDATA;		/*		 *  Does buffer end on odd byte ?		 */		if( len & 1 ) {			len++;			rp->qe_odd_end = 1;		}		rp->qe_buf_len = -(len/2);		buf_addr = UBAI_ADDR(buf_addr);		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;		if (sc->nxmit++ == 0) {			sc->qe_flags |= QEF_FASTTIMEO;			sc->qe_if.if_timer = QETIMEOUT;		}		/*		 * See if the xmit list is invalid.		 */		if( addr->qe_csr & QE_XL_INVALID ) {			buf_addr = (int)(sc->tringaddr+index);			addr->qe_xmtlist_lo = (short)buf_addr;			addr->qe_xmtlist_hi = (short)(buf_addr >> 16);		}	}	splx( s );	return (0);}/* * Ethernet interface interrupt processor */qeintr(unit)	int unit;{	register struct qe_softc *sc = &qe_softc[unit];	struct qedevice *addr = (struct qedevice *)qeinfo[unit]->ui_addr;	int buf_addr, csr;#ifdef notdef	splx(sc->ipl);#else	(void) splimp();#endif	if (!(sc->qe_flags & QEF_FASTTIMEO))		sc->qe_if.if_timer = QESLOWTIMEOUT; /* Restart timer clock */	csr = addr->qe_csr;	addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP;	if( csr & QE_RCV_INT )		qerint( unit );	if( csr & QE_XMIT_INT )		qetint( unit );	if( csr & QE_NEX_MEM_INT )		printf("qe%d: Nonexistent memory interrupt\n", unit);	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);	}}/* * Ethernet interface transmit interrupt. */qetint(unit)	int unit;{	register struct qe_softc *sc = &qe_softc[unit];	register struct qe_ring *rp;	register struct ifxmt *ifxp;	int status1, setupflag;	short len;	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((caddr_t)rp, sizeof(struct qe_ring));		if( --sc->nxmit == 0 ) {			sc->qe_flags &= ~QEF_FASTTIMEO;			sc->qe_if.if_timer = QESLOWTIMEOUT;		}		if( !setupflag ) {			/*			 * Do some statistics.			 */			sc->qe_if.if_opackets++;			sc->qe_if.if_collisions += ( status1 & QE_CCNT ) >> 4;			if (status1 & QE_ERROR)				sc->qe_if.if_oerrors++;			ifxp = &sc->qe_ifw[sc->otindex];			if (ifxp->ifw_xtofree) {				m_freem(ifxp->ifw_xtofree);				ifxp->ifw_xtofree = 0;			}		}		sc->otindex = ++sc->otindex % NXMT;	}	(void) qestart( &sc->qe_if );}/* * 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 qe_ring *rp;	register int nrcv = 0;	int len, status1, status2;	int bufaddr;	/*	 * 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.	 *	 */	while (sc->rring[sc->rindex].qe_status1 == QE_NOTYET && nrcv < NRCV) {		/*		 * We got an interrupt but did not find an input packet		 * where we expected one to be, probably because the ring		 * was overrun.		 * We search forward to find a valid packet and start		 * processing from there.  If no valid packet is found it		 * means we processed all the packets during a previous		 * interrupt and that the QE_RCV_INT bit was set while		 * we were processing one of these earlier packets.  In		 * this case we can safely ignore the interrupt (by dropping		 * through the code below).		 */		sc->rindex = (sc->rindex + 1) % NRCV;		nrcv++;	}	if (nrcv && nrcv < NRCV)		log(LOG_ERR, "qe%d: ring overrun, resync'd by skipping %d\n",		    unit, nrcv);	for( ; sc->rring[sc->rindex].qe_status1 != QE_NOTYET ; sc->rindex = ++sc->rindex % NRCV ){		rp = &sc->rring[sc->rindex];		status1 = rp->qe_status1;		status2 = rp->qe_status2;		bzero((caddr_t)rp, sizeof(struct qe_ring));		if( (status1 & QE_MASK) == QE_MASK )			panic("qe: chained packet");		len = ((status1 & QE_RBL_HI) | (status2 & QE_RBL_LO)) + 60;		sc->qe_if.if_ipackets++;		if (status1 & QE_ERROR) {			if ((status1 & QE_RUNT) == 0)				sc->qe_if.if_ierrors++;		} else {			/*			 * We don't process setup packets.			 */			if( !(status1 & QE_ESETUP) )				qeread(sc, &sc->qe_ifr[sc->rindex],					len - sizeof(struct ether_header));		}		/*		 * Return the buffer to the ring		 */		bufaddr = (int)UBAI_ADDR(sc->qe_ifr[sc->rindex].ifrw_info);		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;	}}/* * 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 ifaddr *ifa = (struct ifaddr *)data;	int s = splimp(), error = 0;	switch (cmd) {	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#ifdef NS		case AF_NS:		    {			register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);			if (ns_nullhost(*ina))				ina->x_host = *(union ns_host *)(sc->qe_addr);			else				qe_setaddr(ina->x_host.c_host, ifp->if_unit);			break;		    }#endif		}		break;	case SIOCSIFFLAGS:		if ((ifp->if_flags & IFF_UP) == 0 &&		    sc->qe_flags & QEF_RUNNING) {			((struct qedevice *)			   (qeinfo[ifp->if_unit]->ui_addr))->qe_csr = QE_RESET;			sc->qe_flags &= ~QEF_RUNNING;		} else if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==		    IFF_RUNNING && (sc->qe_flags & QEF_RUNNING) == 0)			qerestart(sc);		break;	default:		error = EINVAL;	}	splx(s);	return (error);}/* * set ethernet address for unit */qe_setaddr(physaddr, unit)	u_char *physaddr;	int unit;{	register struct qe_softc *sc = &qe_softc[unit];	register int i;	for (i = 0; i < 6; i++)		sc->setup_pkt[i][1] = sc->qe_addr[i] = physaddr[i];	sc->qe_flags |= QEF_SETADDR;	if (sc->qe_if.if_flags & IFF_RUNNING)		qesetup(sc);	qeinit(unit);}/* * Initialize a ring descriptor with mbuf allocation side effects */qeinitdesc(rp, addr, len)	register struct qe_ring *rp;	caddr_t addr; 			/* mapped address */	int len;{	/*	 * clear the entire descriptor	 */	bzero((caddr_t)rp, sizeof(struct qe_ring));	if( len ) {		rp->qe_buf_len = -(len/2);		rp->qe_addr_lo = (short)addr;		rp->qe_addr_hi = (short)((int)addr >> 16);	}}/* * Build a setup packet - the physical address will already be present * in first column. */qesetup( sc )struct qe_softc *sc;{	register i, j;	/*	 * 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((caddr_t)sc->setup_pkt[0], (caddr_t)sc->setup_pkt[8], 64);	/*	 * Fill in the broadcast (and ISO multicast) address(es).	 */	for ( i = 0; i < 6 ; i++ ) {		sc->setup_pkt[i][2] = 0xff;#ifdef ISO		sc->setup_pkt[i][3] = all_es_snpa[i];		sc->setup_pkt[i][4] = all_is_snpa[i];		sc->setup_pkt[i][5] = all_l1is_snpa[i];		sc->setup_pkt[i][6] = all_l2is_snpa[i];#endif	}	sc->setupqueued++;}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */qeread(sc, ifrw, len)	register struct qe_softc *sc;	struct ifrw *ifrw;	int len;{	struct ether_header *eh, ehm;    	struct mbuf *m;	int off, resid, s;	struct ifqueue *inq;	/*	 * Deal with trailer protocol: if type is INET trailer	 * get true type from first 16-bit word past data.	 * Remember that type was trailer by setting off.	 */	eh = (struct ether_header *)ifrw->ifrw_addr;	eh->ether_type = ntohs((u_short)eh->ether_type);#define	qedataaddr(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 */		eh->ether_type = ntohs(*qedataaddr(eh,off, u_short *));		resid = ntohs(*(qedataaddr(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; qeget 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.	 */	bcopy((caddr_t)eh, (caddr_t)&ehm, sizeof(ehm));	m = if_ubaget(&sc->qe_uba, ifrw, len, off, &sc->qe_if);	if (m)		ether_input(&sc->qe_if, &ehm, m);}/* * Watchdog timeout routine. There is a condition in the hardware that * causes the board to lock up under heavy load. This routine detects * the hang up and restarts the device. */qetimeout(unit)	int unit;{	register struct qe_softc *sc;	sc = &qe_softc[unit];#ifdef notdef	log(LOG_ERR, "qe%d: transmit timeout, restarted %d\n",	     unit, sc->qe_restarts++);#endif	qerestart(sc);}/* * Restart for board lockup problem. */qerestart(sc)	register struct qe_softc *sc;{	register struct ifnet *ifp = &sc->qe_if;	register struct qedevice *addr = sc->addr;	register struct qe_ring *rp;	register i;	addr->qe_csr = QE_RESET;	addr->qe_csr &= ~QE_RESET;	qesetup( sc );	for (i = 0, rp = sc->tring; i < NXMT; rp++, i++) {		rp->qe_flag = rp->qe_status1 = QE_NOTYET;		rp->qe_valid = 0;	}	sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;	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);	sc->qe_flags |= QEF_RUNNING;	(void) qestart(ifp);}#endif

⌨️ 快捷键说明

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