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

📄 if_en.c

📁 open bsd vax module -if function
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * 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_en.c	7.7 (Berkeley) 12/16/90 */#include "en.h"#if NEN > 0/* * Xerox prototype (3 Mb) Ethernet interface driver. */#include "../include/pte.h"#include "sys/param.h"#include "sys/systm.h"#include "sys/mbuf.h"#include "sys/buf.h"#include "sys/protosw.h"#include "sys/socket.h"#include "sys/vmmac.h"#include "sys/errno.h"#include "sys/ioctl.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"#endif#ifdef PUP#include "netpup/pup.h"#include "netpup/ether.h"#endif#ifdef NS#include "netns/ns.h"#include "netns/ns_if.h"#endif#include "../include/cpu.h"#include "../include/mtpr.h"#include "if_en.h"#include "if_enreg.h"#include "if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"#define	ENMTU	(1024+512)#define	ENMRU	(1024+512+16)		/* 16 is enough to receive trailer */int	enprobe(), enattach(), enrint(), enxint(), encollide();struct	uba_device *eninfo[NEN];u_short enstd[] = { 0 };struct	uba_driver endriver =	{ enprobe, 0, enattach, 0, enstd, "en", eninfo };#define	ENUNIT(x)	minor(x)int	eninit(),oldenoutput(),enreset(),enioctl(), enstart();#ifdef notdef/* * If you need to byte swap IP's in the system, define * this and do a SIOCSIFFLAGS at boot time. */#define	ENF_SWABIPS	0x1000#endif/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... * We also have, for each interface, a UBA interface structure, which * contains information about the UNIBUS resources held by the interface: * map registers, buffered data paths, etc.  Information is cached in this * structure for use by the if_uba.c routines in running the interface * efficiently. */struct	en_softc {	struct	ifnet es_if;		/* network-visible interface */	struct	ifuba es_ifuba;		/* UNIBUS resources */	short	es_host;		/* hardware host number */	short	es_delay;		/* current output delay */	short	es_mask;		/* mask for current output delay */	short	es_lastx;		/* host last transmitted to */	short	es_oactive;		/* is output active? */	short	es_olen;		/* length of last output */	short	es_nsactive;		/* is interface enabled for ns? */} en_softc[NEN];/* * Do output DMA to determine interface presence and * interrupt vector.  DMA is too short to disturb other hosts. */enprobe(reg)	caddr_t reg;{	register int br, cvec;		/* r11, r10 value-result */	register struct endevice *addr = (struct endevice *)reg;#ifdef lint	br = 0; cvec = br; br = cvec;	enrint(0); enxint(0); encollide(0);#endif	addr->en_istat = 0;	addr->en_owc = -1;	addr->en_oba = 0;	addr->en_ostat = EN_IEN|EN_GO;	DELAY(100000);	addr->en_ostat = 0;	return (1);}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */enattach(ui)	struct uba_device *ui;{	register struct en_softc *es = &en_softc[ui->ui_unit];	es->es_if.if_unit = ui->ui_unit;	es->es_if.if_name = "en";	es->es_if.if_mtu = ENMTU;	es->es_if.if_flags = IFF_BROADCAST;	es->es_if.if_init = eninit;	es->es_if.if_output = oldenoutput;	es->es_if.if_start = enstart;	es->es_if.if_ioctl = enioctl;	es->es_if.if_reset = enreset;	es->es_ifuba.ifu_flags = UBA_NEEDBDP | UBA_NEED16 | UBA_CANTWAIT;#if defined(VAX750)	/* don't chew up 750 bdp's */	if (cpu == VAX_750 && ui->ui_unit > 0)		es->es_ifuba.ifu_flags &= ~UBA_NEEDBDP;#endif	if_attach(&es->es_if);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */enreset(unit, uban)	int unit, uban;{	register struct uba_device *ui;	if (unit >= NEN || (ui = eninfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_ubanum != uban)		return;	printf(" en%d", unit);	eninit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */eninit(unit)	int unit;{	register struct en_softc *es = &en_softc[unit];	register struct uba_device *ui = eninfo[unit];	register struct endevice *addr;	int s;	if (es->es_if.if_addrlist == (struct ifaddr *)0)		return;	if (if_ubainit(&es->es_ifuba, ui->ui_ubanum,	    sizeof (struct en_header), (int)btoc(ENMRU)) == 0) { 		printf("en%d: can't initialize\n", unit);		es->es_if.if_flags &= ~IFF_UP;		return;	}	addr = (struct endevice *)ui->ui_addr;	addr->en_istat = addr->en_ostat = 0;	/*	 * Hang a receive and start any	 * pending writes by faking a transmit complete.	 */	s = splimp();	addr->en_iba = es->es_ifuba.ifu_r.ifrw_info;	addr->en_iwc = -(sizeof (struct en_header) + ENMRU) >> 1;	addr->en_istat = EN_IEN|EN_GO;	es->es_oactive = 1;	es->es_if.if_flags |= IFF_RUNNING;	enxint(unit);	splx(s);}int	enalldelay = 0;int	enlastdel = 50;int	enlastmask = (~0) << 5;/* * Start or restart output on interface. * If interface is already active, then this is a retransmit * after a collision, and just restuff registers and delay. * If interface is not already active, get another datagram * to send off of the interface queue, and map it to the interface * before starting the output. */enstart(dev)	dev_t dev;{        int unit = ENUNIT(dev);	struct uba_device *ui = eninfo[unit];	register struct en_softc *es = &en_softc[unit];	register struct endevice *addr;	register struct en_header *en;	struct mbuf *m;	int dest;	if (es->es_oactive)		goto restart;	/*	 * Not already active: dequeue another request	 * and map it to the UNIBUS.  If no more requests,	 * just return.	 */	IF_DEQUEUE(&es->es_if.if_snd, m);	if (m == 0) {		es->es_oactive = 0;		return;	}	en = mtod(m, struct en_header *);	dest = en->en_dhost;	en->en_shost = es->es_host;	es->es_olen = if_wubaput(&es->es_ifuba, m);#ifdef ENF_SWABIPS	/*	 * The Xerox interface does word at a time DMA, so	 * someone must do byte swapping of user data if high	 * and low ender machines are to communicate.  It doesn't	 * belong here, but certain people depend on it, so...	 *	 * Should swab everybody, but this is a kludge anyway.	 */	if (es->es_if.if_flags & ENF_SWABIPS) {		en = (struct en_header *)es->es_ifuba.ifu_w.ifrw_addr;		if (en->en_type == ENTYPE_IP)			enswab((caddr_t)(en + 1), (caddr_t)(en + 1),			    es->es_olen - sizeof (struct en_header) + 1);	}#endif	/*	 * Ethernet cannot take back-to-back packets (no	 * buffering in interface.  To help avoid overrunning	 * receivers, enforce a small delay (about 1ms) in interface:	 *	* between all packets when enalldelay	 *	* whenever last packet was broadcast	 *	* whenever this packet is to same host as last packet	 */	if (enalldelay || es->es_lastx == 0 || es->es_lastx == dest) {		es->es_delay = enlastdel;		es->es_mask = enlastmask;	}	es->es_lastx = dest;restart:	/*	 * Have request mapped to UNIBUS for transmission.	 * Purge any stale data from this BDP, and start the otput.	 */	if (es->es_ifuba.ifu_flags & UBA_NEEDBDP)		UBAPURGE(es->es_ifuba.ifu_uba, es->es_ifuba.ifu_w.ifrw_bdp);	addr = (struct endevice *)ui->ui_addr;	addr->en_oba = (int)es->es_ifuba.ifu_w.ifrw_info;	addr->en_odelay = es->es_delay;	addr->en_owc = -((es->es_olen + 1) >> 1);	addr->en_ostat = EN_IEN|EN_GO;	es->es_oactive = 1;}/* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */enxint(unit)	int unit;{	register struct uba_device *ui = eninfo[unit];	register struct en_softc *es = &en_softc[unit];	register struct endevice *addr = (struct endevice *)ui->ui_addr;	if (es->es_oactive == 0)		return;	if (es->es_mask && (addr->en_ostat&EN_OERROR)) {		es->es_if.if_oerrors++;		endocoll(unit);		return;	}	es->es_if.if_opackets++;	es->es_oactive = 0;	es->es_delay = 0;	es->es_mask = ~0;	if (es->es_ifuba.ifu_xtofree) {		m_freem(es->es_ifuba.ifu_xtofree);		es->es_ifuba.ifu_xtofree = 0;	}	if (es->es_if.if_snd.ifq_head == 0) {		es->es_lastx = 256;		/* putatively illegal */		return;	}	enstart(unit);}/* * Collision on ethernet interface.  Do exponential * backoff, and retransmit.  If have backed off all * the way print warning diagnostic, and drop packet. */encollide(unit)	int unit;{	struct en_softc *es = &en_softc[unit];	es->es_if.if_collisions++;	if (es->es_oactive == 0)		return;	endocoll(unit);}endocoll(unit)	int unit;{	register struct en_softc *es = &en_softc[unit];	/*	 * Es_mask is a 16 bit number with n low zero bits, with	 * n the number of backoffs.  When es_mask is 0 we have

⌨️ 快捷键说明

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