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

📄 am7990.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (tlen < LEMINSIZE) {		(*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);		tlen = LEMINSIZE;	}	return (tlen);}/* * Pull data off an interface. * Len is length of data, with local net header stripped. * We copy the data into mbufs.  When full cluster sized units are present * we copy into clusters. */integrate struct mbuf *am7990_get(sc, boff, totlen)	struct am7990_softc *sc;	int boff, totlen;{	register struct mbuf *m;	struct mbuf *top, **mp;	int len, pad;	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m == 0)		return (0);	m->m_pkthdr.rcvif = ifp;	m->m_pkthdr.len = totlen;	pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);	m->m_data += pad;	len = MHLEN - pad;	top = 0;	mp = &top;	while (totlen > 0) {		if (top) {			MGET(m, M_DONTWAIT, MT_DATA);			if (m == 0) {				m_freem(top);				return 0;			}			len = MLEN;		}		if (top && totlen >= MINCLSIZE) {			MCLGET(m, M_DONTWAIT);			if (m->m_flags & M_EXT)				len = MCLBYTES;		}		m->m_len = len = min(totlen, len);		(*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);		boff += len;		totlen -= len;		*mp = m;		mp = &m->m_next;	}	return (top);}/* * Pass a packet to the higher levels. */integrate voidam7990_read(sc, boff, len)	register struct am7990_softc *sc;	int boff, len;{	struct mbuf *m;	struct ether_header *eh;	if (len <= sizeof(struct ether_header) ||	    len > ETHERMTU + sizeof(struct ether_header)) {#ifdef LEDEBUG		printf("%s: invalid packet size %d; dropping\n",		    sc->sc_dev.dv_xname, len);#endif		ifp->if_ierrors++;		return;	}	/* Pull packet off interface. */	m = am7990_get(sc, boff, len);	if (m == 0) {		ifp->if_ierrors++;		return;	}	ifp->if_ipackets++;	/* We assume that the header fit entirely in one mbuf. */	eh = mtod(m, struct ether_header *);#if NBPFILTER > 0	/*	 * Check if there's a BPF listener on this interface.	 * If so, hand off the raw packet to BPF.	 */	if (ifp->if_bpf)		bpf_mtap(ifp->if_bpf, m);#endif#ifdef LANCE_REVC_BUG	/*	 * The old LANCE (Rev. C) chips have a bug which causes	 * garbage to be inserted in front of the received packet.	 * The work-around is to ignore packets with an invalid	 * destination address (garbage will usually not match).	 * Of course, this precludes multicast support...	 */	if (ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr) &&	    ETHER_CMP(eh->ether_dhost, etherbroadcastaddr)) {		m_freem(m);		return;	}#endif#if defined(__bsdi__) || defined(PROM)	eh->ether_type = ntohs(eh->ether_type);#endif	/* Pass the packet up, with the ether header sort-of removed. */	m_adj(m, sizeof(struct ether_header));	ether_input(ifp, eh, m);}integrate voidam7990_rint(sc)	struct am7990_softc *sc;{	register int bix;	int rp;	struct lermd rmd;	bix = sc->sc_last_rd;	/* Process all buffers with valid data. */	for (;;) {		rp = LE_RMDADDR(sc, bix);		(*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));		if (rmd.rmd1_bits & LE_R1_OWN)			break;		if (rmd.rmd1_bits & LE_R1_ERR) {			if (rmd.rmd1_bits & LE_R1_ENP) {#ifdef LEDEBUG				if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {					if (rmd.rmd1_bits & LE_R1_FRAM)						printf("%s: framing error\n",						    sc->sc_dev.dv_xname);					if (rmd.rmd1_bits & LE_R1_CRC)						printf("%s: crc mismatch\n",						    sc->sc_dev.dv_xname);				}#endif			} else {				if (rmd.rmd1_bits & LE_R1_OFLO)					printf("%s: overflow\n",					    sc->sc_dev.dv_xname);			}			if (rmd.rmd1_bits & LE_R1_BUFF)				printf("%s: receive buffer error\n",				    sc->sc_dev.dv_xname);			ifp->if_ierrors++;		} else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=		    (LE_R1_STP | LE_R1_ENP)) {			printf("%s: dropping chained buffer\n",			    sc->sc_dev.dv_xname);			ifp->if_ierrors++;		} else {#ifdef LEDEBUG			if (sc->sc_debug)				am7990_recv_print(sc, sc->sc_last_rd);#endif			am7990_read(sc, LE_RBUFADDR(sc, bix),			    (int)mtohs(rmd.rmd3) - 4);		}		rmd.rmd1_bits = LE_R1_OWN;		rmd.rmd2 = htoms(-LEBLEN | LE_XMD2_ONES);		rmd.rmd3 = htoms(0);		(*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));#ifdef LEDEBUG		if (sc->sc_debug)			printf("sc->sc_last_rd = %x, rmd: "			       "ladr %04x, hadr %02x, flags %02x, "			       "bcnt %04x, mcnt %04x\n",				sc->sc_last_rd,				rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,				rmd.rmd2, rmd.rmd3);#endif		if (++bix == sc->sc_nrbuf)			bix = 0;	}	sc->sc_last_rd = bix;}integrate voidam7990_tint(sc)	register struct am7990_softc *sc;{	register int bix;	struct letmd tmd;	bix = sc->sc_first_td;	for (;;) {		if (sc->sc_no_td <= 0)			break;		(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),		    sizeof(tmd));#ifdef LEDEBUG		if (sc->sc_debug)			printf("trans tmd: "			    "ladr %04x, hadr %02x, flags %02x, "			    "bcnt %04x, mcnt %04x\n",			    tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,			    tmd.tmd2, tmd.tmd3);#endif		if (tmd.tmd1_bits & LE_T1_OWN)			break;		ifp->if_flags &= ~IFF_OACTIVE;		if (tmd.tmd1_bits & LE_T1_ERR) {			if (mtohs(tmd.tmd3) & LE_T3_BUFF)				printf("%s: transmit buffer error\n",				    sc->sc_dev.dv_xname);			else if (mtohs(tmd.tmd3) & LE_T3_UFLO)				printf("%s: underflow\n", sc->sc_dev.dv_xname);			if (mtohs(tmd.tmd3) & (LE_T3_BUFF | LE_T3_UFLO)) {				am7990_reset(sc);				return;			}			if (mtohs(tmd.tmd3) & LE_T3_LCAR) {				if (sc->sc_nocarrier)					(*sc->sc_nocarrier)(sc);				else					printf("%s: lost carrier\n",					    sc->sc_dev.dv_xname);			}			if (mtohs(tmd.tmd3) & LE_T3_LCOL)				ifp->if_collisions++;			if (mtohs(tmd.tmd3) & LE_T3_RTRY) {				printf("%s: excessive collisions, tdr %d\n",				    sc->sc_dev.dv_xname,				       mtohs(tmd.tmd3) & LE_T3_TDR_MASK);				ifp->if_collisions += 16;			}			ifp->if_oerrors++;		} else {			if (tmd.tmd1_bits & LE_T1_ONE)				ifp->if_collisions++;			else if (tmd.tmd1_bits & LE_T1_MORE)				/* Real number is unknown. */				ifp->if_collisions += 2;			ifp->if_opackets++;		}		if (++bix == sc->sc_ntbuf)			bix = 0;		--sc->sc_no_td;	}	sc->sc_first_td = bix;	am7990_start(ifp);	if (sc->sc_no_td == 0)		ifp->if_timer = 0;}/* * Controller interrupt. */intam7990_intr(arg)	register void *arg;{	register struct am7990_softc *sc = arg;	register u_int16_t isr;	isr = (*sc->sc_rdcsr)(sc, LE_CSR0);	if ((isr & LE_C0_INTR) == 0)		return (0);	(*sc->sc_wrcsr)(sc, LE_CSR0,	    isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |		   LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));	if (isr & LE_C0_ERR) {		if (isr & LE_C0_BABL) {#ifdef LEDEBUG			printf("%s: babble\n", sc->sc_dev.dv_xname);#endif			ifp->if_oerrors++;		}#if 0		if (isr & LE_C0_CERR) {			printf("%s: collision error\n", sc->sc_dev.dv_xname);			ifp->if_collisions++;		}#endif		if (isr & LE_C0_MISS) {#ifdef LEDEBUG			printf("%s: missed packet\n", sc->sc_dev.dv_xname);#endif			ifp->if_ierrors++;		}		if (isr & LE_C0_MERR) {			printf("%s: memory error\n", sc->sc_dev.dv_xname);			am7990_reset(sc);			return (1);		}	}	if ((isr & LE_C0_RXON) == 0) {		printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);		ifp->if_ierrors++;		am7990_reset(sc);		return (1);	}	if ((isr & LE_C0_TXON) == 0) {		printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);		ifp->if_oerrors++;		am7990_reset(sc);		return (1);	}	if (isr & LE_C0_RINT)		am7990_rint(sc);	if (isr & LE_C0_TINT)		am7990_tint(sc);	return (1);}#undef	ifp#ifdef PROMam7990_watchdog(int unit)#elseam7990_watchdog(struct ifnet *ifp)#endif{#ifdef PROM        struct am7990_softc *sc = UNIT_TO_SOFTC(unit);#else	struct am7990_softc *sc = IFP_TO_SOFTC(ifp);#endif	log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);#ifndef PROM	++ifp->if_oerrors;#endif	am7990_reset(sc);}/* * Setup output on interface. * Get another datagram to send off of the interface queue, and map it to the * interface before starting the output. * Called only at splimp or interrupt level. */ifnet_ret_tam7990_start(ifp)	register struct ifnet *ifp;{	register struct am7990_softc *sc = IFP_TO_SOFTC(ifp);	register int bix;	register struct mbuf *m;	struct letmd tmd;	int rp;	int len;	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)		return;#ifdef PROM	if (!am7990_linkstatus (sc))	    return;#endif	bix = sc->sc_last_td;	for (;;) {		rp = LE_TMDADDR(sc, bix);		(*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));		if (tmd.tmd1_bits & LE_T1_OWN) {			ifp->if_flags |= IFF_OACTIVE;			printf("missing buffer, no_td = %d, last_td = %d\n",			    sc->sc_no_td, sc->sc_last_td);		}		IF_DEQUEUE(&ifp->if_snd, m);		if (m == 0)			break;#if NBPFILTER > 0		/*		 * If BPF is listening on this interface, let it see the packet		 * before we commit it to the wire.		 */		if (ifp->if_bpf)			bpf_mtap(ifp->if_bpf, m);#endif		/*		 * Copy the mbuf chain into the transmit buffer.		 */		len = am7990_put(sc, LE_TBUFADDR(sc, bix), m);#ifdef LEDEBUG		if (len > ETHERMTU + sizeof(struct ether_header))			printf("packet length %d\n", len);#endif		ifp->if_timer = 5;		/*		 * Init transmit registers, and set transmit start flag.		 */		tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;		tmd.tmd2 = htoms(-len | LE_XMD2_ONES);		tmd.tmd3 = htoms(0);		(*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));#ifdef LEDEBUG		if (sc->sc_debug)			am7990_xmit_print(sc, sc->sc_last_td);#endif		(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);		if (++bix == sc->sc_ntbuf)			bix = 0;		if (++sc->sc_no_td == sc->sc_ntbuf) {			ifp->if_flags |= IFF_OACTIVE;			break;		}	}	sc->sc_last_td = bix;}/* * Process an ioctl request. */intam7990_ioctl(ifp, cmd, data)	register struct ifnet *ifp;	u_long cmd;	caddr_t data;{	register struct am7990_softc *sc = IFP_TO_SOFTC(ifp);	struct ifaddr *ifa = (struct ifaddr *)data;	struct ifreq *ifr = (struct ifreq *)data;	int s, error = 0;	s = splimp();#ifndef PROM	if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {		splx(s);		return error;	}#endif	switch (cmd) {#ifdef PROM    case SIOCPOLL:/*printf ("am7990_iocyl: poll\n");*/	am7990_intr(sc);	break;#endif	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;

⌨️ 快捷键说明

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