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

📄 if_ne.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
			m = m_pullup(m, 2);		} else {			neput(mtod(m, caddr_t), buffer, m->m_len);			buffer += m->m_len;			t -= m->m_len;			MFREE(m, m0);			m = m0;		}	}	/*	 * Init transmit length registers, and set transmit start flag.	 */	len = total;	if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN;	outb(nec+ds0_tbcr0,len&0xff);	outb(nec+ds0_tbcr1,(len>>8)&0xff);	outb(nec+ds0_tpsr, TBUF/DS_PGSIZE);	outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);}/* buffer successor/predecessor in ring? */#define succ(n) (((n)+1 >= RBUFEND/DS_PGSIZE) ? RBUF/DS_PGSIZE : (n)+1)#define pred(n) (((n)-1 < RBUF/DS_PGSIZE) ? RBUFEND/DS_PGSIZE-1 : (n)-1)/* * Controller interrupt. */neintr(unit){	register struct ne_softc *ns = &ne_softc[unit];	u_char cmd,isr;	/* Save cmd, clear interrupt */	cmd = inb (nec+ds_cmd);loop:	isr = inb (nec+ds0_isr);	outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);	outb(nec+ds0_isr, isr);	/* Receiver error */	if (isr & DSIS_RXE) {		/* need to read these registers to clear status */		(void) inb(nec+ ds0_rsr);		(void) inb(nec+ 0xD);		(void) inb(nec + 0xE);		(void) inb(nec + 0xF);		ns->ns_if.if_ierrors++;	}	/* We received something; rummage thru tiny ring buffer */	if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) {		u_char pend,lastfree;		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);		pend = inb(nec+ds1_curr);		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);		lastfree = inb(nec+ds0_bnry);		/* Have we wrapped? */		if (lastfree >= RBUFEND/DS_PGSIZE)			lastfree = RBUF/DS_PGSIZE;		if (pend < lastfree && ns->ns_cur < pend)			lastfree = ns->ns_cur;		else	if (ns->ns_cur > lastfree)			lastfree = ns->ns_cur;		/* Something in the buffer? */		while (pend != lastfree) {			u_char nxt;			/* Extract header from microcephalic board */			nefetch(&ns->ns_ph,lastfree*DS_PGSIZE,				sizeof(ns->ns_ph));			ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph);			/* Incipient paranoia */			if (ns->ns_ph.pr_status == DSRS_RPC ||				/* for dequna's */				ns->ns_ph.pr_status == 0x21)				nerecv (ns);#ifdef NEDEBUG			else  {				printf("cur %x pnd %x lfr %x ",					ns->ns_cur, pend, lastfree);				printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg,					(ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0);				printf("Bogus Sts %x\n", ns->ns_ph.pr_status);				}#endif			nxt = ns->ns_ph.pr_nxtpg ;			/* Sanity check */			if ( nxt >= RBUF/DS_PGSIZE && nxt <= RBUFEND/DS_PGSIZE				&& nxt <= pend)				ns->ns_cur = nxt;			else	ns->ns_cur = nxt = pend;			/* Set the boundaries */			lastfree = nxt;			outb(nec+ds0_bnry, pred(nxt));			outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);			pend = inb(nec+ds1_curr);			outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);		}		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);	}	/* Transmit error */	if (isr & DSIS_TXE) {		ns->ns_flags &= ~DSF_LOCK;		/* Need to read these registers to clear status */		ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);		ns->ns_if.if_oerrors++;	}	/* Packet Transmitted */	if (isr & DSIS_TX) {		ns->ns_flags &= ~DSF_LOCK;		++ns->ns_if.if_opackets;		ns->ns_if.if_collisions += inb(nec+ds0_tbcr0);	}	/* Receiver ovverun? */	if (isr & DSIS_ROVRN) {		log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr			/*, DSIS_BITS*/);		outb(nec+ds0_rbcr0, 0);		outb(nec+ds0_rbcr1, 0);		outb(nec+ds0_tcr, DSTC_LB0);		outb(nec+ds0_rcr, DSRC_MON);		outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);		outb(nec+ds0_rcr, DSRC_AB);		outb(nec+ds0_tcr, 0);	}	/* Any more to send? */	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);	nestart(&ns->ns_if);	outb (nec+ds_cmd, cmd);	outb (nec+ds0_imr, 0xff);	/* Still more to do? */	isr = inb (nec+ds0_isr);	if(isr) goto loop;}/* * Ethernet interface receiver interface. * If input error just drop packet. * Otherwise examine packet to determine type.  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. */nerecv(ns)	register struct ne_softc *ns;{	int len,i;	ns->ns_if.if_ipackets++;	len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);	if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)		return;	/* this need not be so torturous - one/two bcopys at most into mbufs */	nefetch(ns->ns_pb, ns->ns_ba, min(len,DS_PGSIZE-sizeof(ns->ns_ph)));	if (len > DS_PGSIZE-sizeof(ns->ns_ph)) {		int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ;		u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph));		if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;		b = ns->ns_cur*DS_PGSIZE;				while (l >= DS_PGSIZE) {			nefetch(p, b, DS_PGSIZE);			p += DS_PGSIZE; l -= DS_PGSIZE;			if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46;			b = ns->ns_cur*DS_PGSIZE;		}		if (l > 0)			nefetch(p, b, l);	}	/* don't forget checksum! */	len -= sizeof(struct ether_header) + sizeof(long);				neread(ns,(caddr_t)(ns->ns_pb), len);}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */neread(ns, buf, len)	register struct ne_softc *ns;	char *buf;	int len;{	register struct ether_header *eh;    	struct mbuf *m;	int off, resid;	register struct ifqueue *inq;	/*	 * Deal with trailer protocol: if type is trailer type	 * get true type from first 16-bit word past data.	 * Remember that type was trailer by setting off.	 */	eh = (struct ether_header *)buf;	eh->ether_type = ntohs((u_short)eh->ether_type);#define	nedataaddr(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(*nedataaddr(eh, off, u_short *));		resid = ntohs(*(nedataaddr(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; neget 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 = neget(buf, len, off, &ns->ns_if);	if (m == 0) return;	ether_input(&ns->ns_if, eh, m);}/* * Supporting routines *//* * Pull read data off a interface. * Len is length of data, with local net header stripped. * Off is non-zero if a trailer protocol was used, and * gives the offset of the trailer information. * We copy the trailer information and then all the normal * data into mbufs.  When full cluster sized units are present * we copy into clusters. */struct mbuf *neget(buf, totlen, off0, ifp)	caddr_t buf;	int totlen, off0;	struct ifnet *ifp;{	struct mbuf *top, **mp, *m, *p;	int off = off0, len;	register caddr_t cp = buf;	char *epkt;	buf += sizeof(struct ether_header);	cp = buf;	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;	top = 0;	mp = &top;	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 = buf;	}	return (top);}/* * Process an ioctl request. */neioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	struct ne_softc *ns = &ne_softc[ifp->if_unit];	struct ifreq *ifr = (struct ifreq *)data;	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:			neinit(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 *)(ns->ns_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)ns->ns_addr, sizeof(ns->ns_addr));			}			neinit(ifp->if_unit); /* does ne_setaddr() */			break;		    }#endif		default:			neinit(ifp->if_unit);			break;		}		break;	case SIOCSIFFLAGS:		if ((ifp->if_flags & IFF_UP) == 0 &&		    ifp->if_flags & IFF_RUNNING) {			ifp->if_flags &= ~IFF_RUNNING;			outb(nec+ds_cmd,DSCM_STOP|DSCM_NODMA);		} else if (ifp->if_flags & IFF_UP &&		    (ifp->if_flags & IFF_RUNNING) == 0)			neinit(ifp->if_unit);		break;#ifdef notdef	case SIOCGHWADDR:		bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data,			sizeof(ns->ns_addr));		break;#endif	default:		error = EINVAL;	}	splx(s);	return (error);}#endif

⌨️ 快捷键说明

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