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

📄 if_ex.c

📁 open bsd vax module -if function
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Excelan Inc. * * 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_ex.c	7.9 (Berkeley) 12/16/90 */#include "ex.h"#if NEX > 0/* * Excelan EXOS 204 Interface * *	George Powers *	Excelan Inc. */#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/ioctl.h"#include "sys/syslog.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#ifdef ISO#include "netiso/iso.h"#include "netiso/iso_var.h"extern char all_es_snpa[], all_is_snpa[];#endif#include "../include/pte.h"#include "../include/cpu.h"#include "../include/mtpr.h"#include "if_exreg.h"#include "if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"/* #define DEBUG			/* check for "impossible" events */#define	NH2X 4			/* a sufficient number is critical */#define	NX2H 4			/* this is pretty arbitrary */#define	EXWATCHINTVL 10		/* call exwatch() every 10 seconds */int	exprobe(), exattach(), excdint();struct	uba_device *exinfo[NEX];u_short exstd[] = { 0 };struct	uba_driver exdriver =	{ exprobe, 0, exattach, 0, exstd, "ex", exinfo };int	exinit(),exstart(),ether_output(),exioctl(),exreset(),exwatch();struct ex_msg *exgetcbuf();/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * xs_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	ex_softc {	struct	arpcom xs_ac;		/* Ethernet common part */#define	xs_if	xs_ac.ac_if		/* network-visible interface */#define	xs_addr	xs_ac.ac_enaddr		/* hardware Ethernet address */#ifdef DEBUG	int	xs_wait;#endif	struct	ifuba xs_ifuba;		/* UNIBUS resources */	int	xs_flags;		/* private flags */#define	EX_XPENDING	1		/* xmit rqst pending on EXOS */#define	EX_STATPENDING	(1<<1)		/* stats rqst pending on EXOS */#define	EX_RUNNING	(1<<2)		/* board is running */#define EX_SETADDR	(1<<3)		/* physaddr has been changed */	struct	ex_msg *xs_h2xnext;	/* host pointer to request queue */	struct	ex_msg *xs_x2hnext;	/* host pointer to reply queue */	int	xs_ubaddr;		/* map info for structs below */#define	UNIADDR(x)	((u_long)(x)&0x3FFFF)#define	P_UNIADDR(x)	((u_long)(x)&0x3FFF0)	/* the following structures are always mapped in */	u_short	xs_h2xhdr;		/* EXOS's request queue header */	u_short	xs_x2hhdr;		/* EXOS's reply queue header */	struct	ex_msg xs_h2xent[NH2X];	/* request msg buffers */	struct	ex_msg xs_x2hent[NX2H];	/* reply msg buffers */	struct	confmsg xs_cm;		/* configuration message */	struct	stat_array xs_xsa;	/* EXOS writes stats here */	/* end mapped area */#define	INCORE_BASE(p)	((caddr_t)((u_long)(&(p)->xs_h2xhdr) & 0xFFFFFFF0))#define	RVAL_OFF(unit, n) \	((caddr_t)(&(ex_softc[unit].n)) - INCORE_BASE(&ex_softc[unit]))#define	LVAL_OFF(unit, n) \	((caddr_t)(ex_softc[unit].n) - INCORE_BASE(&ex_softc[unit]))#define	H2XHDR_OFFSET(unit)	RVAL_OFF(unit, xs_h2xhdr)#define	X2HHDR_OFFSET(unit)	RVAL_OFF(unit, xs_x2hhdr)#define	H2XENT_OFFSET(unit)	LVAL_OFF(unit, xs_h2xent)#define	X2HENT_OFFSET(unit)	LVAL_OFF(unit, xs_x2hent)#define	CM_OFFSET(unit)		RVAL_OFF(unit, xs_cm)#define	SA_OFFSET(unit)		RVAL_OFF(unit, xs_xsa)#define	INCORE_SIZE(unit)	RVAL_OFF(unit, xs_end)	int	xs_end;			/* place holder */} ex_softc[NEX];/* * The following structure is a kludge to store a cvec value * between the time exprobe is called, and exconfig. */struct	ex_cvecs {	struct	exdevice *xc_csraddr;	int	xc_cvec;}ex_cvecs[NEX];int	ex_ncall = 0;			/* counts calls to exprobe */exprobe(reg)	caddr_t reg;{	register int br, cvec;		/* r11, r10 value-result */	register struct exdevice *addr = (struct exdevice *)reg;	register i;	/*	 * We program the EXOS interrupt vector, like dmf device.	 */	br = 0x15;	cvec = (uba_hd[numuba].uh_lastiv -= 4);	ex_cvecs[ex_ncall].xc_csraddr = addr;	ex_cvecs[ex_ncall].xc_cvec = cvec;	/*	 * Reset EXOS and run self-test (guaranteed to	 * complete within 2 seconds).	 */	addr->xd_porta = EX_RESET;	i = 2000;	while (((addr->xd_portb & EX_TESTOK) == 0) && --i)		DELAY(1000);	if ((addr->xd_portb & EX_TESTOK) == 0) {		printf("ex: self-test failed\n");		return 0;	}#ifdef lint	br = br;	excdint(0);#endif	ex_ncall++;	return (sizeof(struct exdevice));}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets.  Board is temporarily configured and issues * a NET_ADDRS command, only to get the Ethernet address. */exattach(ui)	register struct uba_device *ui;{	register struct ex_softc *xs = &ex_softc[ui->ui_unit];	register struct ifnet *ifp = &xs->xs_if;	register struct exdevice *addr = (struct exdevice *)ui->ui_addr;	register struct ex_msg *bp;	int unit = ui->ui_unit;	ifp->if_unit = ui->ui_unit;	ifp->if_name = "ex";	ifp->if_mtu = ETHERMTU;	/*	 * Temporarily map queues in order to configure EXOS	 */	xs->xs_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(xs),		INCORE_SIZE(unit), 0);	exconfig(ui, 0);			/* without interrupts */	if (xs->xs_cm.cm_cc) goto badconf;	bp = exgetcbuf(xs);	bp->mb_rqst = LLNET_ADDRS;	bp->mb_na.na_mask = READ_OBJ;	bp->mb_na.na_slot = PHYSSLOT;	bp->mb_status |= MH_EXOS;	addr->xd_portb = EX_NTRUPT;	bp = xs->xs_x2hnext;	while ((bp->mb_status & MH_OWNER) == MH_EXOS)	/* poll for reply */		;	printf("ex%d: HW %c.%c, NX %c.%c, hardware address %s\n",		ui->ui_unit, xs->xs_cm.cm_vc[2], xs->xs_cm.cm_vc[3],		xs->xs_cm.cm_vc[0], xs->xs_cm.cm_vc[1],		ether_sprintf(bp->mb_na.na_addrs));	bcopy((caddr_t)bp->mb_na.na_addrs, (caddr_t)xs->xs_addr,	    sizeof (xs->xs_addr));	ifp->if_init = exinit;	ifp->if_output = ether_output;	ifp->if_start = exstart;	ifp->if_ioctl = exioctl;	ifp->if_reset = exreset;	ifp->if_flags = IFF_BROADCAST;	xs->xs_ifuba.ifu_flags = UBA_CANTWAIT;	if_attach(ifp);badconf:	ubarelse(ui->ui_ubanum, &xs->xs_ubaddr);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */exreset(unit, uban)	int unit, uban;{	register struct uba_device *ui;	if (unit >= NEX || (ui = exinfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_ubanum != uban)		return;	printf(" ex%d", unit);	ex_softc[unit].xs_if.if_flags &= ~IFF_RUNNING;	ex_softc[unit].xs_flags &= ~EX_RUNNING;	exinit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. * Called at boot time (with interrupts disabled?), * and at ifconfig time via exioctl, with interrupts disabled. */exinit(unit)	int unit;{	register struct ex_softc *xs = &ex_softc[unit];	register struct uba_device *ui = exinfo[unit];	register struct exdevice *addr = (struct exdevice *)ui->ui_addr;	register struct ifnet *ifp = &xs->xs_if;	register struct ex_msg *bp;	int s;	/* not yet, if address still unknown */	if (ifp->if_addrlist == (struct ifaddr *)0)		return;	if (xs->xs_flags & EX_RUNNING)		return;	if ((ifp->if_flags & IFF_RUNNING) == 0) {		if (if_ubainit(&xs->xs_ifuba, ui->ui_ubanum,		    sizeof (struct ether_header),		    (int)btoc(EXMAXRBUF-sizeof(struct ether_header))) == 0) { 			printf("ex%d: can't initialize\n", unit);			xs->xs_if.if_flags &= ~IFF_UP;			return;		}		xs->xs_ubaddr = uballoc(ui->ui_ubanum, INCORE_BASE(xs),			INCORE_SIZE(unit), 0);	}	exconfig(ui, 4);		/* with vectored interrupts*/	/*	 * Put EXOS on the Ethernet, using NET_MODE command	 */	bp = exgetcbuf(xs);	bp->mb_rqst = LLNET_MODE;	bp->mb_nm.nm_mask = WRITE_OBJ;	bp->mb_nm.nm_optn = 0;	bp->mb_nm.nm_mode = MODE_PERF;	bp->mb_status |= MH_EXOS;	addr->xd_portb = EX_NTRUPT;	bp = xs->xs_x2hnext;	while ((bp->mb_status & MH_OWNER) == MH_EXOS)	/* poll for reply */		;	bp->mb_length = MBDATALEN;	bp->mb_status |= MH_EXOS;		/* free up buffer */	addr->xd_portb = EX_NTRUPT;		/* tell EXOS about it */	xs->xs_x2hnext = xs->xs_x2hnext->mb_next;	ifp->if_watchdog = exwatch;	ifp->if_timer = EXWATCHINTVL;	s = splimp();	/* are interrupts always disabled here, anyway? */	exhangrcv(unit);			/* hang receive request */	xs->xs_if.if_flags |= IFF_RUNNING;	xs->xs_flags |= EX_RUNNING;	if (xs->xs_flags & EX_SETADDR)		ex_setaddr((u_char *)0, unit);#ifdef ISO	ex_setmulti(all_es_snpa, unit, 1);	ex_setmulti(all_is_snpa, unit, 2);#endif	(void) exstart(&xs->xs_if);			/* start transmits */	splx(s);}/* * Reset, test, and configure EXOS.  This routine assumes * that message queues, etc. have already been mapped into * the UBA.  It is called by exinit, and should also be * callable by exattach. */exconfig(ui, itype)	struct	uba_device *ui;	int itype;{	register int unit = ui->ui_unit;	register struct ex_softc *xs = &ex_softc[unit];	register struct exdevice *addr = (struct exdevice *) ui->ui_addr;	register struct confmsg *cm = &xs->xs_cm;	register struct ex_msg *bp;	int i;	u_long shiftreg;	xs->xs_flags = 0;	/*	 * Reset EXOS, wait for self-test to complete	 */	addr->xd_porta = EX_RESET;	while ((addr->xd_portb & EX_TESTOK) == 0)		;	/*	 * Set up configuration message.	 */	cm->cm_1rsrv = 1;	cm->cm_cc = 0xFF;	cm->cm_opmode = 0;		/* link-level controller mode */	cm->cm_dfo = 0x0101;		/* enable host data order conversion */	cm->cm_dcn1 = 1;	cm->cm_2rsrv[0] = cm->cm_2rsrv[1] = 0;	cm->cm_ham = 3;			/* absolute address mode */	cm->cm_3rsrv = 0;	cm->cm_mapsiz = 0;	cm->cm_byteptrn[0] = 0x01;	/* EXOS deduces data order of host */	cm->cm_byteptrn[1] = 0x03;	/*  by looking at this pattern */	cm->cm_byteptrn[2] = 0x07;	cm->cm_byteptrn[3] = 0x0F;	cm->cm_wordptrn[0] = 0x0103;	cm->cm_wordptrn[1] = 0x070F;	cm->cm_lwordptrn = 0x0103070F;	for (i=0; i<20; i++) cm->cm_rsrvd[i] = 0;	cm->cm_mba = 0xFFFFFFFF;	cm->cm_nproc = 0xFF;	cm->cm_nmbox = 0xFF;	cm->cm_nmcast = 0xFF;	cm->cm_nhost = 1;	cm->cm_h2xba = P_UNIADDR(xs->xs_ubaddr);	cm->cm_h2xhdr = H2XHDR_OFFSET(unit);	cm->cm_h2xtyp = 0;		/* should never wait for rqst buffer */	cm->cm_x2hba = cm->cm_h2xba;	cm->cm_x2hhdr = X2HHDR_OFFSET(unit);	cm->cm_x2htyp = itype;		/* 0 for none, 4 for vectored */	for (i=0; (addr != ex_cvecs[i].xc_csraddr); i++)#ifdef DEBUG	if (i >= NEX)		panic("ex: matching csr address not found");#endif		;

⌨️ 快捷键说明

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