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

📄 if_le.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	if ((csr0 & LE_C0_TXON) == 0) {		sc->sc_txoff++;		lereset(&sc->sc_dev);		return (1);	}	if (csr0 & LE_C0_RINT) {		/* interrupt is cleared in lerint */		lerint(sc);	}	if (csr0 & LE_C0_TINT) {		ler1->ler1_rdp = LE_C0_TINT|LE_C0_INEA;		lexint(sc);	}	return (1);}/* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */voidlexint(sc)	register struct le_softc *sc;{	register volatile struct letmd *tmd = sc->sc_r2->ler2_tmd;	sc->sc_lestats.lexints++;	if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {		sc->sc_xint++;		return;	}	if (tmd->tmd1_bits & LE_T1_OWN) {		sc->sc_xown++;		return;	}	if (tmd->tmd1_bits & LE_T1_ERR) {err:		lexerror(sc);		sc->sc_if.if_oerrors++;		if (tmd->tmd3 & (LE_T3_BUFF|LE_T3_UFLO)) {			sc->sc_uflo++;			lereset(&sc->sc_dev);		} else if (tmd->tmd3 & LE_T3_LCOL)			sc->sc_if.if_collisions++;		else if (tmd->tmd3 & LE_T3_RTRY)			sc->sc_if.if_collisions += 16;	}	else if (tmd->tmd3 & LE_T3_BUFF)		/* XXX documentation says BUFF not included in ERR */		goto err;	else if (tmd->tmd1_bits & LE_T1_ONE)		sc->sc_if.if_collisions++;	else if (tmd->tmd1_bits & LE_T1_MORE)		/* what is the real number? */		sc->sc_if.if_collisions += 2;	else		sc->sc_if.if_opackets++;	sc->sc_if.if_flags &= ~IFF_OACTIVE;	lestart(&sc->sc_if);}#define	LENEXTRMP \	if (++bix == LERBUF) bix = 0, rmd = sc->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. */voidlerint(sc)	register struct le_softc *sc;{	register int bix = sc->sc_rmd;	register volatile struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];	sc->sc_lestats.lerints++;	/*	 * Out of sync with hardware, should never happen?	 */	if (rmd->rmd1_bits & LE_R1_OWN) {		do {			sc->sc_lestats.lerscans++;			LENEXTRMP;		} while ((rmd->rmd1_bits & LE_R1_OWN) && bix != sc->sc_rmd);		if (bix == sc->sc_rmd)			printf("%s: RINT with no buffer\n",			    sc->sc_dev.dv_xname);	} else		sc->sc_lestats.lerhits++;	/*	 * Process all buffers with valid data	 */	while ((rmd->rmd1_bits & LE_R1_OWN) == 0) {		int len = rmd->rmd3;		/* Clear interrupt to avoid race condition */		sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;		if (rmd->rmd1_bits & LE_R1_ERR) {			sc->sc_rmd = bix;			lererror(sc, "bad packet");			sc->sc_if.if_ierrors++;		} else if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) !=		    (LE_R1_STP|LE_R1_ENP)) {			/* XXX make a define for LE_R1_STP|LE_R1_ENP? */			/*			 * Find the end of the packet so we can see how long			 * it was.  We still throw it away.			 */			do {				sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;				rmd->rmd3 = 0;				rmd->rmd1_bits = LE_R1_OWN;				LENEXTRMP;			} while (!(rmd->rmd1_bits &			    (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)));			sc->sc_rmd = bix;			lererror(sc, "chained buffer");			sc->sc_rxlen++;			/*			 * If search terminated without successful completion			 * we reset the hardware (conservative).			 */			if ((rmd->rmd1_bits &			    (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)) !=			    LE_R1_ENP) {				lereset(&sc->sc_dev);				return;			}		} else {			leread(sc, sc->sc_r2->ler2_rbuf[bix], len);#ifdef PACKETSTATS			lerpacketsizes[len]++;#endif			sc->sc_lestats.lerbufs++;		}		rmd->rmd3 = 0;		rmd->rmd1_bits = LE_R1_OWN;		LENEXTRMP;	}	sc->sc_rmd = bix;}voidleread(sc, pkt, len)	register struct le_softc *sc;	char *pkt;	int len;{	register struct ether_header *et;	register struct ifnet *ifp = &sc->sc_if;	struct mbuf *m;	struct ifqueue *inq;	int flags;	ifp->if_ipackets++;	et = (struct ether_header *)pkt;	et->ether_type = ntohs((u_short)et->ether_type);	/* adjust input length to account for header and CRC */	len -= sizeof(struct ether_header) + 4;	if (len <= 0) {		if (ledebug)			log(LOG_WARNING,			    "%s: ierror(runt packet): from %s: len=%d\n",			    sc->sc_dev.dv_xname,			    ether_sprintf(et->ether_shost), len);		sc->sc_runt++;		ifp->if_ierrors++;		return;	}	/* Setup mbuf flags we'll need later */	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, then discard things	 * not destined for us (but be sure to keep broadcast/multicast).	 */	if (sc->sc_bpf) {		bpf_tap(sc->sc_bpf, pkt, len + sizeof(struct ether_header));		if ((flags & (M_BCAST | M_MCAST)) == 0 &&		    bcmp(et->ether_dhost, sc->sc_addr,			    sizeof(et->ether_dhost)) != 0)			return;	}#endif	m = leget(pkt, len, 0, ifp);	if (m == 0)		return;	/* XXX this code comes from ether_input() */	ifp->if_lastchange = time;	ifp->if_ibytes += m->m_pkthdr.len + sizeof (*et);	if (flags) {		m->m_flags |= flags;		ifp->if_imcasts++;	}	/* XXX end of code from ether_input() */	switch (et->ether_type) {#ifdef INET	case ETHERTYPE_IP:		schednetisr(NETISR_IP);		inq = &ipintrq;		break;	case ETHERTYPE_ARP:		schednetisr(NETISR_ARP);		inq = &arpintrq;		break;#endif#ifdef NS	case ETHERTYPE_NS:		schednetisr(NETISR_NS);		inq = &nsintrq;		break;#endif#ifdef UTAHONLY#ifdef APPLETALK	case ETHERTYPE_APPLETALK:		schednetisr(NETISR_DDP);		inq = &ddpintq;		break;	case ETHERTYPE_AARP:		aarpinput(&sc->sc_ac, m);		return;#endif#endif	default:		m_freem(m);		return;	}	if (IF_QFULL(inq)) {		IF_DROP(inq);		m_freem(m);		return;	}	IF_ENQUEUE(inq, m);}/* * Routine to copy from mbuf chain to transmit * buffer in board local memory. * * ### this can be done by remapping in some cases */intleput(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);}/* * Routine to copy from board local memory into mbufs. */struct mbuf *leget(lebuf, totlen, off0, ifp)	char *lebuf;	int totlen, off0;	struct ifnet *ifp;{	register struct mbuf *m;	struct mbuf *top = 0, **mp = &top;	register int off = off0, len;	register char *cp;	char *epkt;	lebuf += sizeof(struct ether_header);	cp = lebuf;	epkt = cp + totlen;	if (off) {		cp += off + 2 * sizeof(u_short);		totlen -= 2 * sizeof(u_short);	}	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == 0)		return (0);	m->m_pkthdr.rcvif = ifp;	m->m_pkthdr.len = totlen;	m->m_len = MHLEN;	while (totlen > 0) {		if (top) {			MGET(m, M_DONTWAIT, MT_DATA);			if (m == 0) {				m_freem(top);				return (0);			}			m->m_len = MLEN;		}		len = min(totlen, epkt - cp);		if (len >= MINCLSIZE) {			MCLGET(m, M_DONTWAIT);			if (m->m_flags & M_EXT)				m->m_len = len = min(len, MCLBYTES);			else				len = m->m_len;		} else {			/*			 * Place initial small packet/header at end of mbuf.			 */			if (len < m->m_len) {				if (top == 0 && len + max_linkhdr <= m->m_len)					m->m_data += max_linkhdr;				m->m_len = len;			} else				len = m->m_len;		}		bcopy(cp, mtod(m, caddr_t), (unsigned)len);		cp += len;		*mp = m;		mp = &m->m_next;		totlen -= len;		if (cp == epkt)			cp = lebuf;	}	return (top);}/* * Process an ioctl request. */intleioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa;	register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];	register volatile struct lereg1 *ler1;	int s = splimp(), error = 0;	switch (cmd) {	case SIOCSIFADDR:		ifa = (struct ifaddr *)data;		ifp->if_flags |= IFF_UP;		switch (ifa->ifa_addr->sa_family) {#ifdef INET		case AF_INET:			(void)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 *)(sc->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;				bcopy((caddr_t)ina->x_host.c_host,				    (caddr_t)sc->sc_addr, sizeof(sc->sc_addr));			}			(void)leinit(ifp->if_unit);	/* does le_setaddr() */			break;		    }#endif		default:			(void)leinit(ifp->if_unit);			break;		}		break;	case SIOCSIFFLAGS:		ler1 = sc->sc_r1;		if ((ifp->if_flags & IFF_UP) == 0 &&		    ifp->if_flags & IFF_RUNNING) {			ler1->ler1_rdp = LE_C0_STOP;			ifp->if_flags &= ~IFF_RUNNING;		} else if (ifp->if_flags & IFF_UP &&		    (ifp->if_flags & IFF_RUNNING) == 0)			(void)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 ^ sc->sc_iflags) & IFF_PROMISC) &&		    (ifp->if_flags & IFF_RUNNING)) {			sc->sc_iflags = ifp->if_flags;			lereset(&sc->sc_dev);			lestart(ifp);		}		break;	case SIOCADDMULTI:		error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);		goto update_multicast;	case SIOCDELMULTI:		error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);	update_multicast:		if (error == ENETRESET) {			/*			 * Multicast list has changed; set the hardware			 * filter accordingly.			 */			lereset(&sc->sc_dev);			error = 0;		}		break;	default:		error = EINVAL;	}	splx(s);	return (error);}voidleerror(sc, stat)	register struct le_softc *sc;	int stat;{	if (!ledebug)		return;	/*	 * Not all transceivers implement heartbeat	 * so we only log CERR once.	 */	if ((stat & LE_C0_CERR) && sc->sc_cerr)		return;	log(LOG_WARNING, "%s: error: stat=%b\n",	    sc->sc_dev.dv_xname, stat, LE_C0_BITS);}voidlererror(sc, msg)	register struct le_softc *sc;	char *msg;{	register volatile struct lermd *rmd;	int len;	if (!ledebug)		return;	rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];	len = rmd->rmd3;	log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",	    sc->sc_dev.dv_xname, msg, len > 11 ?	    ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) :	    "unknown",	    sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS);}voidlexerror(sc)	register struct le_softc *sc;{	register volatile struct letmd *tmd;	register int len, tmd3, tdr;	if (!ledebug)		return;	tmd = sc->sc_r2->ler2_tmd;	tmd3 = tmd->tmd3;	tdr = tmd3 & LE_T3_TDR_MASK;	len = -tmd->tmd2;	log(LOG_WARNING,    "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n",	    sc->sc_dev.dv_xname, len > 5 ?	    ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",	    0, len,	    tmd->tmd1_bits, LE_T1_BITS,	    tmd3, LE_T3_BITS, tdr, tdr * 100);}

⌨️ 快捷键说明

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