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

📄 if_de.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * if_de.c */#ifndef lintstatic char *sccsid = "@(#)if_de.c	4.3	(ULTRIX)	2/26/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1985-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.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   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.	* *									* ************************************************************************//************************************************************************ *			Modification History				* *									* * 24-Feb-91 - jsd * 	Allow loopback packets if COPYALL mode is set * * 10-Nov-89 - jaw * 	replace references to maxcpu with smp. * * 28-Oct-89 - Uttam Shikarpur						* *	Added:								* *		1) Reporting counters for multicast packs. and bytes	* *		2) Added "if_version" support.				* *									* * 3-Mar-89 - Uttam S.N							* *	Add support for Ethernet packet filter				* *	Moved common read code to ../net/ether_read.c			* *									* * 3-Mar-89 - U. Sinkewicz						* *	Added smp support.						* *									* * 29-Jun-88 - Fred L. Templin						* *	Added code to the "deoutput" routine to verify that the		* *	interface has been marked as "IFF_UP" and "IFF_RUNNING"		* *									* * 05-Feb-88 - lp							* *	Fix deget to switch only 1 cluster as unibus mapping had not	* *	changed.							* *									* * 15-Jan-88 - Larry Palmer						* *	Added changes for 43BSD. Also added changes for malloced mbufs.	* * 12-Aug-87  -- Fred L. Templin					* *	Removed the "de0: buffer unavailable" printf. This has been     * *   around since the beginning of time, and this information is        * *   already maintained by the deuna counter block. Also, added check   * *   in deintr for USCI and SERI error interrupts. No error recovery    * *   is attempted; only print diagnostic messages. Fix suggested by	* *   Bill Dallas.							* *									* * 26-Feb-87  -- jsd							* *	Check return of iftype_to_proto so that we don't jump to 0.	* *									* * 13-Jun-86   -- jaw 	fix to uba reset and drivers.			* *									* * 18-mar-86  -- jaw     br/cvec changed to NOT use registers.		* *									* *	Chet Juszczak - 03/12/86					* *		Modify MCLGET macro call to match new definition	* *									* *	Larry Cohen  -	09/16/85					* * 		Add 43bsd alpha tape changes for subnet routing		* *									* *	10-Sep-85 -- pjt						* *		Delua support 						* *									* * 	19-Jun-85 -- jaw					 	*	 *		VAX8200 name change.					* *									* *	13 Mar 85 - Jaw							* *		add support for VAX8200 and bua				* *									* *	LSC001 - Larry Cohen, 3/6/85: add internal loopback 		* *									* *	LSC002 - Larry cohen, 3/685: poke deuna when transmit ring	* *		   is full and more data to send. Prevents system from 	* *		   dropping off the network and hanging occasionally	* ***********************************************************************/#include "de.h"#if NDE > 0 || defined(BINARY)/* * DEC DEUNA interface * *	Lou Salkind *	New York University * * TODO: *	timeout routine (get statistics) */#include "packetfilter.h"	/* NPACKETFILTER */#include "../data/if_de_data.c"int dedebug = 0;u_char unused_multi[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern struct timeval time;extern int net_output();int	deprobe(), deattach(), deintr();struct	uba_device ;u_short destd[] = { 0 };struct	uba_driver dedriver =	{ deprobe, 0, deattach, 0, destd, "de", deinfo };#define	DEUNIT(x)	minor(x)int	deinit(),destart(),deioctl(),dereset();struct	mbuf *deget();#define DELUA_LOOP_LEN 32-sizeof(struct ether_header)deprobe(reg)	caddr_t reg;{	register struct dedevice *addr = (struct dedevice *)reg;	register i;#ifdef lint	i = 0; derint(i); deintr(i);#endif       /*        * Make sure self-test is finished         * Self-test on a DELUA can take 15 seconds.        */        for (i = 0;             i < 160 &&             (addr->pcsr0 & PCSR0_FATI) == 0 &&             (addr->pcsr1 & PCSR1_STMASK) == STAT_RESET;             ++i)                DELAY(100000);        if ((addr->pcsr0 & PCSR0_FATI) != 0 ||            (addr->pcsr1 & PCSR1_STMASK) != STAT_READY)                return(0);        addr->pcsr0 = 0;	addr->pcsr0 = PCSR0_RSET;	/*	 * just in case this is not a deuna or delua 	 * dont wait for more than 30 secs         */        for (i = 0; i < 300 && (addr->pcsr0 & PCSR0_INTR) == 0; i++)                DELAY(100000);        if ((addr->pcsr0 & PCSR0_INTR) == 0)                 return(0);	/* make board interrupt by executing a GETPCBB command */	addr->pcsr0 = PCSR0_INTE;	addr->pcsr2 = 0;	addr->pcsr3 = 0;	addr->pcsr0 = PCSR0_INTE|CMD_GETPCBB;	DELAY(100000);	return(1);}/* * 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. */deattach(ui)	struct uba_device *ui;{	register struct de_softc *ds = &de_softc[ui->ui_unit];	register struct ifnet *ifp = &ds->ds_if;	register struct dedevice *addr = (struct dedevice *)ui->ui_addr;	struct sockaddr_in *sin;	int csr0,i;	u_short csr1 = addr->pcsr1;	/* Initialize SMP lock */	lockinit(&ds->lk_de_softc, &lock_device15_d);	/* 	 * Is it a DEUNA or a DELUA? Save the device id.	 */	ds->ds_devid = (csr1 & PCSR1_DEVID) >> 4;	/* check status of board */	if (csr1 & 0xff80)		printf("de%d: hardware error, pcsr1=%x\n", csr1);	ifp->if_unit = ui->ui_unit;	ifp->if_name = "de";	ifp->lk_softc = &ds->lk_de_softc;	ifp->if_mtu = ETHERMTU;	ifp->if_type = IFT_ETHER;	ifp->if_flags |= IFF_BROADCAST|IFF_DYNPROTO;	/*	 * 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++)		bcopy(unused_multi,&ds->ds_multicast[i],MULTISIZE);	/*	 * Reset the board and map the pcbb buffer onto the Unibus.	 */	addr->pcsr0 = PCSR0_RSET;	while ((addr->pcsr0 & PCSR0_INTR) == 0)		;	csr0 = addr->pcsr0;	addr->pchigh = csr0 >> 8;	if ((csr0 & PCSR0_PCEI) || (csr0 & PCSR0_DNI)==0) {		if (ds->ds_devid == DEUNA)			printf("de%d: reset failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);		else			printf("de%d: reset failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA);	}	ds->ds_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(ds),		INCORE_SIZE, 0);	addr->pcsr2 = ds->ds_ubaddr & 0xffff;	addr->pcsr3 = (ds->ds_ubaddr >> 16) & 0x3;	addr->pclow = CMD_GETPCBB;	while ((addr->pcsr0 & PCSR0_INTR) == 0)		;	csr0 = addr->pcsr0;	addr->pchigh = csr0 >> 8;	if ((csr0 & PCSR0_PCEI) || (csr0 & PCSR0_DNI)==0) {		if (ds->ds_devid == DEUNA) 			printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);		else			printf("de%d: pcbb failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA);	}	ds->ds_pcbb.pcbb0 = FC_RDPHYAD;	addr->pclow = CMD_GETCMD;	while ((addr->pcsr0 & PCSR0_INTR) == 0)		;	csr0 = addr->pcsr0;	addr->pchigh = csr0 >> 8;	if ((csr0 & PCSR0_PCEI) || (csr0 & PCSR0_DNI)==0) {		if (ds->ds_devid == DEUNA)			printf("de%d: rdphyad failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);		else			printf("de%d: rdphyad failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA);	}	if (dedebug)		printf("de%d: addr=%d:%d:%d:%d:%d:%d\n", ui->ui_unit,		    ds->ds_pcbb.pcbb2&0xff, (ds->ds_pcbb.pcbb2>>8)&0xff,		    ds->ds_pcbb.pcbb4&0xff, (ds->ds_pcbb.pcbb4>>8)&0xff,		    ds->ds_pcbb.pcbb6&0xff, (ds->ds_pcbb.pcbb6>>8)&0xff);	bcopy((caddr_t)&ds->ds_pcbb.pcbb2,(caddr_t)ds->ds_addr,	    sizeof (ds->ds_addr));	ifp->if_init = deinit;	ifp->if_output = net_output;	ifp->if_start = destart;	ifp->if_ioctl = deioctl;	ifp->if_reset = dereset;	ifp->d_affinity = ALLCPU;	/* 10.18.88.us */	ds->ds_deuba.ifu_flags = UBA_CANTWAIT;#ifdef notdef	/* CAN WE USE BDP's ??? */	ds->ds_deuba.ifu_flags |= UBA_NEEDBDP;#endif	if (ds->ds_devid == DEUNA) {		ifp->if_sysid_type = 1;		bcopy("DEC DEUNA Ethernet Interface", ifp->if_version, 28);	} else {		ifp->if_sysid_type = 11;		bcopy("DEC DELUA Ethernet Interface", ifp->if_version, 28);	}	ifp->if_version[28] = '\0';	printf ("de%d: %s, hardware address %s\n", ifp->if_unit,		 ifp->if_version, ether_sprintf(ds->ds_addr));#if NPACKETFILTER > 0	/* Tell the packet filter we are here */	attachpfilter(&(ds->ds_ed));#endif NPACKETFILTER	if_attach(ifp);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */dereset(unit, uban)	int unit, uban;{	register struct uba_device *ui;	register struct de_softc *ds = &de_softc[unit];	if (unit >= nNDE || (ui = deinfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_ubanum != uban)		return;	printf(" de%d", unit);	ds->ds_ubaddr = uballoc(uban, INCORE_BASE(ds), INCORE_SIZE, 0);	deinit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */deinit(unit)	int unit;{	register struct de_softc *ds = &de_softc[unit];	register struct uba_device *ui = deinfo[unit];	register struct dedevice *addr;	register struct ifrw *ifrw;	register struct ifxmt *ifxp;	struct ifnet *ifp = &ds->ds_if;	int s;	struct de_ring *rp;	int incaddr;	int csr0;	/* 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;	if (de_ubainit(&ds->ds_deuba, ui->ui_ubanum,	    sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 		printf("de%d: can't initialize\n", unit);		ds->ds_if.if_flags &= ~IFF_UP;		return;	}	addr = (struct dedevice *)ui->ui_addr;	/* set the transmit and receive ring header addresses */	incaddr = ds->ds_ubaddr + UDBBUF_OFFSET;	ds->ds_pcbb.pcbb0 = FC_WTRING;	ds->ds_pcbb.pcbb2 = incaddr & 0xffff;	ds->ds_pcbb.pcbb4 = (incaddr >> 16) & 0x3;	incaddr = ds->ds_ubaddr + XRENT_OFFSET;	ds->ds_udbbuf.b_tdrbl = incaddr & 0xffff;	ds->ds_udbbuf.b_tdrbh = (incaddr >> 16) & 0x3;	ds->ds_udbbuf.b_telen = sizeof (struct de_ring) / sizeof (short);	ds->ds_udbbuf.b_trlen = NXMT;	incaddr = ds->ds_ubaddr + RRENT_OFFSET;	ds->ds_udbbuf.b_rdrbl = incaddr & 0xffff;	ds->ds_udbbuf.b_rdrbh = (incaddr >> 16) & 0x3;	ds->ds_udbbuf.b_relen = sizeof (struct de_ring) / sizeof (short);	ds->ds_udbbuf.b_rrlen = NRCV;	addr->pclow = CMD_GETCMD;	while ((addr->pcsr0 & PCSR0_INTR) == 0)		;	csr0 = addr->pcsr0;	addr->pchigh = csr0 >> 8;	if (csr0 & PCSR0_PCEI)		if (ds->ds_devid == DEUNA)			printf("de%d: wtring failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);		else			printf("de%d: wtring failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA);	/* initialize the mode - enable hardware padding */	ds->ds_pcbb.pcbb0 = FC_WTMODE;	/* let hardware do padding - set MTCH bit on broadcast */	ds->ds_pcbb.pcbb2 = MOD_TPAD|MOD_HDX;#ifdef IFF_PROMISC	if (ifp->if_flags & IFF_PROMISC)        /* set promiscuous if wanted */		ds->ds_pcbb.pcbb2 |= MOD_PROM;#endif  IFF_PROMISC	addr->pclow = CMD_GETCMD;	while ((addr->pcsr0 & PCSR0_INTR) == 0)		;	csr0 = addr->pcsr0;	addr->pchigh = csr0 >> 8;	if (csr0 & PCSR0_PCEI)		if (ds->ds_devid == DEUNA)			printf("de%d: wtmode failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS);		else			printf("de%d: wtmode failed, csr0=%b csr1=%b\n", ui->ui_unit,		    		csr0, PCSR0_BITS, addr->pcsr1, PCSR1_BITS_DELUA);	/* set up the receive and transmit ring entries */	ifxp = &ds->ds_deuba.ifu_w[0];	for (rp = &ds->ds_xrent[0]; rp < &ds->ds_xrent[NXMT]; rp++) {		rp->r_segbl = ifxp->x_ifrw.ifrw_info & 0xffff;		rp->r_segbh = (ifxp->x_ifrw.ifrw_info >> 16) & 0x3;		rp->r_flags = 0;		ifxp++;	}	ifrw = &ds->ds_deuba.ifu_r[0];	for (rp = &ds->ds_rrent[0]; rp < &ds->ds_rrent[NRCV]; rp++) {		rp->r_slen = sizeof (struct de_buf);		rp->r_segbl = ifrw->ifrw_info & 0xffff;		rp->r_segbh = (ifrw->ifrw_info >> 16) & 0x3;		rp->r_flags = RFLG_OWN;		/* hang receive */		ifrw++;	}	/* start up the board (rah rah) */	s = splimp();	ds->ds_rindex = ds->ds_xindex = ds->ds_xfree = ds->ds_nxmit = 0;	ds->ds_if.if_flags |= IFF_UP|IFF_RUNNING;	ds->ds_if.if_flags &= ~IFF_OACTIVE;	addr->pclow = PCSR0_INTE;		/* avoid interlock */	smp_lock(&ds->lk_de_softc, LK_RETRY);	destart(unit);				/* queue output packets */	smp_unlock(&ds->lk_de_softc);	addr->pclow = CMD_START | PCSR0_INTE;	ds->ds_flags |= DSF_RUNNING;	ds->ds_ztime = time.tv_sec;	splx(s);}/* * Setup output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */destart(unit)	int unit;{        int len;	struct uba_device *ui = deinfo[unit];	struct dedevice *addr = (struct dedevice *)ui->ui_addr;	register struct de_softc *ds = &de_softc[unit];	register struct de_ring *rp;	struct mbuf *m;	register int nxmit;	for (nxmit = ds->ds_nxmit; nxmit < NXMT; nxmit++) {		IF_DEQUEUE(&ds->ds_if.if_snd, m);		if (m == 0)			break;		rp = &ds->ds_xrent[ds->ds_xfree];		if (rp->r_flags & XFLG_OWN)			panic("deuna xmit in progress");		len = deput(&ds->ds_deuba, ds->ds_xfree, m);		if (ds->ds_deuba.ifu_flags & UBA_NEEDBDP)			UBAPURGE(ds->ds_deuba.ifu_uba,			ds->ds_deuba.ifu_w[ds->ds_xfree].x_ifrw.ifrw_bdp,			ds->ds_deuba.ifu_uban);		rp->r_slen = len;		rp->r_tdrerr = 0;		rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;		ds->ds_xfree++;		if (ds->ds_xfree == NXMT)			ds->ds_xfree = 0;	}	if (ds->ds_nxmit != nxmit) {

⌨️ 快捷键说明

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