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

📄 if_ni.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * if_ni.c */#ifndef lintstatic char *sccsid = "@(#)if_ni.c	4.3      ULTRIX  3/7/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1986-89 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/#include "bvpni.h"#if NBVPNI > 0 || defined(BINARY)/* Modification History: * * 24-Feb-91 - jsd *	Allow loopback packets if COPYALL mode is set * * 28-Oct-89 - Uttam Shikarpur						 *	Added:								 *		1) Reporting counters for multicast packs. and bytes	 *		2) Ability to report back the type of network interface. * * 3-May-89 Uttam Shikarpur *      Add support for Ethernet packet filter *      Moved common read code to ../net/ether_read.c * * 3-Mar-89 U. Sinkewicz * 	Picked up R. Bhanukitsiri changes for pmax/vax. * * 28-Dec-88 Fred L. Templin *	Rearranged "nistart" to schedule an interrupt for every datagram *	sent. (Instead of just NFS and broadcast loopbacks as was done *	before). This prevents temporary transmit-side livelocks in the *	case of many transmits enqueued WITHOUT any receive datagrams *	to trigger an interrupt. * * 16-Sep-88 condylis *	Unlocked lk_ni_softc during call to m_freem in nirecv to permit *	the acquisition of locks in the free routine specified in *	the mclgetx call for the mbuf * * 22-Aug-88 U. Sinkewicz *	Changed flags to KM_ALLOC calls to prevent any possibility of *	sleeping.  Needed for SMP. * * 22-Jun-88 Fred L. Templin *	Moved m_compress() code into the nistart routine, and used MCLGET *	instead of messing around with little mbuf's, since the	old scheme *	could possibly leave you with a chain that's still too long to be *	mapped onto a command queue entry. Fixed another bug in which the *	start routine wasn't checking to see if an mbuf was actually a *	cluster-type mbuf before checking the m_cltype field. This could *	possibly generate unnecessary interrupts for non-cluster mbufs. *	Also, added check to make sure that nioutput isn't called with *	the interface down. * * 10-Jun-88 lp *	Crank up in niinit when laying out bde's to keep reset from *	corrupting them. * * 15-Jan-88 lp (Larry Palmer) *			Minor rewrite to better use allocated mbufs. *			43BSD support added. NO MORE PAGE FLIPPING! * * 25-Aug-87  -- templin@decvax *			Added fix pointed out by Ed Ferris which subtracts *			the CRC field length from the length of the data field *			used by niget(). Also added code to avoid reporting *			non-error free queue exhaustions. * 28-Jul-87  -- lp *			Fix problem with multiple interfaces. * * 07-Jul-87  -- templin@decvax *			Fixed "ni_counters" type casts to correct a *			word ordering problem with the counters. * 31-Mar-87  -- lp	 *			Put apa back on a reset for decnet. * 06-Feb-87  -- lp *			Check return of ifproto_type to gaurantee that *			we dont jump to 0. * 28-Jan-87  -- lp *			Cleanup as LINT showed some extra *			variables. * * 12-Dec-86  -- lp	Post FT-v2.0. Added dpaddr, Bumped up  *			freeq0 allocation. * * 23-Oct-86  -- lp	Type 2 mbuf are forced to return on respq. * * 2-Sep-86   -- lp	Cleanup. Bugfix for long (improperly chained) *			packets. * * 7-Aug-86   -- lp	Removed some printf's ('I' baseline). * * 7-Jul-86   -- lp	Fixed a timing problem in niattach. * * 5-Jun-86   -- lp 	Fixed a little bug in reset code. * * 5-Jun-86   -- jaw 	changes to config. * * 22 May 86 -- bjg *	Include types.h and errlog.h for error logging. * * 21 May 86 -- lp *	Reworked sptdb routine to allow clear prior to setting. Bugfixes *	for decnet. Errlog for SUME errors. * * 08 May 86 -- lp *	Trailer packets work. General cleanup. Vaddr no longer saved *	in receive packets. * * 09 Apr 1986 -- lp * 	DEC AIE/NI ethernet driver *		By  * 	Larry Palmer (decvax!lp). *	(rev 40 or higher aie firmware needed) * */#include "packetfilter.h"	/* NPACKETFILTER */#include "../data/if_ni_data.c"#include "../h/types.h"#include "../h/errlog.h"extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern int net_output();struct	mbuf *niget();int	niattach(), bvpniintr(), niprobe();int	niinit(),nistart(),niioctl(),nireset(), ni_ignore;u_char  ni_multi[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00};u_char  ni_notset[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};u_short nistd[] = { 0 };#define vaddr(y) \((char *)(((unsigned long)(ptetosv((struct pte *)((y)->pt_addr))))+(y)->offset))int nidebug = 0;int ni_fqe = 0;/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets.  We get the ethernet address here. * We initialize big mbuf storage for receives here. */niattach(ni)	struct ni *ni;{	register struct ni_softc *ds = &ni_softc[ni->unit];	register struct ifnet *ifp = &ds->ds_if;	int i=0;	struct sockaddr_in *sin;	/* Initialize SMP lock */	lockinit(&ds->lk_ni_softc, &lock_device15_d);	ds->ds_devid = 0;	ifp->if_unit = ni->unit;	ifp->if_name = "ni";	ifp->lk_softc = &ds->lk_ni_softc;	ifp->if_mtu = ETHERMTU;	ifp->if_type = IFT_ETHER;	ifp->if_flags |= IFF_BROADCAST|IFF_DYNPROTO|IFF_NOTRAILERS;	((struct arpcom *)ifp)->ac_ipaddr.s_addr = 0;	/* 	 * Set ni to initialized state	 */	i=0;	while((ni->ni_regs->ps&PS_STATEMASK) != PS_UNDEFINED) {	    if(++i > 200) {		printf("ni%d in wrong state\n", ni->unit);		return;	    }	    DELAY(100000);	}	DELAY(200000);	ni->ni_regs->ps &= ~PS_OWN;	ni->ni_regs->pc &= ~PC_OWN;	/* Go to initialized state */	ni->ni_regs->pc = ni->phys_pqb|PC_INIT|PC_OWN;	DELAY(1000000);	while((ni->ni_regs->pc&PC_OWN)) 		;	i=0;	while((ni->ni_regs->ps&PS_INITIALIZED) == 0) {		if(i++ > 15) {			printf("ni%d Cannot initialize\n", ni->unit);			return;		} else 			DELAY(1000000);	}	ni->ni_regs->ps &= ~PS_OWN;	/*	 * Fill the multicast address table with unused entries (broadcast	 * address) so that we can always give the full table to the device	 * and we don't have to worry about gaps.	 */	for(i=0; i<NMULTI; i++) {		ds->ds_muse[i] = 0;		bcopy(ni_multi, ds->ds_multi[i], 8);	}	sin = (struct sockaddr_in *)&ifp->if_addr;	sin->sin_family = AF_INET;	ifp->if_init = niinit;	ifp->if_output = net_output;	ifp->if_start = nistart;	ifp->if_ioctl = niioctl;	ifp->if_reset = nireset;	ifp->d_affinity = ALLCPU;	/* 8.9.88.us  For nonsym drivers. */	/*	 * Fill out the if_version field with HW (and SW) info	 */	bcopy("DEC DEBNA Ethernet Interface", ifp->if_version, 28);	ifp->if_version[28] = '\0';	/*	 * Hardware address unavailable at this point. (Only avail.	 * after niinit().	 */	printf("ni%d: %s\n", ifp->if_unit, ifp->if_version);#if NPACKETFILTER > 0	/* Tell the packet filter that we are here */	attachpfilter(&(ds->ds_ed));#endif NPACKETFILTER	if_attach(ifp);}/* * Reset of interface after reset. */nireset(unit)	int unit;{	register struct ni *ni;	register struct ni_softc *ds = &ni_softc[unit];	register char *mem;	register int i;	struct ifnet *ifp = &ds->ds_if;	if (unit >= nNI || (ni = &niinfo[unit]) == 0 || ni->alive == 0)		return;	printf("reset ni%d %x %x %x %x\n", unit, ni->ni_regs->pc,		ni->ni_regs->ps, ni->ni_regs->pe, ni->ni_regs->pd);	if((ni->ni_regs->ps&PS_STATEMASK) != PS_ENABLED) {	/* Eat freeq 2 */		while((mem = (char *)remqhi(&ni->freeq2, NI_MAXITRY)) != (char *)QEMPTY) {			struct _bd *bde = (struct _bd *)ni->ni_pqb->ni.bdt_base;			bde += ((struct ni_data *)mem)->cbufs[0].bdt_index;			for(i=0; i<NI_RBUF; bde++, i++) {				if(i == 1) {					KM_FREE(vaddr(bde), KM_CLUSTER);				} else {					KM_FREE(vaddr(bde), KM_DEVBUF);				}			}			KM_FREE(mem, KM_DEVBUF);		}	/* Eat freeq0 & freeq1 */		while((mem = (char *)remqhi(&ni->freeq0, NI_MAXITRY)) != (char *)QEMPTY) {			KM_FREE(mem, KM_DEVBUF);		}		while((mem = (char *)remqhi(&ni->freeq1, NI_MAXITRY)) != (char *)QEMPTY) {			KM_FREE(mem, KM_DEVBUF);		}	/* Eat the respq */		while((mem = (char *)remqhi(&ni->respq, NI_MAXITRY)) != (char *)QEMPTY) {			if(((struct ni_data *)mem)->opcode == DGREC) {			struct _bd *bde = (struct _bd *)ni->ni_pqb->ni.bdt_base;			bde += ((struct ni_data *)mem)->cbufs[0].bdt_index;			for(i=0; i<NI_RBUF; bde++, i++) {				if(i == 1) {					KM_FREE(vaddr(bde), KM_CLUSTER);				} else {					KM_FREE(vaddr(bde), KM_DEVBUF);				}			}			KM_FREE(mem, KM_DEVBUF);			} else if(((struct ni_data *)mem)->opcode == SNDDG) {				KM_FREE(mem, KM_DEVBUF);			} else {				KM_FREE(mem, KM_DEVBUF);			}		}					if((ni->ni_regs->ps&PS_STATEMASK) == PS_STOPPED) {			ni->ni_regs->ps &= ~PS_OWN;			ni->ni_regs->pc = PC_RESTART|PC_OWN;			DELAY(1000000);			while((ni->ni_regs->pc&PC_OWN)) 				;		}		ni->ni_regs->ps &= ~PS_OWN;		/* 	 	* Set ni to initialized state	 	*/		i=0;		while((ni->ni_regs->ps&PS_STATEMASK) != PS_UNDEFINED) {	    	if(++i > 200) {			printf("ni%d in wrong state\n", ni->unit);			return(0);	    	}	    	DELAY(100000);		}		ni->ni_regs->ps &= ~PS_OWN;		/* Go to initialized state */		ni->ni_regs->pc = ni->phys_pqb|PC_INIT|PC_OWN;		DELAY(100000);		while((ni->ni_regs->pc&PC_OWN)) 			;		if((ni->ni_regs->ps&PS_INITIALIZED) == 0) {			printf("ni%d Cannot initialize\n", ni->unit);			printf("nireset: init failed - %d %x %x %x %x\n",				unit, ni->ni_regs->pc, ni->ni_regs->ps,				ni->ni_regs->pe, ni->ni_regs->pd);			return(0);		}		ni->ni_regs->ps &= ~PS_OWN;		ni->ni_regs->pe = 0;		ni->ni_regs->pd = 0;		ifp->if_flags &= ~(IFF_RUNNING);		untimeout(niinit, unit);		timeout(niinit, unit, 1);		return(0);	}	return(1);}/* * Initialization of interface; clear recorded pending * operations. */niinit(unit)	int unit;{	register struct ni_softc *ds = &ni_softc[unit];	register struct ni *ni = &niinfo[unit];	register struct nidevice *addr;	struct ifnet *ifp = &ds->ds_if;	int s,i,empty;	/* not yet, if address still unknown */	/* DECnet must set this somewhere to make device happy */	if (ifp->if_addrlist == (struct ifaddr *)0)			return;	if (ifp->if_flags & IFF_RUNNING)		return;	/* 	 * Set ni to enabled state. Still dont have freeq ready.	 */	addr = (struct nidevice *)ni->ni_regs;	while((addr->pc&PC_OWN))		;	addr->pc = PC_ENABLE|PC_OWN;	/* Should interrupt here */	while((addr->pc&PC_OWN))		;	while((addr->ps&PS_OWN))		;	i = 0;	while((addr->ps&PS_STATEMASK) != PS_ENABLED) {		if(i++ > 500000) {			printf("ni%d Cannot enable\n", ni->unit);			return;		}	}	addr->ps &= ~PS_OWN;	s = splimp();	/* 	 * Setup message freeq Just a few so its not empty 	 */	{		struct ni_msg *ni_msg;		for(i=0; i<6; i++) {		KM_ALLOC(ni_msg, struct ni_msg *, sizeof(struct ni_msg), KM_DEVBUF, KM_NOW_CL);		if (ni_msg == 0){			printf("ni%d Init out of memory - ni_msg\n",ni->unit);			return;		}		if((empty=insqti(ni_msg, &ni->freeq0, NI_MAXITRY)) > 0)			printf("insqti failed\n");		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				;			addr->pc = PC_FREEQNE|PC_MFREEQ|PC_OWN;			while((addr->pc&PC_OWN))				;		}		}	}	/* Setup xmit buffers (empty) */	for(i=0; i<NI_FREEQ_1; i += NI_NUMBUF) {		struct ni_data *ni_data;		struct _bd *bde;		int j;		KM_ALLOC(ni_data, struct ni_data *, NI_DQSIZE, KM_DEVBUF, KM_NOW_CL);		if (ni_data == 0){			printf("ni%d Init out of memory - ni_data\n",ni->unit);			return;		}		ni_data->status = 0;		ni_data->dg_len = NI_DQSIZE-NI_DQHEAD;		ni_data->dg_ptdb_index = 1;		ni_data->opcode = SNDDG;		for(j=0; j<NI_NUMBUF; j++) {				ni_data->cbufs[j].offset = 0;			ni_data->cbufs[j].buffer_key = 1;				bde = (struct _bd *) ni->ni_pqb->ni.bdt_base;			bde += i+j;			bde->key = 1;			bde->valid = 0;			ni_data->cbufs[j].bdt_index = i+j;		}		if((empty=insqti(ni_data, &ni->freeq1, NI_MAXITRY)) > 0)			printf("xmit insqti failed %d\n", i);		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				;			addr->pc =  PC_FREEQNE|PC_DFREEQ|PC_OWN;			while((addr->pc&PC_OWN))				;		}	}	/*	 * Setup recv buffers 	 */		/* Note that these have mbuf data areas associated */	for(i=NI_FREEQ_1; i<(NI_FREEQ_1+NI_FREEQ_2); i += NI_RBUF) {		struct ni_data *ni_data;	  	struct _bd *bde;	  	char *buffer;		int j=0;		KM_ALLOC(ni_data, struct ni_data *, sizeof(struct ni_data), KM_DEVBUF, KM_NOW_CL);		if (ni_data == 0){			printf("ni%d Init out of memory - ni_data\n",ni->unit);			return;

⌨️ 快捷键说明

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