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

📄 if_il.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic char *sccsid = "@(#)if_il.c	4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1985 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				* *									* * 1-Apr-88    -- lea   43.5bsd fixes and decnet hooks.			* *	 * 13-Jun-86   -- jaw 	fix to uba reset and drivers. XXX? * * 18-mar-86  -- jaw     br/cvec changed to NOT use registers. * *	Larry Cohen  -	09/16/85					* * 		Add 43bsd alpha tape changes for subnet routing		* *									* ************************************************************************//* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * *	@(#)if_il.c	7.2 (Berkeley) 8/7/86 */#include "il.h"#ifdef NIL > 0 || defined(BINARY)#include "../data/if_il_data.c"extern struct protosw *iftype_to_proto(), *iffamily_to_proto();int	ilprobe(), ilattach(), ilrint(), ilcint();u_short ilstd[] = { 0 };struct	uba_driver ildriver =	{ ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo };#define	ILUNIT(x)	minor(x)int	ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch();int	ildebug = 0;/* * Interlan Ethernet Communications Controller interface */ilprobe(reg)	caddr_t reg;{	register struct ildevice *addr = (struct ildevice *)reg;	register i;#ifdef lint	i = 0; ilrint(i); ilcint(i); ilwatch(i);#endif	addr->il_csr = ILC_OFFLINE|IL_CIE;	DELAY(100000);	i = addr->il_csr;		/* clear CDONE */	if (cvec > 0 && cvec != 0x200)		cvec -= 4;	return (1);}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets.  A STATUS command is done to get the ethernet * address and other interesting data. */ilattach(ui)	struct uba_device *ui;{	register struct il_softc *is = &il_softc[ui->ui_unit];	register struct ifnet *ifp = &is->is_if;	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;	ifp->if_unit = ui->ui_unit;	ifp->if_name = "il";	ifp->if_mtu = ETHERMTU;	ifp->if_flags = IFF_BROADCAST;	/*	 * Reset the board and map the statistics	 * buffer onto the Unibus.	 */	addr->il_csr = ILC_RESET;	(void)ilwait(ui, "reset");		is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,	    sizeof (struct il_stats), 0);	addr->il_bar = is->is_ubaddr & 0xffff;	addr->il_bcr = sizeof (struct il_stats);	addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;	(void)ilwait(ui, "status");	ubarelse(ui->ui_ubanum, &is->is_ubaddr);	if (ildebug)		printf("il%d: module=%s firmware=%s\n", ui->ui_unit,			is->is_stats.ils_module, is->is_stats.ils_firmware); 	bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, 	    sizeof (is->is_addr));	printf("il%d: hardware address %s\n", ui->ui_unit,		ether_sprintf(is->is_addr));	ifp->if_init = ilinit;	ifp->if_output = iloutput;	ifp->if_ioctl = ilioctl;	ifp->if_reset = ilreset;	is->is_ifuba.ifu_flags = UBA_CANTWAIT;#ifdef notdef	is->is_ifuba.ifu_flags |= UBA_NEEDBDP;#endif	if_attach(ifp);}ilwait(ui, op)	struct uba_device *ui;	char *op;{	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;	while ((addr->il_csr&IL_CDONE) == 0)		;	if (addr->il_csr&IL_STATUS) {		printf("il%d: %s failed, csr=%b\n", ui->ui_unit, op,			addr->il_csr, IL_BITS);		return (-1);	}	return (0);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ilreset(unit, uban)	int unit, uban;{	register struct uba_device *ui;	if (unit >= nNIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_ubanum != uban)		return;	printf(" il%d", unit);	il_softc[unit].is_if.if_flags &= ~IFF_RUNNING;	il_softc[unit].is_flags &= ~ILF_RUNNING;	ilinit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ilinit(unit)	int unit;{	register struct il_softc *is = &il_softc[unit];	register struct uba_device *ui = ilinfo[unit];	register struct ildevice *addr;	register struct ifnet *ifp = &is->is_if;	int s;	/* not yet, if address still unknown */	if (ifp->if_addrlist == (struct ifaddr *)0)		return;	if (is->is_flags & ILF_RUNNING)		return;	if ((ifp->if_flags & IFF_RUNNING) == 0) {		if (if_ubainit(&is->is_ifuba, ui->ui_ubanum,		    sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { 			printf("il%d: can't initialize\n", unit);			is->is_if.if_flags &= ~IFF_UP;			return;		}		is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats,		    sizeof (struct il_stats), 0);	}	ifp->if_watchdog = ilwatch;	is->is_scaninterval = ILWATCHINTERVAL;	ifp->if_timer = is->is_scaninterval;	addr = (struct ildevice *)ui->ui_addr;	/*	 * Turn off source address insertion (it's faster this way),	 * and set board online.  Former doesn't work if board is	 * already online (happens on ubareset), so we put it offline	 * first.	 */	s = splimp();	addr->il_csr = ILC_RESET;	if (ilwait(ui, "hardware diag")) { 		is->is_if.if_flags &= ~IFF_UP; 		splx(s); 		return; 	}	addr->il_csr = ILC_CISA;	while ((addr->il_csr & IL_CDONE) == 0)		;	/*	 * If we must reprogram this board's physical ethernet	 * address (as for secondary XNS interfaces), we do so	 * before putting it on line, and starting receive requests.	 * If you try this on an older 1010 board, it will total	 * wedge the board.	 */	if (is->is_flags & ILF_SETADDR) {		bcopy((caddr_t)is->is_addr, (caddr_t)&is->is_stats,							sizeof is->is_addr);		addr->il_bar = is->is_ubaddr & 0xffff;		addr->il_bcr = sizeof is->is_addr;		addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_LDPA;		if (ilwait(ui, "setaddr"))			return;		addr->il_bar = is->is_ubaddr & 0xffff;		addr->il_bcr = sizeof (struct il_stats);		addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT;		if (ilwait(ui, "verifying setaddr"))			return;		if (bcmp((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr,						sizeof (is->is_addr)) != 0) {			printf("il%d: setaddr didn't work\n", ui->ui_unit);			return;		}	}	/*	 * Set board online.	 * Hang receive buffer and start any pending	 * writes by faking a transmit complete.	 * Receive bcr is not a multiple of 8 so buffer	 * chaining can't happen.	 */	addr->il_csr = ILC_ONLINE;	while ((addr->il_csr & IL_CDONE) == 0)		;	addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;	addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;	addr->il_csr =	    ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;	while ((addr->il_csr & IL_CDONE) == 0)		;	is->is_flags = ILF_OACTIVE;	is->is_if.if_flags |= IFF_RUNNING;	is->is_flags |= ILF_RUNNING;	is->is_lastcmd = 0;	ilcint(unit);	splx(s);}/* * Start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */ilstart(dev)	dev_t dev;{        int unit = ILUNIT(dev), len;	struct uba_device *ui = ilinfo[unit];	register struct il_softc *is = &il_softc[unit];	register struct ildevice *addr;	struct mbuf *m;	short csr;	IF_DEQUEUE(&is->is_if.if_snd, m);	addr = (struct ildevice *)ui->ui_addr;	if (m == 0) {		if ((is->is_flags & ILF_STATPENDING) == 0)			return;		addr->il_bar = is->is_ubaddr & 0xffff;		addr->il_bcr = sizeof (struct il_stats);		csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE;		is->is_flags &= ~ILF_STATPENDING;		goto startcmd;	}	len = if_wubaput(&is->is_ifuba, m);	/*	 * Ensure minimum packet length.	 * This makes the safe assumtion that there are no virtual holes	 * after the data.	 * For security, it might be wise to zero out the added bytes,	 * but we're mainly interested in speed at the moment.	 */	if (len - sizeof(struct ether_header) < ETHERMIN)		len = ETHERMIN + sizeof(struct ether_header);	if (is->is_ifuba.ifu_flags & UBA_NEEDBDP)		UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp,			is->is_ifuba.ifu_uban);	addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff;	addr->il_bcr = len;	csr =	  ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;startcmd:	is->is_lastcmd = csr & IL_CMD;	addr->il_csr = csr;	is->is_flags |= ILF_OACTIVE;}/* * Command done interrupt. */ilcint(unit)	int unit;{	register struct il_softc *is = &il_softc[unit];	struct uba_device *ui = ilinfo[unit];	register struct ildevice *addr = (struct ildevice *)ui->ui_addr;	short csr;	if ((is->is_flags & ILF_OACTIVE) == 0) {		printf("il%d: stray xmit interrupt, csr=%b\n", unit,			addr->il_csr, IL_BITS);		return;	}	csr = addr->il_csr;	/*	 * Hang receive buffer if it couldn't	 * be done earlier (in ilrint).	 */	if (is->is_flags & ILF_RCVPENDING) {		int s;		addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff;		addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6;		addr->il_csr =		  ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE;		s = splhigh();		while ((addr->il_csr & IL_CDONE) == 0)			;		splx(s);		is->is_flags &= ~ILF_RCVPENDING;	}	is->is_flags &= ~ILF_OACTIVE;	csr &= IL_STATUS;	switch (is->is_lastcmd) {	case ILC_XMIT:		is->is_if.if_opackets++;		if (csr > ILERR_RETRIES)			is->is_if.if_oerrors++;		break;	case ILC_STAT:		if (csr == ILERR_SUCCESS)			iltotal(is);		break;	}	if (is->is_ifuba.ifu_xtofree) {		m_freem(is->is_ifuba.ifu_xtofree);		is->is_ifuba.ifu_xtofree = 0;	}	ilstart(unit);}/* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine  * packet to determine type.  If can't determine length * from type, then have to drop packet.  Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */ilrint(unit)	int unit;{	register struct il_softc *is = &il_softc[unit];	struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr;

⌨️ 快捷键说明

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