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

📄 if_le.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: hp300/dev/if_le.c	7.16 (Berkeley) 3/11/93 * *	@(#)if_le.c	8.1 (Berkeley) 6/10/93 */#include "le.h"#if NLE > 0#include "bpfilter.h"/* * AMD 7990 LANCE * * This driver will accept tailer encapsulated packets even * though it buys us nothing.  The motivation was to avoid incompatibilities * with VAXen, SUNs, and others that handle and benefit from them. * This reasoning is dubious. */#include <sys/param.h>#include <sys/proc.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/buf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/syslog.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <net/if.h>#include <net/netisr.h>#include <net/route.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#endif#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#if defined (CCITT) && defined (LLC)#include <sys/socketvar.h>#include <netccitt/x25.h>extern llc_ctlinput(), cons_rtrequest();#endif#include <machine/cpu.h>#include <machine/mtpr.h>#include <luna68k/dev/device.h>#include <luna68k/dev/if_lereg.h>#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endifint	leattach();struct	driver ledriver = {	leattach, "le",};int	ledebug = 0;		/* console error messages */int	leintr(), leinit(), leioctl(), lestart(), ether_output(), lereset();struct	mbuf *m_devget();extern	struct ifnet loif;/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * le_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct	le_softc {	struct	arpcom sc_ac;	/* common Ethernet structures */#define	sc_if	sc_ac.ac_if	/* network-visible interface */#define	sc_addr	sc_ac.ac_enaddr	/* hardware Ethernet address */	struct	lereg1 *sc_r1;	/* LANCE registers */	struct	lereg2 *sc_r2;	/* dual-port RAM */	int	sc_rmd;		/* predicted next rmd to process */	int	sc_tmd;		/* next available tmd */	int	sc_txcnt;	/* # of transmit buffers in use */	/* stats */	int	sc_runt;	int	sc_jab;	int	sc_merr;	int	sc_babl;	int	sc_cerr;	int	sc_miss;	int	sc_rown;	int	sc_xown;	int	sc_xown2;	int	sc_uflo;	int	sc_rxlen;	int	sc_rxoff;	int	sc_txoff;	int	sc_busy;	short	sc_iflags;} le_softc[NLE];/* access LANCE registers */#define	LERDWR(cntl, src, dst)	(dst) = (src)#define LE_IPL		3/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */leattach(hd)	struct hp_device *hd;{	register struct lereg2 *ler2;	struct lereg2 *lemem = (struct lereg2 *) 0;	struct le_softc *le = &le_softc[hd->hp_unit];	struct ifnet *ifp = &le->sc_if;	char *cp;	int i;	le->sc_r1 = (struct lereg1 *) hd->hp_addr;	ler2 = le->sc_r2 = (struct lereg2 *) 0x71000000;	hd->hp_ipl = LE_IPL;	/*	 * Read the ethernet address off the board, one nibble at a time.	 */#ifdef NOROM	cp = "00000a02456c";#else#if defined(LUNA2)	if (machineid == LUNA_II) {		static char rom_data[128];		volatile u_int *from = (u_int *)0xf1000004;		for (i = 0; i < 128; i++) {			*from = (i * 2) << 16;			rom_data[i] |= (*from >> 12) & 0xf0;			*from = (i * 2 + 1) << 16;			rom_data[i] |= (*from >> 16) & 0xf;		}		cp =&rom_data[6]; /* ETHER0 must be here */		/* one port only now  XXX */	} else#endif	{		cp = (char *) 0x4101FFE0;	}#endif	for (i = 0; i < sizeof(le->sc_addr); i++) {		le->sc_addr[i]  = (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9) << 4;		cp++;		le->sc_addr[i] |= (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9);		cp++;	}	printf("le%d: hardware address %s\n", hd->hp_unit,		ether_sprintf(le->sc_addr));	/*	 * Setup for transmit/receive	 */	ler2->ler2_mode = LE_MODE;	ler2->ler2_ladrf[0] = 0;	ler2->ler2_ladrf[1] = 0;	ler2->ler2_rlen = LE_RLEN;	ler2->ler2_rdra = (int)lemem->ler2_rmd;	ler2->ler2_tlen = LE_TLEN;	ler2->ler2_tdra = (int)lemem->ler2_tmd;	ifp->if_unit = hd->hp_unit;	ifp->if_name = "le";	ifp->if_mtu = ETHERMTU;	ifp->if_init = leinit;	ifp->if_reset = lereset;	ifp->if_ioctl = leioctl;	ifp->if_output = ether_output;	ifp->if_start = lestart;#ifdef MULTICAST	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;#else	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;#endif#if NBPFILTER > 0	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));#endif	if_attach(ifp);	return (1);}#ifdef MULTICAST/* * Setup the logical address filter */voidlesetladrf(sc)	register struct le_softc *sc;{	register volatile struct lereg2 *ler2 = sc->sc_r2;	register struct ifnet *ifp = &sc->sc_if;	register struct ether_multi *enm;	register u_char *cp;	register u_long crc;	register u_long c;	register int i, len;	struct ether_multistep step;	/*	 * Set up multicast address filter by passing all multicast	 * addresses through a crc generator, and then using the high	 * order 6 bits as a index into the 64 bit logical address	 * filter. The high order two bits select the word, while the	 * rest of the bits select the bit within the word.	 */	ler2->ler2_ladrf[0] = 0;	ler2->ler2_ladrf[1] = 0;	ifp->if_flags &= ~IFF_ALLMULTI;	ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);	while (enm != NULL) {		if (bcmp((caddr_t)&enm->enm_addrlo,		    (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) == 0) {			/*			 * We must listen to a range of multicast			 * addresses. For now, just accept all			 * multicasts, rather than trying to set only			 * those filter bits needed to match the range.			 * (At this time, the only use of address			 * ranges is for IP multicast routing, for			 * which the range is big enough to require all			 * bits set.)			 */			ler2->ler2_ladrf[0] = 0xffffffff;			ler2->ler2_ladrf[1] = 0xffffffff;			ifp->if_flags |= IFF_ALLMULTI;			return;		}		cp = (unsigned char *)&enm->enm_addrlo;		c = *cp;		crc = 0xffffffff;		len = 6;		while (len-- > 0) {			c = *cp;			for (i = 0; i < 8; i++) {				if ((c & 0x01) ^ (crc & 0x01)) {					crc >>= 1;					crc = crc ^ 0xedb88320;				}				else					crc >>= 1;				c >>= 1;			}			cp++;		}		/* Just want the 6 most significant bits. */		crc = crc >> 26;		/* Turn on the corresponding bit in the filter. */		ler2->ler2_ladrf[crc >> 5] |= 1 << (crc & 0x1f);		ETHER_NEXT_MULTI(step, enm);	}}#endifledrinit(ler2, le)	register struct lereg2 *ler2;	register struct le_softc *le;{	register struct lereg2 *lemem = (struct lereg2 *) 0;	register int i;	ler2->ler2_padr[0] = le->sc_addr[1];	ler2->ler2_padr[1] = le->sc_addr[0];	ler2->ler2_padr[2] = le->sc_addr[3];	ler2->ler2_padr[3] = le->sc_addr[2];	ler2->ler2_padr[4] = le->sc_addr[5];	ler2->ler2_padr[5] = le->sc_addr[4];	for (i = 0; i < LERBUF; i++) {		ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];		ler2->ler2_rmd[i].rmd1 = LE_OWN;		ler2->ler2_rmd[i].rmd2 = -LEMTU;		ler2->ler2_rmd[i].rmd3 = 0;	}	for (i = 0; i < LETBUF; i++) {		ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];		ler2->ler2_tmd[i].tmd1 = 0;		ler2->ler2_tmd[i].tmd2 = 0;		ler2->ler2_tmd[i].tmd3 = 0;	}	/* Setup the logical address filter */#ifdef MULTICAST	lesetladrf(le);#else	ler2->ler2_ladrf[0] = 0;	ler2->ler2_ladrf[1] = 0;#endif}lereset(unit)	register int unit;{	register struct le_softc *le = &le_softc[unit];	register struct lereg1 *ler1 = le->sc_r1;	register struct lereg2 *lemem = (struct lereg2 *) 0;	register int timo = 100000;	register int stat;#ifdef lint	stat = unit;#endif#if NBPFILTER > 0	if (le->sc_if.if_flags & IFF_PROMISC)		/* set the promiscuous bit */		le->sc_r2->ler2_mode = LE_MODE|0x8000;	else		le->sc_r2->ler2_mode = LE_MODE;#endif	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);	LERDWR(ler0, LE_STOP, ler1->ler1_rdp);	ledrinit(le->sc_r2, le);	le->sc_rmd = le->sc_tmd = 0;	LERDWR(ler0, LE_CSR1, ler1->ler1_rap);	LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);	LERDWR(ler0, LE_CSR2, ler1->ler1_rap);	LERDWR(ler0, 0, ler1->ler1_rdp);	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);	LERDWR(ler0, LE_INIT, ler1->ler1_rdp);	do {		if (--timo == 0) {			printf("le%d: init timeout, stat = 0x%x\n",			       unit, stat);			break;		}		LERDWR(ler0, ler1->ler1_rdp, stat);	} while ((stat & LE_IDON) == 0);	LERDWR(ler0, LE_STOP, ler1->ler1_rdp);	LERDWR(ler0, LE_CSR3, ler1->ler1_rap);	LERDWR(ler0, LE_BSWP, ler1->ler1_rdp);	LERDWR(ler0, LE_CSR0, ler1->ler1_rap);	LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);	le->sc_if.if_flags &= ~IFF_OACTIVE;	le->sc_txcnt = 0;}/* * Initialization of interface */leinit(unit)	int unit;{	register struct ifnet *ifp = &le_softc[unit].sc_if;	register struct ifaddr *ifa;	int s;	/* not yet, if address still unknown */	for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next)		if (ifa == 0)			return;		else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK)			break;	if ((ifp->if_flags & IFF_RUNNING) == 0) {		s = splimp();		ifp->if_flags |= IFF_RUNNING;		lereset(unit);	        (void) lestart(ifp);		splx(s);	}}/* * Start output on interface.  Get another datagram to send * off of the interface queue, and copy it to the interface * before starting the output. */lestart(ifp)	struct ifnet *ifp;{	register struct le_softc *le = &le_softc[ifp->if_unit];	register struct letmd *tmd;	register struct mbuf *m;	int len;	if ((le->sc_if.if_flags & IFF_RUNNING) == 0)		return (0);	tmd = &le->sc_r2->ler2_tmd[le->sc_tmd];	do {		if (tmd->tmd1 & LE_OWN) {			le->sc_xown2++;			return (0);		}		IF_DEQUEUE(&le->sc_if.if_snd, m);		if (m == 0)			return (0);		len = leput(le->sc_r2->ler2_tbuf[le->sc_tmd], m);#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_tap(ifp->if_bpf, le->sc_r2->ler2_tbuf[le->sc_tmd],				len);#endif		tmd->tmd3 = 0;		tmd->tmd2 = -len;		tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;		if (++le->sc_tmd == LETBUF) {			le->sc_tmd = 0;			tmd = le->sc_r2->ler2_tmd;		} else			tmd++;	} while (++le->sc_txcnt < LETBUF);	le->sc_if.if_flags |= IFF_OACTIVE;	return (0);}void_leintr()

⌨️ 快捷键说明

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