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

📄 if_le.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	register int stat;	if ((ler0->ler0_status & LE_IR) == 0)		return(0);	if (ler0->ler0_status & LE_JAB) {		le->sc_jab++;		lereset(unit);		return(1);	}	ler1 = le->sc_r1;	LERDWR(ler0, ler1->ler1_rdp, stat);	if (stat & LE_SERR) {		leerror(unit, stat);		if (stat & LE_MERR) {			le->sc_merr++;			lereset(unit);			return(1);		}		if (stat & LE_BABL)			le->sc_babl++;		if (stat & LE_CERR)			le->sc_cerr++;		if (stat & LE_MISS)			le->sc_miss++;		LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);	}	if ((stat & LE_RXON) == 0) {		le->sc_rxoff++;		lereset(unit);		return(1);	}	if ((stat & LE_TXON) == 0) {		le->sc_txoff++;		lereset(unit);		return(1);	}	if (stat & LE_RINT)		lerint(unit);	if (stat & LE_TINT)		lexint(unit);	return(1);}/* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */lexint(unit)	register int unit;{	register struct le_softc *le = &le_softc[unit];	register struct letmd *tmd;	int i, gotone = 0;#ifdef USELEDS	if (inledcontrol == 0)		ledcontrol(0, 0, LED_LANXMT);#endif	do {		if ((i = le->sc_tmd - le->sc_txcnt) < 0)			i += LETBUF;		tmd = &le->sc_r2->ler2_tmd[i];		if (tmd->tmd1 & LE_OWN) {			if (gotone)				break;			le->sc_xown++;			return;		}		/* clear interrupt */		LERDWR(le->sc_r0, LE_TINT|LE_INEA, le->sc_r1->ler1_rdp);		/* XXX documentation says BUFF not included in ERR */		if ((tmd->tmd1 & LE_ERR) || (tmd->tmd3 & LE_TBUFF)) {			lexerror(unit);			le->sc_if.if_oerrors++;			if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {				le->sc_uflo++;				lereset(unit);			} else if (tmd->tmd3 & LE_LCOL)				le->sc_if.if_collisions++;			else if (tmd->tmd3 & LE_RTRY)				le->sc_if.if_collisions += 16;		} else if (tmd->tmd1 & LE_ONE)			le->sc_if.if_collisions++;		else if (tmd->tmd1 & LE_MORE)			/* what is the real number? */			le->sc_if.if_collisions += 2;		else			le->sc_if.if_opackets++;		gotone++;	} while (--le->sc_txcnt > 0);	le->sc_if.if_flags &= ~IFF_OACTIVE;	(void) lestart(&le->sc_if);}#define	LENEXTRMP \	if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd/* * Ethernet interface receiver interrupt. * If input error just drop packet. * Decapsulate packet based on type and pass to type specific * higher-level input routine. */lerint(unit)	int unit;{	register struct le_softc *le = &le_softc[unit];	register int bix = le->sc_rmd;	register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];#ifdef USELEDS	if (inledcontrol == 0)		ledcontrol(0, 0, LED_LANRCV);#endif	/*	 * Out of sync with hardware, should never happen?	 */	if (rmd->rmd1 & LE_OWN) {		le->sc_rown++;		LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);		return;	}	/*	 * Process all buffers with valid data	 */	while ((rmd->rmd1 & LE_OWN) == 0) {		int len = rmd->rmd3;		/* Clear interrupt to avoid race condition */		LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);		if (rmd->rmd1 & LE_ERR) {			le->sc_rmd = bix;			lererror(unit, "bad packet");			le->sc_if.if_ierrors++;		} else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {			/*			 * Find the end of the packet so we can see how long			 * it was.  We still throw it away.			 */			do {				LERDWR(le->sc_r0, LE_RINT|LE_INEA,				       le->sc_r1->ler1_rdp);				rmd->rmd3 = 0;				rmd->rmd1 = LE_OWN;				LENEXTRMP;			} while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));			le->sc_rmd = bix;			lererror(unit, "chained buffer");			le->sc_rxlen++;			/*			 * If search terminated without successful completion			 * we reset the hardware (conservative).			 */			if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=			    LE_ENP) {				lereset(unit);				return;			}		} else			leread(unit, le->sc_r2->ler2_rbuf[bix], len);		rmd->rmd3 = 0;		rmd->rmd1 = LE_OWN;		LENEXTRMP;	}	le->sc_rmd = bix;}leread(unit, buf, len)	int unit;	char *buf;	int len;{	register struct le_softc *le = &le_softc[unit];	register struct ether_header *et;    	struct mbuf *m;	int off, resid, flags;	le->sc_if.if_ipackets++;	et = (struct ether_header *)buf;	et->ether_type = ntohs((u_short)et->ether_type);	/* adjust input length to account for header and CRC */	len = len - sizeof(struct ether_header) - 4;#define	ledataaddr(et, off, type)	((type)(((caddr_t)((et)+1)+(off))))	if (et->ether_type >= ETHERTYPE_TRAIL &&	    et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {		off = (et->ether_type - ETHERTYPE_TRAIL) * 512;		if (off >= ETHERMTU)			return;		/* sanity */		et->ether_type = ntohs(*ledataaddr(et, off, u_short *));		resid = ntohs(*(ledataaddr(et, off+2, u_short *)));		if (off + resid > len)			return;		/* sanity */		len = off + resid;	} else		off = 0;	if (len <= 0) {		if (ledebug)			log(LOG_WARNING,			    "le%d: ierror(runt packet): from %s: len=%d\n",			    unit, ether_sprintf(et->ether_shost), len);		le->sc_runt++;		le->sc_if.if_ierrors++;		return;	}	flags = 0;	if (bcmp((caddr_t)etherbroadcastaddr,	    (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)		flags |= M_BCAST;	if (et->ether_dhost[0] & 1)		flags |= M_MCAST;#if NBPFILTER > 0	/*	 * Check if there's a bpf filter listening on this interface.	 * If so, hand off the raw packet to enet.	 */	if (le->sc_if.if_bpf) {		bpf_tap(le->sc_if.if_bpf, buf, len + sizeof(struct ether_header));		/*		 * Keep the packet if it's a broadcast or has our		 * physical ethernet address (or if we support		 * multicast and it's one).		 */		if (#ifdef MULTICAST		    (flags & (M_BCAST | M_MCAST)) == 0 &&#else		    (flags & M_BCAST) == 0 &&#endif		    bcmp(et->ether_dhost, le->sc_addr,			sizeof(et->ether_dhost)) != 0)			return;	}#endif	/*	 * Pull packet off interface.  Off is nonzero if packet	 * has trailing header; m_devget 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.	 */	m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0);	if (m == 0)		return;	m->m_flags |= flags;	ether_input(&le->sc_if, et, m);}/* * Routine to copy from mbuf chain to transmit * buffer in board local memory. */leput(lebuf, m)	register char *lebuf;	register struct mbuf *m;{	register struct mbuf *mp;	register int len, tlen = 0;	for (mp = m; mp; mp = mp->m_next) {		len = mp->m_len;		if (len == 0)			continue;		tlen += len;		bcopy(mtod(mp, char *), lebuf, len);		lebuf += len;	}	m_freem(m);	if (tlen < LEMINSIZE) {		bzero(lebuf, LEMINSIZE - tlen);		tlen = LEMINSIZE;	}	return(tlen);}/* * Process an ioctl request. */leioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	struct le_softc *le = &le_softc[ifp->if_unit];	struct lereg1 *ler1 = le->sc_r1;	int s = splimp(), error = 0;	switch (cmd) {	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		switch (ifa->ifa_addr->sa_family) {#ifdef INET		case AF_INET:			leinit(ifp->if_unit);	/* before arpwhohas */			((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 *)(le->sc_addr);			else {				/* 				 * The manual says we can't change the address 				 * while the receiver is armed,				 * so reset everything				 */				ifp->if_flags &= ~IFF_RUNNING; 				LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);				bcopy((caddr_t)ina->x_host.c_host,				    (caddr_t)le->sc_addr, sizeof(le->sc_addr));			}			leinit(ifp->if_unit); /* does le_setaddr() */			break;		    }#endif		default:			leinit(ifp->if_unit);			break;		}		break;#if defined (CCITT) && defined (LLC)	case SIOCSIFCONF_X25:		ifp -> if_flags |= IFF_UP;		ifa -> ifa_rtrequest = cons_rtrequest;		error = x25_llcglue(PRC_IFUP, ifa -> ifa_addr);		if (error == 0)			leinit(ifp -> if_unit);		break;#endif /* CCITT && LLC */	case SIOCSIFFLAGS:		if ((ifp->if_flags & IFF_UP) == 0 &&		    ifp->if_flags & IFF_RUNNING) {			LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);			ifp->if_flags &= ~IFF_RUNNING;		} else if (ifp->if_flags & IFF_UP &&		    (ifp->if_flags & IFF_RUNNING) == 0)			leinit(ifp->if_unit);		/*		 * If the state of the promiscuous bit changes, the interface		 * must be reset to effect the change.		 */		if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) &&		    (ifp->if_flags & IFF_RUNNING)) {			le->sc_iflags = ifp->if_flags;			lereset(ifp->if_unit);			lestart(ifp);		}		break;#ifdef MULTICAST	case SIOCADDMULTI:	case SIOCDELMULTI:		/* Update our multicast list  */		error = (cmd == SIOCADDMULTI) ?		    ether_addmulti((struct ifreq *)data, &le->sc_ac) :		    ether_delmulti((struct ifreq *)data, &le->sc_ac);		if (error == ENETRESET) {			/*			 * Multicast list has changed; set the hardware			 * filter accordingly.			 */			lereset(ifp->if_unit);			error = 0;		}		break;#endif	default:		error = EINVAL;	}	splx(s);	return (error);}leerror(unit, stat)	int unit;	int stat;{	if (!ledebug)		return;	/*	 * Not all transceivers implement heartbeat	 * so we only log CERR once.	 */	if ((stat & LE_CERR) && le_softc[unit].sc_cerr)		return;	log(LOG_WARNING,	    "le%d: error: stat=%b\n", unit,	    stat,	    "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");}lererror(unit, msg)	int unit;	char *msg;{	register struct le_softc *le = &le_softc[unit];	register struct lermd *rmd;	int len;	if (!ledebug)		return;	rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];	len = rmd->rmd3;	log(LOG_WARNING,	    "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",	    unit, msg,	    len > 11 ?		ether_sprintf((u_char *)&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) :		"unknown",	    le->sc_rmd, len,	    rmd->rmd1,	    "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");}lexerror(unit)	int unit;{	register struct le_softc *le = &le_softc[unit];	register struct letmd *tmd;	int len;	if (!ledebug)		return;	tmd = le->sc_r2->ler2_tmd;	len = -tmd->tmd2;	log(LOG_WARNING,	    "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",	    unit,	    len > 5 ?		ether_sprintf((u_char *)&le->sc_r2->ler2_tbuf[0][0]) :		"unknown",	    0, len,	    tmd->tmd1,	    "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",	    tmd->tmd3,	    "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");}#endif

⌨️ 快捷键说明

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