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

📄 if_we.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* need to read these registers to clear status */		(void) inb(sc->we_io_nic_addr + 0xD);		(void) inb(sc->we_io_nic_addr + 0xE);		(void) inb(sc->we_io_nic_addr + 0xF);		++sc->we_if.if_ierrors;	}	/* normal transmit complete */	if (weisr.is_ptx || weisr.is_txe)		wetint (unit);	/* normal receive notification */	if (weisr.is_prx || weisr.is_rxe)		werint (unit);	/* try to start transmit */	westart(&sc->we_if);	/* re-enable onboard interrupts */	wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);	wecmd.cs_ps = 0;	outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);	outb(sc->we_io_nic_addr + WD_P0_IMR, 0xff/*WD_I_CONFIG*/);	weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);	if (weisr.is_byte) {		/*		 * I caught it looping forever here a couple of times,		 * but I haven't had time to figure out why.  Just		 * returning seems to be safe, and it does not appear		 * to interfere with future packets.    - Pace 5/19/92		 */		if (--nloops <= 0) {			printf ("we0: weintr is looping\n");			return;		}		goto loop;	}} /* * Ethernet interface transmit interrupt. */wetint(unit)	int unit;{	register struct we_softc *sc = &we_softc[unit];	/*	 * Do some statistics (assume page zero of NIC mapped in)	 */	sc->we_flags &= ~WDF_TXBUSY; 	sc->we_if.if_timer = 0;	++sc->we_if.if_opackets;	sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0);} /* * Ethernet interface receiver interrupt. */werint(unit)	int unit;{	register struct we_softc *sc = &we_softc[unit];	u_char bnry, curr;	long len;	union we_command wecmd;	struct we_ring *wer; 	/*	 * Traverse the receive ring looking for packets to pass back.	 * The search is complete when we find a descriptor not in use.	 */	wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);	wecmd.cs_ps = 0;	outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);	bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY);	wecmd.cs_ps = 1;	outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);	curr = inb(sc->we_io_nic_addr + WD_P1_CURR);if(Bdry)	bnry =Bdry;	while (bnry != curr)	{		/* get pointer to this buffer header structure */		wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8));		/* count includes CRC */		len = wer->we_count - 4;		if (len > 30 && len <= ETHERMTU+100			/*&& (*(char *)wer  == 1 || *(char *) wer == 0x21)*/)			weread(sc, (caddr_t)(wer + 1), len);		else printf("reject %d", len);outofbufs:		wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);		wecmd.cs_ps = 0;		outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);		/* advance on chip Boundry register */		if((caddr_t) wer + WD_PAGE_SIZE - 1 > sc->we_vmem_end) {			bnry = WD_TXBUF_SIZE;			outb(sc->we_io_nic_addr + WD_P0_BNRY,					sc->we_vmem_size / WD_PAGE_SIZE-1);			} else {			if (len > 30 && len <= ETHERMTU+100)				bnry = wer->we_next_packet;			else bnry = curr;			/* watch out for NIC overflow, reset Boundry if invalid */			if ((bnry - 1) < WD_TXBUF_SIZE) {		    		outb(sc->we_io_nic_addr + WD_P0_BNRY,					(sc->we_vmem_size / WD_PAGE_SIZE) - 1);				bnry = WD_TXBUF_SIZE;			} else				outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1);		}		/* refresh our copy of CURR */		wecmd.cs_ps = 1;		outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);		curr = inb(sc->we_io_nic_addr + WD_P1_CURR);	}Bdry = bnry;}#ifdef shit/* * Process an ioctl request. */weioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	struct we_softc *sc = &we_softc[ifp->if_unit];	struct ifaddr *ifa = (struct ifaddr *)data;	int s = splimp(), error = 0; 	switch (cmd) { 	case SIOCSIFADDR:		ifp->if_flags |= IFF_UP;		weinit(ifp->if_unit);		switch(ifa->ifa_addr->sa_family) {#ifdef INET		case AF_INET:			((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->we_addr);			else				wesetaddr(ina->x_host.c_host, ifp->if_unit);			break;		    }#endif		}		break;	case SIOCSIFFLAGS:		if (((ifp->if_flags & IFF_UP) == 0) &&		   (sc->we_flags & WDF_RUNNING)) {			westop(ifp->if_unit);		} else if (((ifp->if_flags & IFF_UP) == IFF_UP) &&		   ((sc->we_flags & WDF_RUNNING) == 0))			weinit(ifp->if_unit);		break;	default:		error = EINVAL; 	}	(void) splx(s);	return (error);}#endif /* * Process an ioctl request. */weioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ifaddr *ifa = (struct ifaddr *)data;	struct we_softc *sc = &we_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:			weinit(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->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)sc->ns_addr, sizeof(sc->ns_addr));			}			weinit(ifp->if_unit); /* does ne_setaddr() */			break;		    }#endif		default:			weinit(ifp->if_unit);			break;		}		break;	case SIOCSIFFLAGS:		if ((ifp->if_flags & IFF_UP) == 0 &&		    ifp->if_flags & IFF_RUNNING) {			ifp->if_flags &= ~IFF_RUNNING;			westop(ifp->if_unit);		} else if (ifp->if_flags & IFF_UP &&		    (ifp->if_flags & IFF_RUNNING) == 0)			weinit(ifp->if_unit);		break;#ifdef notdef	case SIOCGHWADDR:		bcopy((caddr_t)sc->sc_addr, (caddr_t) &ifr->ifr_data,			sizeof(sc->sc_addr));		break;#endif	default:		error = EINVAL;	}	splx(s);	return (error);}/* * set ethernet address for unit */wesetaddr(physaddr, unit)	u_char *physaddr;	int unit;{	register struct we_softc *sc = &we_softc[unit];	register int i;	/*	 * Rewrite ethernet address, and then force restart of NIC	 */	for (i = 0; i < ETHER_ADDR_LEN; i++)		sc->we_addr[i] = physaddr[i];	sc->we_flags &= ~WDF_RUNNING;	weinit(unit);} #define	wedataaddr(sc, eh, off, type) \	((type) ((caddr_t)((eh)+1)+(off) >= (sc)->we_vmem_end) ? \		(((caddr_t)((eh)+1)+(off))) - (sc)->we_vmem_end \		+ (sc)->we_vmem_ring: \		((caddr_t)((eh)+1)+(off)))/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */weread(sc, buf, len)	register struct we_softc *sc;	char *buf;	int len;{	register struct ether_header *eh;    	struct mbuf *m, *weget();	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);	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(*wedataaddr(sc, eh, off, u_short *));		resid = ntohs(*(wedataaddr(sc, eh, off+2, u_short *)));		if (off + resid > len) return;		/* sanity */		len = off + resid;	} else	off = 0;	len -= sizeof(struct ether_header);	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 = weget(buf, len, off, &sc->we_if, sc);	if (m == 0) return;	ether_input(&sc->we_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 *weget(buf, totlen, off0, ifp, sc)	caddr_t buf;	int totlen, off0;	struct ifnet *ifp;	struct we_softc *sc;{	struct mbuf *top, **mp, *m, *p;	int off = off0, len;	register caddr_t cp = buf;	char *epkt;	int tc =totlen;	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;		}		totlen -= len;		/* only do up to end of buffer */		if (cp+len > sc->we_vmem_end) {			unsigned toend = sc->we_vmem_end - cp;			bcopy(cp, mtod(m, caddr_t), toend);			cp = sc->we_vmem_ring;			bcopy(cp, mtod(m, caddr_t)+toend, len - toend);			cp += len - toend;			epkt = cp + totlen;		} else {			bcopy(cp, mtod(m, caddr_t), (unsigned)len);			cp += len;		}		*mp = m;		mp = &m->m_next;		if (cp == epkt) {			cp = buf;			epkt = cp + tc;		}	}	return (top);}#endif

⌨️ 快捷键说明

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