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

📄 if_ix.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Micom-Interlan 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_ix.c	7.8 (Berkeley) 12/16/90 */#include "np.h"#if NNP > 0/* * Interlan NP100 Ethernet Communications 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/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/if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"#include "../uba/npreg.h"#include "../if/if_ix.h"int	ixattach(), ixrint(), ixcint();#define	ILUNIT(x)	minor(x)int	ixinit(), ixioctl(), ixreset(), ixwatch(), ixstart();int (*IxAttach)() = ixattach;int (*IxReset)() = ixreset;/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * ix_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	ix_softc {	struct	arpcom ix_ac;		/* Ethernet common part */#define	ix_if	ix_ac.ac_if		/* network-visible interface */#define	ix_addr	ix_ac.ac_enaddr		/* hardware Ethernet address */	int	ix_flags;#define	IXF_OACTIVE	0x1		/* output is active */#define	IXF_RCVPENDING	0x2		/* start rcv in ilcint */#define	IXF_GOTUBA	0x4		/* unibus resources mapped */#define	IXF_RUNNING	0x8		/* board is running */#define	IXF_SETADDR	0x10		/* physical address is changed */#define	IXF_STATPENDING	0x20		/* stat cmd pending */#define	IXF_GOTCQE	0x40		/* np resources available */#define	IXF_OWATCH	0x80		/* is output hung? */#define	IXF_RWATCH	0x100		/* is input hung? */	struct	ifuba ix_ifuba;		/* unibus resources */	u_short	ix_aid;			/* Access Id returned by open DDL */	u_short ix_badcqe;	struct	npmaster *ix_mp;	/* Board physio request header */	struct	npreq *ix_rrp;		/* Cached npreq for recv */	struct	npreq *ix_wrp;		/* Cached npreq for xmit */	short	ix_scaninterval;	/* interval of stat collection */#define	IXWATCHINTERVAL	60		/* once every 60 seconds */	union	ix_stats ix_stats;	/* holds on-board statistics */	int	ix_ubaddr;		/* mapping registers of ix_stats */} ix_softc[NNP];extern struct uba_device *npdinfo[];/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets.  We can't even get the ethernet address * or other interesting data until the board has been downloaded. * running ifconfig will attempt to start unit. */ixattach(ui)	struct uba_device *ui;{	register struct ix_softc *ix = &ix_softc[ui->ui_unit];	register struct ifnet *ifp = &ix->ix_if;	extern struct npmaster npmasters[];	ifp->if_unit = ui->ui_unit;	ifp->if_name = "ix";	ifp->if_mtu = ETHERMTU;	ifp->if_flags = IFF_BROADCAST;	ifp->if_init = ixinit;	ifp->if_output = ether_output;	ifp->if_start = ixstart;	ifp->if_ioctl = ixioctl;	ifp->if_reset = ixreset;	ix->ix_mp = npmasters + ui->ui_unit;	ix->ix_ifuba.ifu_flags = UBA_CANTWAIT;	if_attach(ifp);}struct npreq *ix_GetReq(mp, addr, len)	struct npmaster *mp;	caddr_t addr;{	int unit = mp->unit;	register struct npreq *rp;	register struct CQE *ep;	struct ix_softc *ix = ix_softc + unit;	extern struct npreq *NpGetReq();	while ((rp = NpGetReq(mp->reqtab)) == NULL) {		mp->reqtab->flags |= WANTREQ;		sleep((caddr_t)(mp->reqtab), PZERO - 1);	}	rp->flags = KERNREQ;			/* Clear flags */	ep = rp->element;			/* Associated CQE */	ep->cqe_famid = (unsign32)ix;		/* Process ID */	ep->cqe_wind = 0;			/* Amount of buffer mapped */	ep->cqe_nbuf = 1;			/* Must be 1, no buffer chain */	ep->cqe_char = 1;			/* Driver owns this CQE */	ep->cqe_prot = NPDLA;			/* Data Link Access  protocol */	ep->cqe_bcnt = len;			/* Byte count */	rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */	ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr);	ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr);	return (rp);}ix_DoReq(mp, rp, cmd, addr, len, rpb, routine)	struct npmaster *mp;	register struct npreq *rp;	u_short cmd;	caddr_t addr;	int len;	register u_short *rpb;	int (*routine)();{	register struct CQE *ep = rp->element;	register u_short *p = &ep->rpb1;	u_short cnt = *rpb++;	extern long NpDebug;	int pri;	int result = 0;	ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR;	/* Clear status */	ep->cqe_bcnt = len;			/* Byte count */	rp->flags = KERNREQ | REQALOC;			/* Clear flags */	rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */	rp->intr = routine;	rp->user = (caddr_t) (ep->cqe_func = cmd);/* In case pissed on in CQE */	ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr);	ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr);	ep->cqe_lenrpb = cnt + cnt;	for (; cnt > 0; cnt--) *p++ = *rpb++;	if (NpDebug & DEBCQE)		printf("Function is %x ep %x reqid %x\n", ep->cqe_func, ep, ep->cqe_reqid);	if (NpDebug & DEBCQE)		printf("irp len = %x rp = %x\n", ep->cqe_lenrpb, rp);	if (routine == 0) {		NpAddReq(mp->reqtab, rp);	/* Queue onto active list */		while (!(rp->flags & REQDONE)) {			pri = spl5();			NpAddCQE(ep, &mp->shmemp->devcq, mp);			sleep((caddr_t)rp, PZERO - 1);			splx(pri);		}		if (rp->flags & IOABORT || ep->cqe_sts != NPDONE		    || ep->cqe_ust0 != NPDONE		    || ep->cqe_ust1 != NPOK) {			struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid;			printf("ix%d: Req failed, cmd %x, stat %x, flags %x, ",				ix->ix_if.if_unit, rp->user,				ep->cqe_sts, rp->flags);			printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1);			result = 1;		}		NpRemReq(rp);			/* Clear request */	} else {		pri = spl5();		NpAddCQE(ep, &mp->shmemp->devcq, mp);		splx(pri);	}	return(result);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */ixreset(unit, uban, softp)	int unit, uban;	caddr_t softp;{	register struct uba_device *ui;	int mask = IXF_SETADDR;		/* Only remember new physaddr */	if (unit >= NNP || (ui = npdinfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_ubanum != uban)		return;	printf(" ix%d reset", unit);	if (softp) 		mask |= IXF_GOTUBA;	/* UBA mapping regs still valid; */	ix_softc[unit].ix_if.if_flags &= ~IFF_RUNNING;	ix_softc[unit].ix_flags &= mask;}int ix_MacLoop = 0;/* * Initialization of interface; clear recorded pending * operations, and reinitialize UNIBUS usage. */ixinit(unit)	int unit;{	register struct ix_softc *ix = &ix_softc[unit];	struct uba_device *ui = npdinfo[unit];	register struct ifnet *ifp = &ix->ix_if;	register struct CQE *ep;	struct npreq *rp;	struct npmaster *mp = ix->ix_mp;	register u_short *dpmp = & mp->shmemp->statblock.sb_dpm;	u_short rpb[7];	int s;	/* not yet, if address still unknown */	if ((ifp->if_addrlist == (struct ifaddr *)0) ||	    (ix->ix_flags & IXF_RUNNING))		return;	if ((mp->flags & AVAILABLE) == 0 || (*dpmp & PROTOMASK(NPDLA)) == 0) {		ifp->if_flags &= ~IFF_UP;		return;	}	if ((ix->ix_flags & IXF_GOTUBA) == 0) {		ix->ix_ifuba.ifu_flags = UBA_CANTWAIT;		if (if_ubainit(&ix->ix_ifuba, ui->ui_ubanum,		    sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 			printf("ix%d: can't initialize\n", unit);			ix->ix_if.if_flags &= ~IFF_UP;			return;		}		ix->ix_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&ix->ix_stats,			sizeof (union ix_stats), 0);		ix->ix_flags |= IXF_GOTUBA;	}	if ((ix->ix_flags & IXF_GOTCQE) == 0) {		ix->ix_rrp = ix_GetReq(mp, ix->ix_ifuba.ifu_r.ifrw_info,								ETHERMTU);		ix->ix_wrp = ix_GetReq(mp, 0, 0);		ix->ix_flags |= IXF_GOTCQE;	}	rp = ix->ix_wrp;	ep = rp->element;	/* Changing the ethernet address resets the dla module,	   so must do it before opening the channel */	if (ix->ix_flags & IXF_SETADDR) {		register char *cp = (char *) &ix->ix_stats;		int spincount;		int x;		/* Try Issuing an open channel request before reprogramming		   the physical address */		rpb[0] = 6;		/* RPB length */		rpb[2] = 0x10;		/* Share with any smart users */		rpb[3] = 0;		/* Take (a copy of) all frames */		rpb[5] = 8;		/* On board rcv queue length */		rpb[6] = 0;		/* XMT packets as is */		if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0))			return;		/* Proceed with LDPA */		*cp++ = 1;		bcopy(ix->ix_addr, (caddr_t)cp, 6);		rpb[0] = 1;				/* RPB length */		if (ix_DoReq(mp, rp, IXC_LDPA, ix->ix_ubaddr, 7, rpb, 0))			return;#ifndef TheyFinallyFixedTheBoard		/* Board requires some time to reinitialize its protocols */		x = spl1();		spincount = 2000000;		while (((*dpmp & PROTOMASK(NPDLA))==0) && spincount > 0)			spincount--;		if (spincount==0) {			printf("ix%d: failed to reinitialize DLA module\n",					unit);			splx(x);		}		splx(x);#endif	}	rpb[0] = 6;		/* RPB length */	rpb[2] = 0x10;		/* Share with any smart users */	if (ix_MacLoop) rpb[2] |= 0x8;				/* Enable software loopback on board */	rpb[3] = 0;		/* Take (a copy of) all frames */	rpb[5] = 8;		/* On board rcv queue length */	rpb[6] = 0;		/* XMT packets as is */	if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0))		return;	ix->ix_aid = ep->rpb1;	/* Here we request our ethernet address, if we didn't reset it*/	if ((ix->ix_flags & IXF_SETADDR)==0) {		rpb[0] = 2;		rpb[1] = ix->ix_aid;		rpb[2] = 0;		/* get all stats */

⌨️ 快捷键说明

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