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

📄 if_ie.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic        char sccsid[] = "@(#)if_ie.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1988 by Sun Microsystems, Inc. */#ifndef sun4c	/* to end of file *//*  * Parameters controlling TIMEBOMB action: times out if chip hangs. * */#define	TIMEBOMB	1000000		/* One million times around is all... */#define	TIMEOUT		-1		/* if (function()) return (TIMEOUT); */#define	OK		0		/* Traditional OK value *//* * Sun Intel Ethernet Controller interface */#include <stand/saio.h>#include <stand/param.h>#include <sys/socket.h>#include <boot/if.h>#include <netinet/in.h>#include <boot/if_ether.h>#include <sunif/if_iereg.h>#include <sunif/if_mie.h>#include <sunif/if_obie.h>#include <sunif/if_tie.h>#include <mon/idprom.h>#ifdef sun4#include <machine/mmu.h>#include <sun4/cpu.h>#include <sun4/iocache.h>#include <sun4/pte.h>#include <sun4/enable.h>#endif sun4#include <mon/cpu.map.h>#ifdef sun3x#include <sun3x/devaddr.h>#endif sun3x/* * Never did get IO Caching the rbufs to work -- somehow the flush * didn't seem to work.  But since we boot fine with an IO Cached * xmit buf, and multiple non-IO-Cached rbufs, I left it that way. */#ifdef IOC_RBUF#undef IOC_RBUF#endif IOC_RBUFint	iexmit(), iepoll(), iereset(), myetheraddr(), iestats();unsigned long iestd[] = { 0x88000, 0x8C000 };#define NSTD 2struct saif ieif = {	iexmit,	iepoll,	iereset,	myetheraddr,	iestats};#define	IEVVSIZ		1024		/* # of pages in page map */#define IEPHYMEMSIZ	(16*1024)#define IEVIRMEMSIZ	(16*1024)#define IEPAGSIZ	1024#define	IERBUFSIZ	1600	/* Multiple of 32 bytes, for 4/470 IOC */#define	IEXBUFSIZ	1600	/* Multiple of 32 bytes, for 4/470 IOC */#ifdef sun2#define	IEDMABASE	0x000000	/* Can access all of memory */#endif sun2#ifdef sun3#define	IEDMABASE	0x0F000000	/* Can access top 16MB of memory */#endif sun3#ifdef sun3x#define	IEDMABASE	0xFF000000	/* Can access top 16MB of memory */#endif sun3x#ifdef sun4#define	IEDMABASE	0xFF000000	/* Can access top 16MB of memory */#endif sun4/* Location in virtual memory of the SCP (System Configuration Pointer) */#define SCP_LOC (char *)(IEDMABASE+IESCPADDR)/* controller types */#define IE_MB	1	/* Multibus */#define	IE_OB	2	/* onboard */#define	IE_TE	3	/* 3E *//* 2nd ethernet multibus ie1 defines */#define IE_MB_PA_MEM		0xe40000#define IE_MB_PA_REG		0xe88000/* 3E releated defines */#define IE_TE_BOARD		0x300000#define IE_TE_CSR		(IE_TE_BOARD + 0x1ff02)#define IE_TE_BUFFER		(IE_TE_BOARD + 0x20000)#define IE_TE_SCP_OFFSET	0x1fff6#define	IENRBUF	8	/* # of receive rfd's, rbd's, and rbuf's */struct ie_softc {	/*	 * This first item does two things.  First, it reserves space for	 * all the various protocols that need to put their locals somewhere	 * (it was decided that HERE is convenient!).  Second, it fills	 * out the structure to align es_scp to the wierd-in address	 * that Intel (thanks guys) fetches it from.	 */	char	es_fill[PROTOSCRATCH - sizeof(struct iescp)]; /* Align */	struct	iescp	es_scp;		/* System config pointer (used once) */	/* page boundary should be here */	struct	ieiscp	es_iscp;	/* Intermediate sys config ptr (once) */	struct	iescb	es_scb;		/* Sys Control Block, the real mama */	struct	ierbd	es_rbdtab[IENRBUF];	struct	ierfd	es_rfdtab[IENRBUF];	struct	ietfd	es_tfd;	struct	ietbd	es_tbd;	struct	mie_device *es_mie;	struct	obie_device *es_obie;	struct	tie_device *es_tie;	short	es_type;	struct	ieiaddr	es_iaddr;	/* Cmd to set up our Ethernet addr */	struct	ieconf	es_ic;		/* Cmd to configure the chip */	/*	 * The Sun-3/E VME board can address buffers only if they	 * are on-board.  For this reason, Sun-3 declares es_rubfs[]	 * and es_xbuf statically inside ie_softc which lives on-board.	 * The Sun-4/490 needs to put ie_softc inside special ethernet	 * descriptor RAM, but these static buffers would not fit.	 * For this reason, and the fact that the 490 needs to I/O Cache	 * the xbuf to prevent underruns, Sun-4 allocates es_rbufs[] and	 * es_xbuf dynamically.	 */#ifdef sun4	char	*es_rbufs[IENRBUF];	char	*es_xbuf;	/* only one, must be NULL till allocated */#else	char	es_rbufs[IENRBUF][IERBUFSIZ];	char	es_xbuf[IEXBUFSIZ];#endif	struct	ierfd	*es_rfdhd;	/* points to first rfd */};/* Statistics counters for iestats() */static struct {	int	ipackets;	int	opackets;	int	collis;	int	defer;	int	crcerrs;	int	alnerrs;	int	rscerrs;	int	orunerrs;	int	urunerrs;} stats;/* * Convert big endian address to Intel 24-bit address. */#define put_ieaddr(addr, where) { \	register char *cp; \	union { \		int	n; \		char	c[4]; \	} a; \ \	a.n = (int)(addr); \	cp = (char *)(where); \	cp[0] = a.c[3]; \	cp[1] = a.c[2]; \	cp[2] = a.c[1]; \} /* * This initializes the onboard Ethernet control reg to: *	Reset is active *	Loopback is NOT active *	Channel Attn is not active *	Interrupt enable is not active. * Loopback is deactivated due to a bug in the Intel serial interface * chip.  This chip powers-up in a locked up state if Loopback is active. * It "unlocks" itself if you release Loopback; then it's OK to reassert it. */struct obie_device obie_reset = {0, 1, 0, 0, 0, 0, 0};ieoff_t to_ieoff();ieaddr_t to_ieaddr();ieint_t	from_ieint();#ifdef sun4void ieallocbufs();#endif sun4extern int verbosemode;struct	ierfd	*prevrfd(), *nextrfd();struct devinfo ieinfo = {	sizeof (struct mie_device),	sizeof(struct ie_softc),	0,	NSTD,	iestd,	MAP_MBMEM,	0				/* transfer size handled by ND */};int xxprobe(), xxboot(), ieopen(), ieclose(), etherstrategy(), nullsys();struct boottab iedriver = {	"ie",	xxprobe,	xxboot,	ieopen,		ieclose,	etherstrategy,	"ie: Sun/Intel Ethernet",	&ieinfo,};struct idprom id;/* * Open Intel Ethernet nd connection, return -1 for errors. */ieopen(sip)	struct saioreq *sip;{	register int result;	sip->si_sif = &ieif;	if ( ieinit(sip) || (result = etheropen(sip)) < 0 ) {		ieclose(sip);		/* Make sure we kill chip */		return (-1);	}	return (result);}/* * Set up memory maps and Ethernet chip. * Returns 1 for error, 0 for ok. */intieinit(sip)	struct saioreq *sip;{	register struct ie_softc *es = (struct ie_softc *)0;	int paddr;	int i;	register struct mie_device *mie;	struct miepg *pg;	short *ap;	if (idprom(IDFORM_1, &id) != IDFORM_1) {		printf("not supported\n");		return (1);	}	switch (id.id_machine) {	case IDM_SUN2_MULTI:		mie = (struct mie_device *) sip->si_devaddr;		mie->mie_peack = 1;		mie->mie_noloop = 0;		mie->mie_ie = 0;		mie->mie_pie = 0;		paddr = mie->mie_mbmhi << 16;		ap = (short *)mie->mie_pgmap;		for (i=0; i<IEVVSIZ; i++)	/* note: sets p2mem -> 0 */			*ap++ = 0;		for (i=0; i<IEPHYMEMSIZ/IEPAGSIZ; i++) {			mie->mie_pgmap[0].mp_pfnum = i;		}		pg = &mie->mie_pgmap[0];		for (i=0; i<IEVIRMEMSIZ/IEPAGSIZ; i++) {			pg->mp_swab = 1;			pg->mp_pfnum = i;			pg++;		}		/* last page for chip init */		mie->mie_pgmap[IEVVSIZ-1].mp_pfnum = (PROTOSCRATCH/IEPAGSIZ)-1;		es = (struct ie_softc *)			devalloc(MAP_MBMEM, paddr, sizeof (struct ie_softc));		bzero((char *)es, sizeof *es);		es->es_type = IE_MB;		es->es_mie = mie;		break;	case IDM_SUN3_E:		/* 3E ethernet */		es = (struct ie_softc *)			devalloc(MAP_VME24A16D, IE_TE_BUFFER, IE_TE_MEMSIZE);		bzero((char *)es, IE_TE_MEMSIZE);		es->es_tie = (struct tie_device *)devalloc(MAP_VME24A16D,			IE_TE_CSR, sizeof (struct tie_device));		es->es_type = IE_TE;		break;#if defined(sun4)	case IDM_SUN4_SUNRAY:		/* if this is a sunray ie0, the iocache has to be used */		if (sip->si_ctlr == 0 || sip->si_ctlr == 0x88000) {			struct pte pte;			char *temp;			register u_int *p;			/*			 * for sunray IOC_IEDESCR_ADDR is the magic address			 * where the 4K sunray descriptor cache sits.			 * everything in ie_softc will fit; we double			 * map the page before it so that the scp is at			 * the end of the page at the "hard-weird" address.			 */			sunray_ioc_init();			/* grab a page for the scp */			p = (u_int *)&pte;			temp = resalloc(RES_MAINMEM, PAGESIZE);			*p = getpgmap(temp);			pte.pg_nc = 1;			setpgmap(IOC_IEDESCR_ADDR - PAGESIZE, *p);			*p = getpgmap(IOC_IEDESCR_ADDR);			pte.pg_ioc = 1;			setpgmap(IOC_IEDESCR_ADDR, *p);			es = (struct ie_softc *)(IOC_IEDESCR_ADDR - PAGESIZE);			es->es_type = IE_OB;			es->es_obie = (struct obie_device *)				devalloc(MAP_OBIO, VIOPG_ETHER<<BYTES_PG_SHIFT,					sizeof (struct obie_device));			break;		}		/* if not onboard, fall through to default */#endif /* sun4 */	default:		if (sip->si_ctlr == 0 || ((sip->si_ctlr == 0x88000) &&					(id.id_machine != IDM_SUN4_SUNRAY))) {			/* onboard Ethernet */			es = (struct ie_softc *)sip->si_dmaaddr;			bzero((char *)es, sizeof *es);			es->es_type = IE_OB;#ifdef sun3x			es->es_obie = (struct obie_device *)				devalloc(MAP_OBIO, OBIO_INTEL_ETHER,					sizeof (struct obie_device));#else sun3x			es->es_obie = (struct obie_device *)				devalloc(MAP_OBIO, VIOPG_ETHER<<BYTES_PG_SHIFT,					sizeof (struct obie_device));#endif sun3x		} else if ((sip->si_ctlr == 1) || (sip->si_ctlr == 0x8c000)) {			/* ie1 multibus in vme */			mie = (struct mie_device *)				devalloc(MAP_VME24A16D, IE_MB_PA_REG,					sizeof (struct mie_device));			sip->si_devaddr = (char *)mie;			/* probably need only a page */			es = (struct ie_softc *)				devalloc(MAP_VME24A16D, IE_MB_PA_MEM,					IEPHYMEMSIZ);			sip->si_devdata = (char *)es;			ie_putval(mie, &es->es_mie);			mie->mie_reset = 1;			DELAY(200);			mie->mie_peack = 1;			mie->mie_noloop = 0;			DELAY(40);			mie->mie_ie = 0;			mie->mie_pie = 0;			mie->mie_reset = 0;			DELAY(200);			ap = (short *)&mie->mie_pgmap[0];			for (i=0; i<IEVVSIZ; i++) /* note: sets p2mem -> 0 */				*ap++ = 0;			for (i=0; i<IEPHYMEMSIZ/IEPAGSIZ; i++) {				mie->mie_pgmap[0].mp_pfnum = i;				bzero((char *)es + (IEPAGSIZ*i), IEPAGSIZ);			}			pg = &mie->mie_pgmap[0];			for (i=0; i<IEVIRMEMSIZ/IEPAGSIZ; i++) {				pg->mp_swab = 1;				pg->mp_pfnum = i;				pg++;			}			/* last page for chip init */			mie->mie_pgmap[IEVVSIZ-1].mp_pfnum =					(PROTOSCRATCH/IEPAGSIZ)-1;			es->es_type = IE_MB;		} else if (sip->si_ctlr == 2) {			/* 3E ethernet */			es = (struct ie_softc *) devalloc(MAP_VME24A32D,				IE_TE_BUFFER, IE_TE_MEMSIZE);			bzero((char *)es, IE_TE_MEMSIZE);			es->es_tie = (struct tie_device *)				devalloc(MAP_VME24A16D, IE_TE_CSR,					sizeof (struct tie_device));			es->es_type = IE_TE;		}		break;	}	/* FIXME, release multibus resources ifdef. */	sip->si_devdata = (caddr_t)es;	return iereset(es, sip);}/* * Basic 82586 initialization * Returns 1 for error, 0 for ok. *//*ARGSUSED*/intiereset(es, sip)	register struct ie_softc *es;	struct saioreq *sip;{	struct ieiscp *iscp = &es->es_iscp;	struct iescb *scb = &es->es_scb;	struct ieiaddr *iad = &es->es_iaddr;	struct ieconf *ic = &es->es_ic;	int j;	int savepmap;	register struct obie_device *obie;	register struct tie_device *tie;	register struct mie_device *mie;	struct iescp *te_scp;#ifdef sun4	register char *addr;	register short savesegno;#endif sun4	for (j = 0; j < 10; j++) {		/* Set up the control blocks for initializing the chip */		bzero((caddr_t)&es->es_scp, sizeof (struct iescp));		bzero((caddr_t)iscp, sizeof (struct ieiscp));		bzero((caddr_t)scb, sizeof (struct iescb));		iscp->ieis_busy = 1;		iscp->ieis_scb = to_ieoff(es, (caddr_t)scb); 		if (es->es_type != IE_MB) {			es->es_scp.ies_iscp = to_ieaddr(es, (caddr_t)iscp);			iscp->ieis_cbbase = to_ieaddr(es, (caddr_t)es);		} else {			put_ieaddr((caddr_t)iscp - (caddr_t)es,				&es->es_scp.ies_iscp);			put_ieaddr(0, &iscp->ieis_cbbase);		} 		switch (es->es_type) {		case IE_OB:			obie = es->es_obie;			/*			 * The 82586 has bugs that require us to be in 			 * loopback mode while we initialize it, to avoid			 * transitions on CRS (carrier sense).			 * 			 * However, the Intel serial interface chip used			 * on Carrera also has bugs: if it powers-up in			 * loopback, you have to release loopback at least			 * once to make it behave -- it powers up with			 * CRS and CDT permanently active, which rapes the 586.			 *			 * How do you spell "broken"?  I-N-T-E-L...			 */			*obie = obie_reset;	/* Reset chip & interface */			DELAY(40);			obie->obie_noloop = 0;	/* Put it in loopback now */			DELAY(40);			obie->obie_noreset = 1;	/* Release Reset on 82586 */			DELAY(300);			/*			 * Now set up to let the Ethernet chip read the SCP.			 * Intel wired in the address of the SCP.  It happens			 * to be 0xFFFFF6.			 */#ifdef sun4			if (id.id_machine != IDM_SUN4_SUNRAY) {				addr = resalloc(RES_RAWVIRT, 2*BYTESPERSEG);				savesegno = getsegmap((int)SCP_LOC);				setsegmap(SCP_LOC, getsegmap((int)(addr +					BYTESPERSEG - 4)));			}#endif sun4			savepmap = getpgmap(SCP_LOC);			setpgmap(SCP_LOC, getpgmap((char *)&es->es_scp));			break;		case IE_MB:			mie = (struct mie_device *)sip->si_devaddr;			mie->mie_reset = 1;			DELAY(20);			mie->mie_noloop = 0;			DELAY(20);			mie->mie_reset = 0;			DELAY(200);			break;		case IE_TE:			tie = es->es_tie;			te_scp = (struct iescp *)#ifdef sun4			    (((caddr_t) es) + IE_TE_SCP_OFFSET - 2);#else			    (((caddr_t) es) + IE_TE_SCP_OFFSET);#endif sun4			bcopy((caddr_t) &es->es_scp,(caddr_t)te_scp,			    sizeof(struct iescp));			tie->tie_reset = 1;			DELAY(20);			*(char *)&tie->tie_status = 0;			DELAY(200);			break;		default:			printf("iereset: unknown interface\n");			break;		}		/*		 * We are set up.  Give the chip a zap, then wait up to		 * 1 sec, or until chip comes ready.		 */		ieca(es);		CDELAY(iscp->ieis_busy != 1, 1000);		/* Whether or not it worked, we have to clean up. */		switch (es->es_type) {		case IE_OB:			/* If it didn't init, reset chip again. */			if (iscp->ieis_busy == 1)				obie->obie_noreset = 0;			setpgmap(SCP_LOC, savepmap);#ifdef sun4			if (id.id_machine != IDM_SUN4_SUNRAY)				setsegmap(SCP_LOC, savesegno);#endif sun4			break;		case IE_MB:		case IE_TE:			break;		}		if (iscp->ieis_busy == 1)			continue;	/* Continue loop until we get it */		/*		 * Now try to run a few simple commands before we say "OK".		 */		bzero((caddr_t)iad, sizeof (struct ieiaddr));		iad->ieia_cb.iec_cmd = IE_IADDR;		myetheraddr((struct ether_addr *)iad->ieia_addr);		if (iesimple(es, &iad->ieia_cb)) {			printf("ie: hang while setting Ethernet address.\n");			continue;		}		iedefaultconf(ic);		if (iesimple(es, &ic->ieconf_cb)) {			printf("ie: hang while setting chip config.\n");			continue;		}		/*		 * Take the Ethernet interface chip out of loopback mode, i.e.		 * put us on the wire.  We can't do this before having		 * initialized the Ethernet chip because the chip does random		 * things if its 'wire' is active between the time it's reset		 * and the first CA.  Also, the IA-setup and configure commands		 * will hang under some conditions unless the interface is		 * very quiet and still.		 */		switch (es->es_type) {		case IE_OB:			obie->obie_noloop = 1;			break;		case IE_MB:			mie->mie_noloop = 1; 			break;		case IE_TE:			tie->tie_noloop = 1;			break;		default:			break;		}#ifdef sun4		ieallocbufs(es);#endif sun4		ierfdinit(es);		if (ierustart(es)) {			printf("ie: hang while starting receiver.\n");			continue;		}					return 0;		/* It all worked! */	}	/* We tried a bunch of times, no luck. */	printf("ie: cannot initialize\n");	return 1;}/* * Return pointer to previous rfd in rfd ring. */struct ierfd*prevrfd(es, rfd)struct ie_softc *es;struct ierfd *rfd;{	if (--rfd >= es->es_rfdtab)		return (rfd);	else		return (&es->es_rfdtab[IENRBUF-1]);}/* * Return pointer to next rfd in rfd ring. */struct ierfd*nextrfd(es, rfd)struct ie_softc	*es;struct ierfd *rfd;{	if (++rfd < &es->es_rfdtab[IENRBUF])		return (rfd);	else		return (es->es_rfdtab);}/* *	Initialize the Receive Unit data structures. *	Chain the es_rfdtab[] entries into a ring *	with each rfd getting one rbd and each rbd getting one rbuf. *	es->es_rfdhd always points to the first rfd in the ring *	and the "tail" of the rfd ring is always prevrfd(es, es->es_rfdhd) *	which makes things pretty simple. */ierfdinit(es)register struct ie_softc *es;{	register	int	i;	struct	ierfd	*rfd;	struct	ierbd	*rbd;	char	*rbuf;	/*	 * Zero the rfd and rbd tables.	 */

⌨️ 快捷键说明

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