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

📄 if_ec.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	hmem->scb.command = CU_START;	hmem->scb.status = 0;	SET_CA;}/* * Start output on interface.  Get another datagram to send * off of the interface queue, and copy it to the interface * before starting the output. */ecstart(ifp)	struct ifnet *ifp;{	register struct ec_softc *ec = &ec_softc[ifp->if_unit];	register struct ec_transmit *tmd;	register struct mbuf *m;	int len;again:	if ((ec->sc_if.if_flags & IFF_RUNNING) == 0 || ec->sc_txcnt >= NTXBUF)		return (0);	tmd = ec->sc_hmem->tcom + ec->sc_txnum;	if (tmd->com0 & (COM0_B | COM0_C))		return (ec->sc_txbusy++, 0);	IF_DEQUEUE(&ec->sc_if.if_snd, m);	if (m == 0)		return (0);	len = ecput(ec->sc_hmem->txbuf[ec->sc_txnum], m);#if NBPFILTER > 0	/*	 * If bpf is listening on this interface, let it	 * see the packet before we commit it to the wire.	 */	if (ec->sc_bpf)                bpf_tap(ec->sc_bpf, ec->sc_hmem->txbuf[ec->sc_txnum], len);#endif	tmd->com0 = 0;	tmd->count = len | COM1_EL;	if (ec->sc_txcnt == 0)		ec_txstart(ec);	if (++ec->sc_txnum >= NTXBUF)		ec->sc_txnum = 0;	if (++ec->sc_txcnt >= NTXBUF) {		ec->sc_txcnt = NTXBUF;		ec->sc_if.if_flags |= IFF_OACTIVE;	}	goto again;}int ECC_intr, ECC_rint, ECC_xint, ECC_unready;ecintr(unit)	register int unit;{	struct ec_softc *ec = &ec_softc[unit];	struct ec_mem *hmem = ec->sc_hmem;	register int stat = hmem->scb.status;	hmem->scb.command = stat & 0xf000; /* Ack interrupt cause */	SET_CA;	if (stat & FR)		ecrint(unit);	if (stat & CX)		ecxint(unit);	ECC_intr++;	if ((stat & RU_STATE) != RUS_READY)		ECC_unready++;	UNLATCH_INT;}/* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */ecxint(unit)	register int unit;{	register struct ec_softc *ec = &ec_softc[unit];	register struct ec_transmit *tmd;	int i;	ECC_rint++;	if (ec->sc_txcnt == 0) {		ec->sc_xint++;	/* unexpected transmit interrupt */		return;	}	ec->sc_iflags &= ~IFF_OACTIVE; /* clear deadman indication */	if ((i = ec->sc_txnum - ec->sc_txcnt) < 0) i += NTXBUF;	tmd = ec->sc_hmem->tcom + i;	if (tmd->com0 & COM0_B)		return;	ec->sc_if.if_collisions += tmd->com0 & 0xf;	if ((tmd->com0 & EXCOL) && (tmd->com0 & 0xf) == 0)		ec->sc_if.if_collisions += 16;	if ((tmd->com0 & COM0_OK) == 0) {		ecxerror(unit);		ec->sc_if.if_oerrors++;		if (tmd->com0 & DMALATE) {			ec->sc_uflo++;			(void) ecreset(unit);			return;		}	} else		ec->sc_if.if_opackets++;	tmd->com0 = 0;	if (--ec->sc_txcnt > 0)		ec_txstart(ec);	if (ec->sc_txcnt < 0) {		ec->sc_txbad++;		ec->sc_txcnt = 0;	}	ec->sc_if.if_flags &= ~IFF_OACTIVE;	(void) ecstart(&ec->sc_if);}#define	ECNEXTRCOM \	if (++bix == NRXBUF) bix = 0, rmd = ec->sc_hmem->rcom; 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. */ecrint(unit)	int unit;{	register struct ec_softc *ec = &ec_softc[unit];	register int bix = ec->sc_rxnum;	register struct ec_rfd *rmd = ec->sc_hmem->rcom + bix;	/*	 * Out of sync with hardware, should never happen?	 */	ECC_xint++;	if ((rmd->rfd0 & COM0_C) == 0 || (rmd->count & RBD_F) == 0) {		ecrerror(unit, "out of sync, resetting");		return ecreset(unit);	}	/*	 * Process all buffers with valid data	 */	while ((rmd->rfd0 & COM0_C) && (rmd->count & RBD_F)) {		if (rmd->rfd0 & (COM0_C|COM0_B|COM0_OK) != (COM0_C|COM0_OK)) {			ec->sc_rxnum = bix;			ecrerror(unit, "bad packet");			ec->sc_if.if_ierrors++;		}		if ((rmd->count & (RBD_F|RBD_EOF)) != (RBD_F|RBD_EOF)) {			ecrerror(unit, "chained buffer");			ec->sc_rxlen++;			ec->sc_if.if_ierrors++;		} else			ecread(ec, ec->sc_hmem->txbuf[bix], rmd->count & 0x2f);		rmd->count = 0;		rmd->rfd0 = 0;		ECNEXTRCOM;		ec->sc_rxnum = bix;	}}voidecread(ec, buf, len)	register struct ec_softc *ec;	char *buf;	int len;{	struct ether_header *et, eh;    	struct mbuf *m;	int off, resid, unit = ec->sc_if.if_unit;	ec->sc_if.if_ipackets++;	et = (struct ether_header *)buf;	et->ether_type = ntohs((u_short)et->ether_type);	bcopy((caddr_t)et, &eh, sizeof(eh));	/* adjust input length to account for header */	len = len - sizeof(struct ether_header);#define	ecdataaddr(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(*ecdataaddr(et, off, u_short *));		resid = ntohs(*(ecdataaddr(et, off+2, u_short *)));		if (off + resid > len)			return;		/* sanity */		len = off + resid;	} else		off = 0;	if (len <= 0) {		if (ecdebug)			log(LOG_WARNING,			    "ec%d: ierror(runt packet): from %s: len=%d\n",			    unit, ether_sprintf(et->ether_shost), len);		ec->sc_runt++;		ec->sc_if.if_ierrors++;		return;	}#if NBPFILTER > 0	/*	 * Check if there's a bpf filter listening on this interface.	 * If so, hand off the raw packet to bpf, which must deal with	 * trailers in its own way.	 */	if (ec->sc_bpf)		bpf_tap(ec->sc_bpf, buf, len + sizeof(struct ether_header));#endif#if defined(ISO) || NBPFILTER > 0	/*	 * Note that the interface cannot be in promiscuous mode if	 * there are no bpf listeners.  If we are in promiscuous	 * mode, we have to check if this packet is really ours.	 * However, there may be appropriate multicate addresses involved	 */#define NOT_TO(p) (bcmp(et->ether_dhost, p, sizeof(et->ether_dhost)) != 0)	if (et->ether_dhost[0] & 1) {		if (NOT_TO(etherbroadcastaddr)#ifdef ISO		    && NOT_TO(all_es_snpa) && NOT_TO(all_is_snpa)		    && NOT_TO(all_l1is_snpa) && NOT_TO(all_l2is_snpa)#endif		     ) return;	} else if ((ec->sc_if.if_flags & IFF_PROMISC) && NOT_TO(ec->sc_addr))		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, &ec->sc_if, 0);	if (m == 0)		return;	ether_input(&ec->sc_if, &eh, m);}/* * Routine to copy from mbuf chain to transmit * buffer in board local memory. */ecput(ecbuf, m)	register char *ecbuf;	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 *), ecbuf, len);		ecbuf += len;	}	m_freem(m);	if (tlen < ECMINSIZE) {		bzero(ecbuf, ECMINSIZE - tlen);		tlen = ECMINSIZE;	}	return(tlen);}/* * Process an ioctl request. */ecioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	struct ec_softc *ec = &ec_softc[ifp->if_unit];	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:			ecinit(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 *)(ec->sc_addr);			else {				ifp->if_flags &= ~IFF_RUNNING; 				bcopy((caddr_t)ina->x_host.c_host,				    (caddr_t)ec->sc_addr, sizeof(ec->sc_addr));			}			ecinit(ifp->if_unit);			break;		    }#endif		default:			ecinit(ifp->if_unit);			break;		}		break;	case SIOCSIFFLAGS:		if ((ifp->if_flags & IFF_UP) == 0 &&		    ifp->if_flags & IFF_RUNNING) {			ifp->if_flags &= ~IFF_RUNNING;			ecreset(ifp->if_unit);		} else if (ifp->if_flags & IFF_UP &&		    (ifp->if_flags & IFF_RUNNING) == 0)			ecinit(ifp->if_unit);		/*		 * If the state of the promiscuous bit changes, the interface		 * must be reset to effect the change.		 */		if (((ifp->if_flags ^ ec->sc_iflags) & IFF_PROMISC) &&		    (ifp->if_flags & IFF_RUNNING)) {			ec->sc_iflags = ifp->if_flags & ~IFF_OACTIVE;			ecreset(ifp->if_unit);			ecstart(ifp);		}		break;	default:		error = EINVAL;	}	splx(s);	return (error);}ecrerror(unit, msg)	int unit;	char *msg;{	register struct ec_softc *ec = &ec_softc[unit];	register struct ec_rfd *rmd;	int len;	if (!ecdebug)		return;	rmd = &ec->sc_hmem->rcom[ec->sc_rxnum];	len = rmd->count;	log(LOG_WARNING,	    "ec%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",	    unit, msg,	    len > 11 ? ether_sprintf(&ec->sc_hmem->rxbuf[ec->sc_rxnum][6]) : "unknown",	    ec->sc_rxnum, len,	    rmd->rfd0, "\14\14LEN\13CRC\12ALGN\11NBUF\10DMAL\07SHRT");}ecxerror(unit)	int unit;{	register struct ec_softc *ec = &ec_softc[unit];	register struct ec_transmit *tmd;	int len;	if (!ecdebug)		return;	tmd = &ec->sc_hmem->tcom[ec->sc_txnum];	len = tmd->count;	log(LOG_WARNING,	    "ec%d: oerror: to %s: buf=%d, len=%d, com0=%b\n",	    unit,	    len > 5 ? ether_sprintf(ec->sc_hmem->txbuf[ec->sc_txnum]) : "unknown",	    ec->sc_txnum, len,	    tmd->com0,	    "\14\14ABRT\13LCOLL\12NCAR\11NCTS\10DMAL\07TDEF\06HRBT\05XCOL");}#endif

⌨️ 快捷键说明

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