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

📄 if_le.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Ralph Campbell and Rick Macklem. * * 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. * *	@(#)if_le.c	8.2 (Berkeley) 11/16/93 */#include <le.h>#if NLE > 0#include <bpfilter.h>/* * AMD 7990 LANCE * * This driver will generate and accept trailer 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/machConst.h>#include <pmax/pmax/pmaxtype.h>#include <pmax/pmax/kn01.h>#include <pmax/pmax/kmin.h>#include <pmax/pmax/asic.h>#include <pmax/dev/device.h>#include <pmax/dev/if_lereg.h>#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endifint	leprobe();void	leintr();struct	driver ledriver = {	"le", leprobe, 0, 0, leintr,};int	ledebug = 1;		/* console error messages *//* * 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 */	volatile struct	lereg1 *sc_r1;	/* LANCE registers */	volatile void *sc_r2;	/* dual-port RAM */	int	sc_ler2pad;	/* Do ring descriptors require short pads? */	void	(*sc_copytobuf)(); /* Copy to buffer */	void	(*sc_copyfrombuf)(); /* Copy from buffer */	void	(*sc_zerobuf)(); /* and Zero bytes in buffer */	int	sc_rmd;		/* predicted next rmd to process */	int	sc_tmd;		/* last tmd processed */	int	sc_tmdnext;	/* next tmd to transmit with */	/* stats */	int	sc_runt;	int	sc_merr;	int	sc_babl;	int	sc_cerr;	int	sc_miss;	int	sc_rown;	int	sc_xint;	int	sc_uflo;	int	sc_rxlen;	int	sc_rxoff;	int	sc_txoff;	int	sc_busy;	short	sc_iflags;} le_softc[NLE];/* access LANCE registers */static void lewritereg();#define	LERDWR(cntl, src, dst)	{ (dst) = (src); DELAY(10); }#define	LEWREG(src, dst)	lewritereg(&(dst), (src))#define CPU_TO_CHIP_ADDR(cpu) \	((unsigned)(&(((struct lereg2 *)0)->cpu)))#define LE_OFFSET_RAM		0x0#define LE_OFFSET_LANCE		0x100000#define LE_OFFSET_ROM		0x1c0000void copytobuf_contig(), copyfrombuf_contig(), bzerobuf_contig();void copytobuf_gap2(), copyfrombuf_gap2(), bzerobuf_gap2();void copytobuf_gap16(), copyfrombuf_gap16(), bzerobuf_gap16();extern int pmax_boardtype;extern u_long le_iomem;extern u_long asic_base;/* * Test to see if device is present. * Return true if found and initialized ok. * If interface exists, make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */leprobe(dp)	struct pmax_ctlr *dp;{	volatile struct lereg1 *ler1;	struct le_softc *le = &le_softc[dp->pmax_unit];	struct ifnet *ifp = &le->sc_if;	u_char *cp;	int i;	extern int leinit(), lereset(), leioctl(), lestart(), ether_output();	switch (pmax_boardtype) {	case DS_PMAX:		le->sc_r1 = ler1 = (volatile struct lereg1 *)dp->pmax_addr;		le->sc_r2 = (volatile void *)MACH_PHYS_TO_UNCACHED(0x19000000);		cp = (u_char *)(MACH_PHYS_TO_UNCACHED(KN01_SYS_CLOCK) + 1);		le->sc_ler2pad = 1;		le->sc_copytobuf = copytobuf_gap2;		le->sc_copyfrombuf = copyfrombuf_gap2;		le->sc_zerobuf = bzerobuf_gap2;		break;	case DS_3MIN:	case DS_MAXINE:	case DS_3MAXPLUS:		if (dp->pmax_unit == 0) {			volatile u_int *ssr, *ldp;			le->sc_r1 = ler1 = (volatile struct lereg1 *)				ASIC_SYS_LANCE(asic_base);			cp = (u_char *)ASIC_SYS_ETHER_ADDRESS(asic_base);			le->sc_r2 = (volatile void *)				MACH_PHYS_TO_UNCACHED(le_iomem);			le->sc_ler2pad = 1;			le->sc_copytobuf = copytobuf_gap16;			le->sc_copyfrombuf = copyfrombuf_gap16;			le->sc_zerobuf = bzerobuf_gap16;			/*			 * And enable Lance dma through the asic.			 */			ssr = (volatile u_int *)ASIC_REG_CSR(asic_base);			ldp = (volatile u_int *)				ASIC_REG_LANCE_DMAPTR(asic_base);			*ldp = (le_iomem << 3);	/* phys addr << 3 */			*ssr |= ASIC_CSR_DMAEN_LANCE;			break;		}		/*		 * Units other than 0 are turbochannel option boards and fall		 * through to DS_3MAX.		 */	case DS_3MAX:		le->sc_r1 = ler1 = (volatile struct lereg1 *)			(dp->pmax_addr + LE_OFFSET_LANCE);		le->sc_r2 = (volatile void *)(dp->pmax_addr + LE_OFFSET_RAM);		cp = (u_char *)(dp->pmax_addr + LE_OFFSET_ROM + 2);		le->sc_ler2pad = 0;		le->sc_copytobuf = copytobuf_contig;		le->sc_copyfrombuf = copyfrombuf_contig;		le->sc_zerobuf = bzerobuf_contig;		break;	default:		printf("Unknown CPU board type %d\n", pmax_boardtype);		return (0);	};	/*	 * Get the ethernet address out of rom	 */	for (i = 0; i < sizeof(le->sc_addr); i++) {		le->sc_addr[i] = *cp;		cp += 4;	}	/* make sure the chip is stopped */	LEWREG(LE_CSR0, ler1->ler1_rap);	LEWREG(LE_STOP, ler1->ler1_rdp);	ifp->if_unit = dp->pmax_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);	printf("le%d at nexus0 csr 0x%x priority %d ethernet address %s\n",		dp->pmax_unit, dp->pmax_addr, dp->pmax_pri,		ether_sprintf(le->sc_addr));	return (1);}#ifdef MULTICAST/* * Setup the logical address filter */voidlesetladrf(le)	register struct le_softc *le;{	register volatile struct lereg2 *ler2 = le->sc_r2;	register struct ifnet *ifp = &le->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_ladrf0(ler2, 0);	LER2_ladrf1(ler2, 0);	ifp->if_flags &= ~IFF_ALLMULTI;	ETHER_FIRST_MULTI(step, &le->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_ladrf0(ler2, 0xff);			LER2_ladrf1(ler2, 0xff);			LER2_ladrf2(ler2, 0xff);			LER2_ladrf3(ler2, 0xff);			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. */		switch (crc >> 5) {		case 0:			LER2_ladrf0(ler2, 1 << (crc & 0x1f));			break;		case 1:			LER2_ladrf1(ler2, 1 << (crc & 0x1f));			break;		case 2:			LER2_ladrf2(ler2, 1 << (crc & 0x1f));			break;		case 3:			LER2_ladrf3(ler2, 1 << (crc & 0x1f));		}		ETHER_NEXT_MULTI(step, enm);	}}#endifledrinit(le)	struct le_softc *le;{	register volatile void *rp;	register int i;	for (i = 0; i < LERBUF; i++) {		rp = LER2_RMDADDR(le->sc_r2, i);		LER2_rmd0(rp, CPU_TO_CHIP_ADDR(ler2_rbuf[i][0]));		LER2_rmd1(rp, LE_OWN);		LER2_rmd2(rp, -LEMTU);		LER2_rmd3(rp, 0);	}	for (i = 0; i < LETBUF; i++) {		rp = LER2_TMDADDR(le->sc_r2, i);		LER2_tmd0(rp, CPU_TO_CHIP_ADDR(ler2_tbuf[i][0]));		LER2_tmd1(rp, 0);		LER2_tmd2(rp, 0);		LER2_tmd3(rp, 0);	}}lereset(unit)	register int unit;{	register struct le_softc *le = &le_softc[unit];	register volatile struct lereg1 *ler1 = le->sc_r1;	register volatile void *ler2 = le->sc_r2;	register int timo = 100000;	register int stat;#ifdef lint	stat = unit;#endif	LEWREG(LE_CSR0, ler1->ler1_rap);	LEWREG(LE_STOP, ler1->ler1_rdp);	/*	 * Setup for transmit/receive	 */#if NBPFILTER > 0	if (le->sc_if.if_flags & IFF_PROMISC)		/* set the promiscuous bit */		LER2_mode(ler2, LE_MODE | 0x8000);	else#endif		LER2_mode(ler2, LE_MODE);	LER2_padr0(ler2, (le->sc_addr[1] << 8) | le->sc_addr[0]);	LER2_padr1(ler2, (le->sc_addr[3] << 8) | le->sc_addr[2]);	LER2_padr2(ler2, (le->sc_addr[5] << 8) | le->sc_addr[4]);	/* Setup the logical address filter */#ifdef MULTICAST	lesetladrf(le);#else	LER2_ladrf0(ler2, 0);	LER2_ladrf1(ler2, 0);	LER2_ladrf2(ler2, 0);	LER2_ladrf3(ler2, 0);#endif	LER2_rlen(ler2, LE_RLEN);	LER2_rdra(ler2, CPU_TO_CHIP_ADDR(ler2_rmd[0]));	LER2_tlen(ler2, LE_TLEN);	LER2_tdra(ler2, CPU_TO_CHIP_ADDR(ler2_tmd[0]));	ledrinit(le);	le->sc_rmd = 0;	le->sc_tmd = LETBUF - 1;	le->sc_tmdnext = 0;	LEWREG(LE_CSR1, ler1->ler1_rap);	LEWREG(CPU_TO_CHIP_ADDR(ler2_mode), ler1->ler1_rdp);	LEWREG(LE_CSR2, ler1->ler1_rap);	LEWREG(0, ler1->ler1_rdp);	LEWREG(LE_CSR3, ler1->ler1_rap);	LEWREG(0, ler1->ler1_rdp);	LEWREG(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",

⌨️ 快捷键说明

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