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

📄 if_xna.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef lintstatic char *sccsid = "@(#)if_xna.c	4.3      (ULTRIX)        2/26/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1988 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.			* *									* *   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.	* *									* ************************************************************************/#include "xna.h"#if NXNA > 0 || defined(BINARY)/* * Revision History: * *	02/24/91 - jsd *		   Allow loopback packets if COPYALL mode is set * *	10/19/89 - Uttam Shikarpur *		   Added "if_version" support to return H/W type *		   Added counters for multicast packets and bytes sent. * *	07/11/89 - Fred L. Templin *		   Changed port register addressing to work with DEMNA. * *	07/11/89 - Ali Rafieymehr *		   Added XMI support for device interrupts and configuration. *		   Also, moved xnadriver initialization here from bi_data.c. * *	06/14/89 - Fred L. Templin *		   Packet filter support integrated. * *	06/12/89 - Fred L. Templin *		   Integrated error logging support for XNA port fatal *		   errors. * *	05/10/89 - Fred L. Templin *		   Re-architected "wait-for-command-completion" strategy. *		   Kick off timers instead of calls to sleep. * *	4/11/88  - Fred L. Templin *		   Added MIPS-to-VAX physical addressing mode for MIPS * *	04/07/89 - Fred L. Templin *		   Added locks to make the XNA driver SMP-Safe * *	12/12/88 - Fred L. Templin *		   Code cleanup for initial baselevel submit * *	08/29/88 - Fred L. Templin *		   Created the if_xna.c module */#include "packetfilter.h"	/* NPACKETFILTER */#include "../data/if_xna_data.c"#include "../h/types.h"#include "../h/errlog.h"extern	struct protosw *iftype_to_proto(), *iffamily_to_proto();extern	int net_output();extern	struct bidata bidata[];extern	struct timeval	time;extern	struct xmidata *get_xmi();int	xnaattach(), xnaintr(), xnaprobe();int	xnainit(),xnastart(),xnaioctl(),xnareset(), xnawatch();struct	mbuf *xnamkparam(), *xnamkuser();u_char  xna_notset[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};#define XNAMCLGET(m) { \	register struct mbuf *p; \	MGET((m), M_DONTWAIT, MT_DATA); \	if ((m)) { \		MCLGET((m), p); \		m->m_len = CLBYTES; \		if (p == 0) { \			m_freem((m)); \			(m) = (struct mbuf *)NULL; \		} \	} \}#define	XNATIMEOUT(xcmd, val) { \	register int s = splnet(); \	register long sec0 = time.tv_sec; \	while (((xcmd)->opcode == (val)) && ((time.tv_sec - sec0) < 3)); \	if ((xcmd)->opcode == (val)) \		(xcmd)->opcode = CMD_NOP; \	splx(s); \}/* * Probe the XNA; set up the register mappings with "nxv" giving the * base address. */xnaprobe(nxv,nxp,number,node,ui)	caddr_t nxv;	struct	uba_device *ui;{	register struct	xna_softc *sc = &xna_softc[ui->ui_unit];	register struct	xnadevice *addr = &sc->xregs;	register struct xnapdb *xpdb;	register int delay;	struct xnarecv_ring *rp;	struct xnacmd_ring *tp;	struct xmidata *xmidata;	struct mbuf *m;	int unit = ui->ui_unit;	caddr_t dpa;	int i;	/*	 * Determine device type (DEBNI, DEXNA). Map register blocks	 * and check for power-up errors.	 */	addr->xnabase = (struct xnabase *)nxv;	switch (addr->xna_dtype & XMIDTYPE_TYPE) {		case XNADEXNA:			addr->_xpd1 = (struct xnareg *)(nxv + XNAPD1_XMI);			addr->_xpd2 = (struct xnareg *)(nxv + XNAPD2_XMI);			addr->_xpst = (struct xnareg *)(nxv + XNAPST_XMI);			addr->_xpud = (struct xnareg *)(nxv + XNAPUD_XMI);			addr->_xpci = (struct xnareg *)(nxv + XNAPCI_XMI);			addr->_xpcp = (struct xnareg *)(nxv + XNAPCP_XMI);			addr->_xpcs = (struct xnareg *)(nxv + XNAPCS_XMI);			/*			 * Wait up to 10 seconds for XPST_UNDEF state			 * to appear.			 */			for (delay = 1000;			     (delay && (addr->xnapst != XPST_UNDEF));			     delay--)				DELAY(10000);			if ((addr->xber_xmi & XMI_STF) ||			     (addr->xnapst != XPST_UNDEF)) {				printf ("xna%d: port self test failed: xber = 0x%x, xpst = 0x%x, xpd1 = 0x%x, xpd2 = 0x%x, xpud = 0x%x\n",					unit, addr->xber_xmi, addr->xnapst, addr->xnapd1, addr->xnapd2, addr->xnapud);				return(0);			}			break;		case XNADEBNI:			addr->_xpst = (struct xnareg *)(nxv + XNAPST_BI);			addr->_xpd1 = (struct xnareg *)(nxv + XNAPD1_BI);			addr->_xpd2 = (struct xnareg *)(nxv + XNAPD2_BI);			addr->_xpud = (struct xnareg *)(nxv + XNAPUD_BI);			addr->_xpci = (struct xnareg *)(nxv + XNAPCI_BI);			addr->_xpcp = (struct xnareg *)(nxv + XNAPCP_BI);			addr->_xpcs = (struct xnareg *)(nxv + XNAPCS_BI);			/*			 * Same as for DEXNA. Wait up to 10 seconds. If the			 * BROKE bit is set, or we're in the wrong state,			 * perform hard node restart.			 */			for (delay = 1000;			     (delay && (addr->xnapst != XPST_UNDEF));			     delay--)				DELAY(10000);			if ((addr->xctrl_bi & BICTRL_BROKE) ||			     (addr->xnapst != XPST_UNDEF)) {				printf ("xna%d: port self test failed: bi_ctrl = 0x%x, bi_err = 0x%x, xpst = 0x%x, xpd1 = 0x%x, xpd2 = 0x%x, xpud = 0x%x\n",					unit, addr->xctrl_bi, addr->xber_bi, addr->xnapst, addr->xnapd1, addr->xnapd2, addr->xnapud);				return(0);			}			break;		default:			return (0);	}	/*	 * We are now guaranteed that the port has succesfully completed	 * self test and is in the "UNINITIALIZED" state. At this point,	 * we can grab the default physical address from the port data	 * registers.	 */	dpa = (caddr_t)&addr->xnapd1;	for (i = 0; i < 4; i++)		sc->is_dpaddr[i] = *dpa++;	dpa = (caddr_t)&addr->xnapd2;	for (; i < 6; i++)		sc->is_dpaddr[i] = *dpa++;	/*	 * Device actual physical address not set yet	 */	bcopy(xna_notset, sc->is_addr, 6);	/*	 * allocate data structures, fill out port data block, and init device.	 */	KM_ALLOC(sc->rring,struct xnarecv_ring *,1024,KM_DEVBUF,KM_NOW_CL_CO_CA);	if (sc->rring == 0) {		printf ("xna%d: couldn't allocate receive ring\n", unit);		return (0);	}	KM_ALLOC(sc->tring,struct xnacmd_ring *,1024,KM_DEVBUF,KM_NOW_CL_CO_CA);	if (sc->tring == 0) {		printf ("xna%d: couldn't allocate command ring\n", unit);		KM_FREE(sc->rring, KM_DEVBUF);		return (0);	}	KM_ALLOC(sc->xpdb,struct xnapdb *,512,KM_DEVBUF,KM_NOW_CL_CO_CA);	if ((xpdb = sc->xpdb) == 0) {		printf ("xna%d: couldn't allocate port data block\n", unit);		KM_FREE(sc->rring, KM_DEVBUF);		KM_FREE(sc->tring, KM_DEVBUF);		return (0);	}	/*	 * Init first sc->nactv receive descriptors with buffer allocation	 * side-effects. (use nNXNAACTV as initial value). xnainitdesc()	 * will turn off ownership bit to give the descriptor to the port.	 * (XNAMCLGET() CAN fail in the case that there are no mbuf's	 * available, but the "while" loop in the receive interrupt handler	 * will initialize more as mbufs become available.) Set ownership of	 * left-over descriptors to the port driver.	 */	sc->nactv = nNXNAACTV;	for (i = 0, rp = &sc->rring[0]; (i < sc->nactv); i++, rp++) {		XNAMCLGET(m);		if (m)			xnainitdesc(rp, m);		else			break;	}	sc->nrecv = i;	for (; i < nNXNARCV; i++, rp++)		rp->status = ST_ROWN;	for (i = 0, tp = &sc->tring[0]; i < nNXNACMD; i++, tp++)		tp->status = ST_TOWN;	/*	 * sc->tindex == index of next transmit/command desc. to activate	 * sc->tlast  == index of last transmit/command processed	 * sc->nxmit  == # of transmit/commands pending	 * sc->rindex == index of next recv. descriptor to activate	 * sc->rlast  == index of last receive processed	 * sc->nrecv  == # of receive descriptors currently active	 * sc->nproc  == running count of receives and transmits processed	 */	sc->tindex = sc->nxmit = 0;	sc->rindex = sc->nrecv;	sc->rlast = sc->tlast = sc->nproc = -1;#ifdef	vax	xpdb->addr_mode = AM_VIRT30;	/* 30-bit, non-interlocked virtual */	xpdb->cmd.xaddr_lo = (u_long)sc->tring;	xpdb->recv.xaddr_lo = (u_long)sc->rring;	xpdb->spt_len = (u_long)mfpr(SLR);	xpdb->spt.xaddr_lo = (u_long)mfpr(SBR);	xpdb->gpt = (u_long)(0x80000000 + mfpr(SBR)); /* Virt. address */	xpdb->ubua.xaddr_lo = (u_long)&sc->xna_ubuacnt;#endif vax#ifdef	mips	xpdb->addr_mode = AM_PHYS40;	/* 40 bit, non-interlocked physical */	xpdb->cmd.xaddr_lo = svtophy(sc->tring);	xpdb->recv.xaddr_lo = svtophy(sc->rring);	xpdb->ubua.xaddr_lo = svtophy(&sc->xna_ubuacnt);#endif	mips	xpdb->cmd.xaddr_hi = 0;	xpdb->cmd.xlen = sizeof(struct xnacmd_ring); /* cmd ring entry size */	xpdb->recv.xaddr_hi = xpdb->recv.xmbz = 0;	xpdb->spt.xaddr_hi = xpdb->spt.xmbz = 0;	xpdb->ubua.xaddr_hi = 0;	xpdb->ubua.xlen = sizeof(struct xnactr_ent);	/*	 * set up interrupt and error interrupt vectors	 */	switch (addr->xna_dtype & XMIDTYPE_TYPE) {		case XNADEXNA:			xmidata = get_xmi(number);			xpdb->ivec.level = xpdb->evec.level = 1;			xpdb->ivec.vector = xpdb->evec.vector =			   SCB_XMI_VEC_ADDR(xmidata, number,node,LEVEL15) -			   &scb.scb_stray;			xpdb->ivec.nid_mask = xpdb->evec.nid_mask =			   xmidata->xmiintr_dst;			break;		case XNADEBNI:			xpdb->ivec.level = xpdb->evec.level = 1;			xpdb->ivec.vector = xpdb->evec.vector =			   SCB_BI_VEC_ADDR(number,node,LEVEL15) -			   &scb.scb_stray;			xpdb->ivec.nid_mask = xpdb->evec.nid_mask =			   bidata[number].biintr_dst;			break;	}	/*	 * Set up user buffer unavailable counter	 */	xpdb->ubua.xaddr_lo = (u_long)&sc->xna_ubuacnt;	xpdb->ubua.xaddr_hi = 0;	xpdb->ubua.xlen = sizeof(struct xnactr_ent);	/*	 * Hit device init, and wait for XPST_INIT state to appear (up to	 * one second).	 */	addr->xnapd1 = svtophy(xpdb); addr->xnapd2 = 0;	addr->xnapci = XPCI_INIT;	for (delay = 100; (delay && (addr->xnapst != XPST_INIT)); delay--)		DELAY(10000);	if ((addr->xnapst & XPST_MASK) != XPST_INIT) {		printf ("xna%d: port probe failed: xpst=0x%x, xpd1=0x%x, xpd2=0x%x, xpud=0x%x\n",			unit, addr->xnapst, addr->xnapd1, addr->xnapd2, addr->xnapud);		return (0);	}	/*	 * Get the initial value of the "potential system buffer unavailable"	 * counter.	 */	sc->xna_sbuacnt = xpdb->p_sbua;	return (sizeof(struct xna_softc));}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */xnaattach(ui)	struct uba_device *ui;{	register struct xna_softc *sc = &xna_softc[ui->ui_unit];	register struct xnadevice *addr = &sc->xregs;	register struct ifnet *ifp = &sc->is_if;	struct sockaddr_in *sin;	register int i;	ifp->if_unit = ui->ui_unit;	ifp->if_name = "xna";	ifp->lk_softc = &sc->lk_xna_softc;	ifp->if_mtu = ETHERMTU;	ifp->if_type = IFT_ETHER;	ifp->if_flags |= IFF_BROADCAST|IFF_DYNPROTO|IFF_NOTRAILERS;	((struct arpcom *)ifp)->ac_ipaddr.s_addr = 0;	/*	 * Initialize multicast address table	 */	for (i = 0; i < NMULTI; i++) {		bcopy(etherbroadcastaddr, sc->is_multi[i], 6);		sc->is_muse[i] = 0;	}	/*	 * Set maxlen for the command queue; attach interface	 */	lockinit(&sc->lk_xna_softc, &lock_device15_d);	sc->if_cmd.ifq_maxlen = IFQ_MAXLEN;	sin = (struct sockaddr_in *)&ifp->if_addr;	sin->sin_family = AF_INET;	ifp->if_init = xnainit;	ifp->if_output = net_output;	ifp->if_start = xnastart;	ifp->if_ioctl = xnaioctl;	ifp->if_reset = xnareset;	ifp->if_watchdog = xnawatch;	ifp->if_timer = 1;	ifp->d_affinity = ALLCPU;	/*	 * Hook up the device interrupt vector to begin allowing interrupts.	 * We know that the device has been successfully initialized at this	 * point. Initialize if_version string.	 */	switch (addr->xna_dtype & XMIDTYPE_TYPE) {		case XNADEXNA:			xmidev_vec(ui->ui_adpt, ui->ui_nexus, LEVEL15, ui);			bcopy("DEC DEMNA Ethernet Interface", ifp->if_version, 28);			ifp->if_version[28] = '\0';			break;		case XNADEBNI:			bidev_vec(ui->ui_adpt, ui->ui_nexus, LEVEL15, ui);			bcopy("DEC DEBNI Ethernet Interface", ifp->if_version, 28);			ifp->if_version[28] = '\0';			break;	}	printf("xna%d: %s, hardware address %s\n", ifp->if_unit,	       ifp->if_version, ether_sprintf(sc->is_dpaddr));#if	NPACKETFILTER > 0	attachpfilter(&(sc->is_ed));#endif	NPACKETFILTER	if_attach(ifp);}/* * Initialize interface. May be called by a user process or a software * interrupt scheduled by xnareset(). */xnainit(unit)	int unit;{	register struct xna_softc *sc = &xna_softc[unit];	register struct xnadevice *addr = &sc->xregs;	register struct xnacmd_buf *xcmd;	register struct mbuf *m;	register int delay;	struct ifnet *ifp = &sc->is_if;	int s, t;	/* not yet, if address still unknown */	if (ifp->if_addrlist == (struct ifaddr *)0)		return;	if (ifp->if_flags & IFF_RUNNING)		return;	/*	 * Lock the softc to ensure coherency of softc data needed to fill	 * out the command buffers by "xnamkparam()" and "xnamkuser()", and	 * to lock access to the if_cmd queue by "xnacmd()". (xnaintr writes	 * command completion info. into the first longword of the command	 * buffer; XNATIMEOUT flags command timeouts. Need the splnet() if	 * we're called from softclock() by xnareset.	 */	s = splnet(); t = splimp();	smp_lock(&sc->lk_xna_softc, LK_RETRY);	/*	 * Issue a "PARAM" command to fill in actual physical address (from	 * sc->is_addr) and other system parameters. Wait for completion,	 * which will be signaled by the interrupt handler.	 */	if (m = xnamkparam(sc, ifp)) {		xnacmd(sc, m);		smp_unlock(&sc->lk_xna_softc);		splx(t);		xcmd = mtod(m, struct xnacmd_buf *);		XNATIMEOUT(xcmd, CMD_PARAM);	/* Wait */		t = splimp();		smp_lock(&sc->lk_xna_softc, LK_RETRY);		switch (xcmd->opcode) {			case CMD_COMPLETE:				/*				 * Set actual physical address				 */				bcopy(&xcmd->xnaparam.apa, sc->is_addr, 6);				m_freem(m);

⌨️ 快捷键说明

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