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

📄 if_ec.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_ec.c	7.8 (Berkeley) 12/16/90 */#include "ec.h"#if NEC > 0/* * 3Com Ethernet Controller interface */#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/syslog.h"#include "sys/vmmac.h"#include "sys/ioctl.h"#include "sys/errno.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"#include "netinet/if_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_ecreg.h"#include "if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"#if CLSIZE == 2#define ECBUFSIZE	32		/* on-board memory, clusters */#endifint	ecubamem(), ecprobe(), ecattach(), ecrint(), ecxint(), eccollide();struct	uba_device *ecinfo[NEC];u_short ecstd[] = { 0 };struct	uba_driver ecdriver =	{ ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo, 0, 0, 0, 0, ecubamem };int	ecinit(),ecioctl(),ecstart(),ecreset(),ether_output();struct	mbuf *ecget();extern struct ifnet loif;/* * 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	ec_softc {	struct	arpcom es_ac;		/* common Ethernet structures */#define	es_if	es_ac.ac_if		/* network-visible interface */#define	es_addr	es_ac.ac_enaddr		/* hardware Ethernet address */	struct	ifuba es_ifuba;		/* UNIBUS resources */	short	es_mask;		/* mask for current output delay */	u_char	*es_buf[16];		/* virtual addresses of buffers */} ec_softc[NEC];/* * Configure on-board memory for an interface. * Called from autoconfig and after a uba reset. * The address of the memory on the uba is supplied in the device flags. */ecubamem(ui, uban)	register struct uba_device *ui;{	register caddr_t ecbuf = (caddr_t) &umem[uban][ui->ui_flags];	register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;	/*	 * Make sure csr is there (we run before ecprobe).	 */	if (badaddr((caddr_t)addr, 2))		return (-1);#if VAX780	if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {		uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;		return (-1);	}#endif	/*	 * Make sure memory is turned on	 */	addr->ec_rcr = EC_AROM;	/*	 * Tell the system that the board has memory here, so it won't	 * attempt to allocate the addresses later.	 */	if (ubamem(uban, ui->ui_flags, ECBUFSIZE*CLSIZE, 1) == 0) {		printf("ec%d: cannot reserve uba addresses\n", ui->ui_unit);		addr->ec_rcr = EC_MDISAB;	/* disable memory */		return (-1);	}	/*	 * Check for existence of buffers on Unibus.	 */	if (badaddr((caddr_t)ecbuf, 2)) {bad:		printf("ec%d: buffer mem not found\n", ui->ui_unit);		(void) ubamem(uban, ui->ui_flags, ECBUFSIZE*2, 0);		addr->ec_rcr = EC_MDISAB;	/* disable memory */		return (-1);	}#if VAX780	if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) {		uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr;		goto bad;	}#endif	if (ui->ui_alive == 0)		/* Only printf from autoconfig */		printf("ec%d: mem %x-%x\n", ui->ui_unit,			ui->ui_flags, ui->ui_flags + ECBUFSIZE*CLBYTES - 1);	ui->ui_type = 1;		/* Memory on, allocated */	return (0);}/* * Do output DMA to determine interface presence and * interrupt vector.  DMA is too short to disturb other hosts. */ecprobe(reg, ui)	caddr_t reg;	struct uba_device *ui;{	register int br, cvec;		/* r11, r10 value-result */	register struct ecdevice *addr = (struct ecdevice *)reg;	register caddr_t ecbuf = (caddr_t) &umem[ui->ui_ubanum][ui->ui_flags];#ifdef lint	br = 0; cvec = br; br = cvec;	ecrint(0); ecxint(0); eccollide(0);#endif	/*	 * Check that buffer memory was found and enabled.	 */	if (ui->ui_type == 0)		return(0);	/*	 * Make a one byte packet in what should be buffer #0.	 * Submit it for sending.  This should cause an xmit interrupt.	 * The xmit interrupt vector is 8 bytes after the receive vector,	 * so adjust for this before returning.	 */	*(u_short *)ecbuf = (u_short) 03777;	ecbuf[03777] = '\0';	addr->ec_xcr = EC_XINTEN|EC_XWBN;	DELAY(100000);	addr->ec_xcr = EC_XCLR;	if (cvec > 0 && cvec != 0x200) {		if (cvec & 04) {	/* collision interrupt */			cvec -= 04;			br += 1;		/* rcv is collision + 1 */		} else {		/* xmit interrupt */			cvec -= 010;			br += 2;		/* rcv is xmit + 2 */		}	}	return (1);}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */ecattach(ui)	struct uba_device *ui;{	struct ec_softc *es = &ec_softc[ui->ui_unit];	register struct ifnet *ifp = &es->es_if;	register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr;	int i, j;	u_char *cp;	ifp->if_unit = ui->ui_unit;	ifp->if_name = "ec";	ifp->if_mtu = ETHERMTU;	/*	 * Read the ethernet address off the board, one nibble at a time.	 */	addr->ec_xcr = EC_UECLR; /* zero address pointer */	addr->ec_rcr = EC_AROM;	cp = es->es_addr;#define	NEXTBIT	addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM	for (i=0; i < sizeof (es->es_addr); i++) {		*cp = 0;		for (j=0; j<=4; j+=4) {			*cp |= ((addr->ec_rcr >> 8) & 0xf) << j;			NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT;		}		cp++;	}	printf("ec%d: hardware address %s\n", ui->ui_unit,		ether_sprintf(es->es_addr));	ifp->if_init = ecinit;	ifp->if_ioctl = ecioctl;	ifp->if_output = ether_output;	ifp->if_start = ecstart;	ifp->if_reset = ecreset;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;	for (i=0; i<16; i++)		es->es_buf[i] 		    = (u_char *)&umem[ui->ui_ubanum][ui->ui_flags + 2048*i];	if_attach(ifp);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ecreset(unit, uban)	int unit, uban;{	register struct uba_device *ui;	if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_ubanum != uban)		return;	printf(" ec%d", unit);	ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING;	ecinit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ecinit(unit)	int unit;{	struct ec_softc *es = &ec_softc[unit];	struct ecdevice *addr;	register struct ifnet *ifp = &es->es_if;	int i, s;	/* not yet, if address still unknown */	if (ifp->if_addrlist == (struct ifaddr *)0)		return;	/*	 * Hang receive buffers and start any pending writes.	 * Writing into the rcr also makes sure the memory	 * is turned on.	 */	if ((ifp->if_flags & IFF_RUNNING) == 0) {		u_short start_read;		addr = (struct ecdevice *)ecinfo[unit]->ui_addr;		s = splimp();		/*		 * write our ethernet address into the address recognition ROM 		 * so we can always use the same EC_READ bits (referencing ROM),		 * in case we change the address sometime.		 * Note that this is safe here as the receiver is NOT armed.		 */		ec_setaddr(es->es_addr, unit);		/*		 * Arm the receiver#ifdef MULTI		if (es->es_if.if_flags & IFF_PROMISC)			start_read = EC_PROMISC;		else if (es->es_if.if_flags & IFF_MULTI)			start_read = EC_MULTI;		else#endif MULTI			start_read = EC_READ;		 */		for (i = ECRHBF; i >= ECRLBF; i--)			addr->ec_rcr = EC_READ | i;		es->es_if.if_flags &= ~IFF_OACTIVE;		es->es_mask = ~0;		es->es_if.if_flags |= IFF_RUNNING;		if (es->es_if.if_snd.ifq_head)			(void) ecstart(&es->es_if);		splx(s);	}}/* * Start output on interface.  Get another datagram to send * off of the interface queue, and copy it to the interface * before starting the output. */ecstart(ifp)struct ifnet *ifp;{	int unit = ifp->if_unit;	register struct ec_softc *es = &ec_softc[unit];	struct ecdevice *addr;	struct mbuf *m;	if ((es->es_if.if_flags & IFF_RUNNING) == 0)		return (0);	IF_DEQUEUE(&es->es_if.if_snd, m);	if (m == 0)		return (0);	ecput(es->es_buf[ECTBF], m);	addr = (struct ecdevice *)ecinfo[unit]->ui_addr;	addr->ec_xcr = EC_WRITE|ECTBF;	es->es_if.if_flags |= IFF_OACTIVE;	return (0);}/* * Ethernet interface transmitter interrupt. * Start another output if more data to send. */ecxint(unit)	int unit;{	register struct ec_softc *es = &ec_softc[unit];	register struct ecdevice *addr =		(struct ecdevice *)ecinfo[unit]->ui_addr;	if ((es->es_if.if_flags & IFF_OACTIVE) == 0)		return;	if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) {		printf("ec%d: stray xmit interrupt, xcr=%b\n", unit,			addr->ec_xcr, EC_XBITS);		es->es_if.if_flags &= ~IFF_OACTIVE;		addr->ec_xcr = EC_XCLR;		return;	}	es->es_if.if_opackets++;	es->es_if.if_flags &= ~IFF_OACTIVE;	es->es_mask = ~0;	addr->ec_xcr = EC_XCLR;	if (es->es_if.if_snd.ifq_head)		(void) ecstart(&es->es_if);}/* * Collision on ethernet interface.  Do exponential * backoff, and retransmit.  If have backed off all * the way print warning diagnostic, and drop packet. */eccollide(unit)	int unit;{	register struct ec_softc *es = &ec_softc[unit];	register struct ecdevice *addr =	    (struct ecdevice *)ecinfo[unit]->ui_addr;	register i;	int delay;	es->es_if.if_collisions++;	if ((es->es_if.if_flags & IFF_OACTIVE) == 0)		return;	/*	 * 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	 * backed off 16 times, and give up.	 */	if (es->es_mask == 0) {		u_short start_read;		es->es_if.if_oerrors++;		log(LOG_ERR, "ec%d: send error\n", unit);

⌨️ 快捷键说明

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