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

📄 if_ne.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 2 页
字号:
	while ((inb(nec+ds0_isr) & DSIS_RDC) == 0)		;	outb(nec+ds0_isr, DSIS_RDC);	outb(nec+ds_cmd, cmd);		/* Clear remote DMA */	/*	 * Init transmit length registers, and set transmit start flag.	 */	if (len < ETHER_MIN_LEN)		len = ETHER_MIN_LEN;	outb(nec+ds0_tbcr0, len);	outb(nec+ds0_tbcr1, len >> 8);	outb(nec+ds0_tpsr, ns->ns_tbuf);	outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);	m_freem(m0);}/* * Controller interrupt. */neintr(ns)	register struct ne_softc *ns;{	register nec = ns->ns_base;	u_char cmd, isr;	/* Save cmd, clear interrupt */	cmd = inb(nec+ds_cmd);loop:	isr = inb(nec+ds0_isr);#ifdef PROM	if (isr == 0)		return 1;#endif	outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);	outb(nec+ds0_isr, isr);	/* Packet Transmitted or Transmit error */	if (isr & (DSIS_TX|DSIS_TXE)) {		ns->ns_if.if_flags &= ~IFF_OACTIVE;		/* Need to read these registers to clear status */		++ns->ns_if.if_opackets;		ns->ns_if.if_collisions += inb(nec+ds0_tbcr0) & 0xf;		if (isr & DSIS_TXE)			ns->ns_if.if_oerrors++;	}	/* Receiver error */	if (isr & DSIS_RXE) {		/* need to read these registers to clear status */		(void) inb(nec + ds0_rsr);		(void) inb(nec + ds0_rcvalctr);		(void) inb(nec + ds0_rcvcrcctr);		(void) inb(nec + ds0_rcvfrmctr);		ns->ns_if.if_ierrors++;	}	/* We received something; rummage thru tiny ring buffer */	if (isr & (DSIS_RX|DSIS_RXE)) {		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 >= ns->ns_rbufend)	/* should not happen */			lastfree = ns->ns_rbuf;		if (pend < lastfree && ns->ns_cur <= pend)			lastfree = ns->ns_cur;		else	if (ns->ns_cur > lastfree)			lastfree = ns->ns_cur;#ifdef NEDEBUG		else if (lastfree != ns->ns_cur)			printf("ne lastfree? (%x %x %x)\n",			    lastfree, pend, ns->ns_cur);#endif		/* Something in the buffer? */		while (pend != lastfree) {			u_char nxt;			/* Extract header from microcephalic board */			nefetch(nec, ns->ns_ne1000, (caddr_t)&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 if (ns->ns_if.if_flags & IFF_DEBUG) {				printf("ne: 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 >= ns->ns_rbuf && nxt <= ns->ns_rbufend /*&&			    nxt <= pend*/)	/* XXX */				ns->ns_cur = nxt;			else {				if (ns->ns_if.if_flags & IFF_DEBUG)				   printf("ne: bad nxt: %x (pend %x, cur %x)\n",					nxt, pend, ns->ns_cur);				ns->ns_cur = nxt = pend;			}			/* Set the boundaries */			lastfree = nxt;			if (--nxt < ns->ns_rbuf)				nxt = ns->ns_rbufend - 1;			outb(nec+ds0_bnry, 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);	}#if 0	/* Receiver ovverun? */	if (isr & DSIS_ROVRN) {		log(LOG_ERR, "ne%d: error: isr %x\n", ns->ne_dev.dv_unit,		    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);	}#endif	if ((isr & (DSIS_RX|DSIS_RXE|DSIS_TX|DSIS_TXE)) == 0 &&	    ns->ns_if.if_flags & IFF_DEBUG)		log(LOG_ERR, "ne%d: intr status %x\n",		    ns->ns_if.if_unit, isr);	/* Any more to send? */	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);	if ((ns->ns_if.if_flags & IFF_OACTIVE) == 0)		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;	return (1);}/* * 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. */voidnerecv(ns)	register struct ne_softc *ns;{	int len;	int b;	register int l;	register caddr_t p;	register nec = ns->ns_base;	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(nec, ns->ns_ne1000, ns->ns_pb, ns->ns_ba,	    min(len, DS_PGSIZE - sizeof(ns->ns_ph)));	if (len > DS_PGSIZE - sizeof(ns->ns_ph)) {		l = len - (DS_PGSIZE - sizeof(ns->ns_ph));		p = ns->ns_pb + (DS_PGSIZE - sizeof(ns->ns_ph));		if(++ns->ns_cur >= ns->ns_rbufend)			ns->ns_cur = ns->ns_rbuf;		b = ns->ns_cur*DS_PGSIZE;				while (l >= DS_PGSIZE) {			nefetch(nec, ns->ns_ne1000, p, b, DS_PGSIZE);			p += DS_PGSIZE;			l -= DS_PGSIZE;			if(++ns->ns_cur >= ns->ns_rbufend)				ns->ns_cur = ns->ns_rbuf;			b = ns->ns_cur*DS_PGSIZE;		}		if (l > 0)			nefetch(nec, ns->ns_ne1000, p, b, l);	}	/* don't forget checksum! */	len -= sizeof(struct ether_header) + sizeof(long);				neread(ns, (caddr_t)(ns->ns_pb), len);}/* * Fetch from onboard ROM/RAM */voidnefetch(nec, ne1000, up, ad, len)	register nec;	int ne1000;	caddr_t up;	int ad, len;{	u_char cmd;	int cnt;	if (!ne1000 && len & 01)		len++;	cmd = inb(nec+ds_cmd);	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);	/* Setup remote dma */	outb(nec+ds0_isr, DSIS_RDC);	outb(nec+ds0_rbcr0, len);	outb(nec+ds0_rbcr1, len >> 8);	outb(nec+ds0_rsar0, ad);	outb(nec+ds0_rsar1, ad >> 8);	/* Execute & extract from card */	outb(nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);	if (ne1000)		insb(nec+ne_data, up, len);	else		insw(nec+ne_data, up, len / 2);	/* Wait till done, then shutdown feature */	cnt = 10000;	while ((inb(nec+ds0_isr) & DSIS_RDC) == 0 && --cnt)		;	outb(nec+ds0_isr, DSIS_RDC);	outb(nec+ds_cmd, cmd);}/* * Put to onboard RAM. */voidneput(nec, ne1000, up, ad, len)	register int nec;	int ne1000;	caddr_t up;	int ad, len;{	u_char cmd;	int cnt;		if (!ne1000 && len & 01)		len++;	cmd = inb(nec+ds_cmd);	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);	/* Setup for remote dma */	outb(nec+ds0_isr, DSIS_RDC);	outb(nec+ds0_rbcr0, len);	outb(nec+ds0_rbcr1, len >> 8);	outb(nec+ds0_rsar0, ad);	outb(nec+ds0_rsar1, ad >> 8);	/* Execute & stuff to card */	outb(nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);	if (ne1000)		outsb(nec+ne_data, up, len);	else		outsw(nec+ne_data, up, len / 2);		/* Wait till done, then shutdown feature */	cnt = 10000;	while ((inb(nec+ds0_isr) & DSIS_RDC) == 0 && --cnt)		;	outb(nec+ds0_isr, DSIS_RDC);	outb(nec+ds_cmd, cmd);}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */voidneread(ns, buf, len)	register struct ne_softc *ns;	char *buf;	int len;{	register struct ether_header *eh;    	struct mbuf *m;	int off, resid;	/*	 * 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;#if NBPFILTER > 0	/* For BPF.  */        /*         * 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 (ns->ns_if.if_bpf) {                eh->ether_type = htons((u_short)eh->ether_type);                bpf_tap(ns->ns_if.if_bpf, buf,		    len + sizeof(struct ether_header));                eh->ether_type = ntohs((u_short)eh->ether_type);                /*                 * Note that the interface cannot be in promiscuous mode if                 * there are no bpf listeners.  And if we are in promiscuous                 * mode, we have to check if this packet is really ours.                 */                if ((ns->ns_if.if_flags & IFF_PROMISC) &&                    bcmp(eh->ether_dhost, ns->sc_addr,                    sizeof(eh->ether_dhost)) != 0 &&#ifdef MULTICAST		    /* non-multicast (also non-broadcast) */		    !ETHER_IS_MULTICAST(eh->ether_dhost)#else                    bcmp(eh->ether_dhost, etherbroadcastaddr, 			 sizeof(eh->ether_dhost)) != 0#endif		    )			return;        }#endif /* NBPFILTER > 0 */#if 0	/*	 * Promiscuous multicast hack will cause us to receive	 * packets we don't want.  Be paranoid and always filter.	 */	if (!ETHER_IS_MULTICAST(eh->ether_dhost) &&	    bcmp(eh->ether_dhost, ns->sc_addr, sizeof(eh->ether_dhost)) != 0)		return;#endif	/*	 * 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;	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 = (struct ne_softc *) necd.cd_devs[ifp->if_unit];	register nec = ns->ns_base;	int s;	int error = 0;	s = splimp();	switch (cmd) {#ifdef PROM	case SIOCPOLL:	    if (ns->ns_if.if_flags & IFF_RUNNING)		neintr (ns);	    break;#endif	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		switch (ifa->ifa_addr->sa_family) {#ifdef INET		case AF_INET:			neinit(ifp->if_unit);			arp_ifinit((struct arpcom *)ifp, ifa);			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->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)ns->sc_addr, sizeof(ns->sc_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|IFF_OACTIVE);			outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA);		} else			neinit(ifp->if_unit);		break;#ifdef MULTICAST	/*	 * Update our multicast list.	 */	case SIOCADDMULTI:		error = ether_addmulti((struct ifreq *)data, &ns->ns_ac);		goto reset;	case SIOCDELMULTI:		error = ether_delmulti((struct ifreq *)data, &ns->ns_ac);	reset:		if (error == ENETRESET) {			neinit(ifp->if_unit);			error = 0;		}		break;#endif#ifdef notdef	case SIOCGHWADDR:		bcopy((caddr_t)ns->sc_addr, (caddr_t) &ifr->ifr_data,			sizeof(ns->sc_addr));		break;#endif	default:		error = EINVAL;	}	ns->ns_ifoldflags = ifp->if_flags;	splx(s);	return (error);}#ifdef PROM/* * eninit(): initialise ethernet *//* probe these i/o port addresses only */static const int neports[] = {0x320, 0x340, 0x360, -1};inteninit (){    static struct isa_attach_args ia;    static struct ne_softc sc;    static struct cfdata cf;    static void *devs[2];    unsigned int i;    cf.cf_unit = 0;    ia.ia_unit = 0;    for (i = 0; neports[i] > 0; i++) {	ia.ia_iobase = neports[i];	if (neprobe (NULL, &cf, &ia)) {	    necd.cd_devs = devs;	    necd.cd_devs[0] = &sc;	    neattach (NULL, (struct device *)&sc, &ia);	    return 1;	}    }    return 0;}#endif

⌨️ 快捷键说明

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