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

📄 if_dmv.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
#ifndef lintstatic char *sccsid = "@(#)if_dmv.c	4.2	(ULTRIX)	9/4/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1986 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.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   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.	* *									* ************************************************************************//* ------------------------------------------------------------------------ * Modification History: /sys/vaxif/if_dmv.c * *  11/29/88 -- jaw - remove cursysproc stuff. * *  12/28/86 -- ejf - report threshold error only once. * *  12/16/86 -- ejf - fixed problem where IPL could be lowered below device ipl. * *  03/06/86 -- ejf - cloned from dmc driver *							 * ----------------------------------------------------------------------- */#include "dmv.h"#if NDMV > 0 || defined(BINARY)/* * DMV11 device driver */#include "../data/if_dmv_data.c"int	dmvtimer;			/* timer started? */int	dmv_timeout = 25;		/* timeout value */int	dmvwatch();#define printd if(dmvdebug)printf#define printdmverr if(sc->sc_dmvcs.if_dstate == IFS_RUNNING || ! sc->sc_dmverrmsg++ || dmvdebug)printfint dmvdebug = 0;/* error reporting intervals */#define DMV_RPNBFS	50#define DMV_RPDSC	50#define	DMV_RPTMO	10#define DMV_RPDCK	10struct mbuf *dmv_get();extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern struct timeval time;extern int boot_cpu_mask;/* * DMV software status per interface. * * Each interface is referenced by a network interface structure, * sc_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  set of 7 UBA interface structures * for each, which * contain 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. *//* flags */#define DMV_ALLOC       01              /* unibus resources allocated */#define DMV_BMAPPED     02              /* base table mapped */#define	DMV_RESTART	04		/* software restart in progress */#define	DMV_ACTIVE	08		/* device active *//* * Driver information for auto-configuration stuff. */int     dmvprobe(), dmvattach(), dmvinit(), dmvioctl();int     dmvoutput(), dmvreset();u_short dmvstd[] = { 0 };struct  uba_driver dmvdriver =        { dmvprobe, 0, dmvattach, 0, dmvstd, "dmv", dmvinfo };/* * dmv software packet encapsulation.  This allows the dmv * link to be multiplexed among several protocols. * The first eight bytes of the dmv header are garbage; they * exist for historical reasons only since this structure is * the same one used for the DMC driver. * The next two bytes encapsulate packet type. */struct dmv_header {	char	dmv_buf[8];	/* space for uba on vax */	short	dmv_type;	/* encapsulate packet type */};/* queue manipulation macros */#define	QUEUE_AT_HEAD(qp, head, tail) \	(qp)->qp_next = (head); \	(head) = (qp); \	if((tail) == (struct dmv_command *) 0) \		(tail) = (head) #define QUEUE_AT_TAIL(qp, head, tail) \	if((tail)) \		(tail)->qp_next = (qp); \	else \		(head) = (qp); \	(qp)->qp_next = (struct dmv_command *) 0; \	(tail) = (qp)#define DEQUEUE(head, tail) \	(head) = (head)->qp_next;\	if((head) == (struct dmv_command *) 0)\		(tail) = (head)dmvprobe(reg)        caddr_t reg;{        register struct dmvdevice *addr = (struct dmvdevice *)reg;        register int i;#ifdef lint        dmvrint(0); dmvxint(0);#endif        addr->bsel1 = DMV_MCLR;        for (i = 100000; i && (addr->bsel1 & DMV_RUN) == 0; i--)                ;        if ((addr->bsel1 & DMV_RUN) == 0) {		printf("dmvprobe: can't start device\n" );                return (0);	}        if ( (addr->sel4 & DMV_LBSEL_MASK)  != 033 || (addr->sel6 & DMV_LBSEL_MASK) != 0305 ) {		printf("dmvprobe: device failed diagnostics, octal failure code = %o\n", (addr->sel6 & DMV_LBSEL_MASK) );                return (0);	}        addr->bsel0 = DMV_RQI|DMV_IEI;        DELAY(1000000);        addr->bsel1 = DMV_MCLR;        for (i = 100000; i && (addr->bsel1 & DMV_RUN) == 0; i--)                ;        return (sizeof(struct dmvdevice));}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */dmvattach(ui)        register struct uba_device *ui;{        register struct dmv_softc *sc = &dmv_softc[ui->ui_unit];	struct dmvdevice *addr = (struct dmvdevice *)dmvinfo[ui->ui_unit]->ui_addr;	int ncl;        sc->sc_if.if_unit = ui->ui_unit;        sc->sc_if.if_name = "dmv";        sc->sc_if.if_mtu = DMVMTU;        sc->sc_if.if_init = dmvinit;        sc->sc_if.if_output = dmvoutput;        sc->sc_if.if_ioctl = dmvioctl;        sc->sc_if.if_reset = dmvreset;        sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_DYNPROTO;	sc->sc_if.d_affinity = boot_cpu_mask;        sc->sc_ifuba.ifu_flags = UBA_CANTWAIT;	bzero(&sc->sc_dmvcs, sizeof(sc->sc_dmvcs));	bzero(&sc->sc_errctrs, sizeof(sc->sc_errctrs));	sc->sc_dmvcs.if_family = AF_UNSPEC;	sc->sc_dmvcs.if_next_family = AF_UNSPEC;	sc->sc_dmvcs.if_mode = ui->ui_flags;	if ((sc->sc_bufres.nxmt = ((NXMT_MASK & ui->ui_flags) >> NXMT_SHIFT)) > NXMT_MIN ) {		if (sc->sc_bufres.nxmt > NXMT_MAX) 			sc->sc_bufres.nxmt = NXMT_MAX;	} else		sc->sc_bufres.nxmt = NXMT_MIN;	sc->sc_bufres.nrcv = NRCV;	sc->sc_bufres.ntot = sc->sc_bufres.nrcv + sc->sc_bufres.nxmt;	sc->sc_bufres.ncmds = sc->sc_bufres.ntot + 4;	/*	 * Allocate page size buffers now. If we wait until the network	 * is setup they have already fragmented. By doing it here in	 * conjunction with always coping on uVAX-I processors we obtain	 * physically contigous buffers for dma transfers.	 */	ncl = clrnd((int)btoc(DMVMTU) + CLSIZE) / CLSIZE;	sc->sc_bufres.buffers = m_clalloc(sc->sc_bufres.ntot * ncl, MPG_SPACE);        if_attach(&sc->sc_if);	if (dmvtimer == 0) {		dmvtimer = 1;		timeout(dmvwatch, (caddr_t) 0, hz);	}}/* * Reset of interface after UNIBUS reset. * If interface is on specified UBA, reset it's state. */dmvreset(unit, uban)        int unit, uban;{        register struct uba_device *ui;        register struct dmv_softc *sc = &dmv_softc[unit];        if (unit >= nNDMV || (ui = dmvinfo[unit]) == 0 || ui->ui_alive == 0 ||            ui->ui_ubanum != uban)                return;        printf("resetting dmv%d", unit);        sc->sc_flag = 0;        dmvinit(unit);}/* * Initialization of interface; reinitialize UNIBUS usage. */dmvinit(unit)        int unit;{        register struct dmv_softc *sc = &dmv_softc[unit];        register struct uba_device *ui = dmvinfo[unit];        register struct dmvdevice *addr;        register struct ifnet *ifp = &sc->sc_if;        register struct ifrw *ifrw;	register struct ifxmt *ifxp;        register struct dmvbufs *rp;	register struct dmv_command *qp;	register struct ifaddr *ifa;	struct dmv_command cmd;        int base;	int s;	u_short dev_strt = 0;        addr = (struct dmvdevice *)ui->ui_addr;	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)		if ((ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family) || ifa->ifa_addr.sa_family == AF_OSI)			break;	if (ifa == (struct ifaddr *) 0)		return;        if((addr->bsel1&DMV_RUN) == 0) {                printf("dmvinit: DMV%d not running\n", unit);                ifp->if_flags &= ~(IFF_RUNNING|IFF_UP);                return;        }        /* map base table */        if ((sc->sc_flag & DMV_BMAPPED) == 0) {                sc->sc_ubinfo = uballoc(ui->ui_ubanum,                        (caddr_t)&dmv_base[unit],                        sizeof (struct dmv_base), 0);                sc->sc_flag |= DMV_BMAPPED;        }        /* initialize UNIBUS resources */        sc->sc_iused = sc->sc_oused = 0;        if ((sc->sc_flag & DMV_ALLOC) == 0) {                if (dmv_ubainit(&sc->sc_ifuba, ui->ui_ubanum,		    sizeof(struct dmv_header), (int)btoc(DMVMTU), &sc->sc_bufres) == 0) {                        printf("dmv%d: can't initialize\n", unit);                        ifp->if_flags &= ~IFF_UP;                        return;                }                sc->sc_flag |= DMV_ALLOC;        }        /* initialize buffer pool */        /* recieves */        ifrw= &sc->sc_ifuba.ifu_r[0];        for(rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[sc->sc_bufres.nrcv]; rp++) {                rp->ubinfo = ifrw->ifrw_info & 0x3ffff;		rp->cc = DMVMTU + sizeof (struct dmv_header);                rp->flags = DBUF_OURS|DBUF_RCV;                ifrw++;         }        /* transmits */        ifxp= &sc->sc_ifuba.ifu_w[0];        for(rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[sc->sc_bufres.nxmt]; rp++) {                rp->ubinfo = ifxp->x_ifrw.ifrw_info & 0x3ffff;                rp->cc = 0;                rp->flags = DBUF_OURS|DBUF_XMIT;		ifxp++;        }	/* set up command queues */	sc->sc_qfreeh = sc->sc_qfreet		 = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive =		(struct dmv_command *)0;	/* set up free command buffer list */	for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[sc->sc_bufres.ncmds]; qp++) {		QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);	}	/* if first time through, zero out counters */	if ( ! (ifp->if_flags & IFF_RUNNING) ) {		sc->sc_ztime = time.tv_sec;		bzero(&sc->sc_errctrs, sizeof(sc->sc_errctrs));	}	/* set up internal loopback if requested */	if ( ifp->if_flags & IFF_LOOPBACK ) {		int i;		addr->bsel1 |= (DMV_ILOOP | DMV_MCLR);		for ( i = 10000; i && ! (addr->bsel2 & DMV_RDYO); i-- ) ;		if ( ! (addr->bsel2 & DMV_RDYO) )			printf("dmvinit: can't place dmv%d into internal loopback\n", unit);		else			addr->bsel2 = DMV_MAINT_ILOOP;	}        /* enable operation done interrupts */        sc->sc_flag &= ~DMV_ACTIVE;        while ((addr->bsel0 & DMV_IEO) == 0)                addr->bsel0 |= DMV_IEO;        s = splimp();	/* Issue mode command, establish trib and start device */        switch ( (ifp->if_flags & IFF_LOOPBACK) ? DMV_MFLAGS_FDPLX_DMC : (sc->sc_dmvcs.if_mode & DMV_MFLAGS_MASK) )	{                /* use DDCMP point to point full duplex mode */		case DMV_MFLAGS_FDPLX_DMC:			dev_strt = DMV_CNTL_RQSTRT;			if ( (ifp->if_flags & IFF_RUNNING) && ! (sc->sc_flag & DMV_RESTART) && ! (ifp->if_flags & IFF_LOOPBACK) ) 				break;			printd("dmv%d: starting device in full duplex, dmc compatible mode\n", unit);			dmv_issue_mode(sc, DMV_MODE_FDPLX_DMC);			dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_ESTRIB );			break;		case DMV_MFLAGS_FDPLX:			dev_strt = DMV_CNTL_RQSTRT;			if ( (ifp->if_flags & IFF_RUNNING) && ! (sc->sc_flag & DMV_RESTART) ) 				break;			printf("dmv%d: starting device in full duplex mode\n", unit);			dmv_issue_mode(sc, DMV_MODE_FDPLX);			dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_ESTRIB );			break;                /* use DDCMP half duplex as primary station */		case DMV_MFLAGS_HDPLX_DMC:			dev_strt = DMV_CNTL_RQSTRT;			if ( (ifp->if_flags & IFF_RUNNING) && ! (sc->sc_flag & DMV_RESTART) ) 				break;			printd("dmv%d: starting device in half duplex, dmc compatible mode\n", unit);			dmv_issue_mode(sc, DMV_MODE_HDPLX_DMC);			dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_ESTRIB );			break;		case DMV_MFLAGS_HDPLX:			dev_strt = DMV_CNTL_RQSTRT;			if ( (ifp->if_flags & IFF_RUNNING) && ! (sc->sc_flag & DMV_RESTART) ) 				break;			printd("dmv%d: starting device in half duplex mode\n", unit);			dmv_issue_mode(sc, DMV_MODE_HDPLX);			dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_ESTRIB );			break;                /* use MAINTENANCE full duplex mode */		case DMV_MFLAGS_MAINT_FDPLX:			dev_strt = DMV_CNTL_RQMAINT;			if ( (ifp->if_flags & IFF_RUNNING) && ! (sc->sc_flag & DMV_RESTART) ) 				break;			printf("dmv%d: starting device in full duplex maintenance mode\n", unit);			dmv_issue_mode(sc, DMV_MODE_FDPLX_DMC);			dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_ESTRIB );			break;                /* use MAINTENANCE half duplex mode */		case DMV_MFLAGS_MAINT_HDPLX:		default:			dev_strt = DMV_CNTL_RQMAINT;			if ( (ifp->if_flags & IFF_RUNNING) && ! (sc->sc_flag & DMV_RESTART) ) 				break;			printd("dmv%d: starting device in half duplex maintenance mode\n", unit);			dmv_issue_mode(sc, DMV_MODE_HDPLX_DMC);			dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, DMV_CNTL_ESTRIB );			break;	}	/* override device default values for select and babble timers */	dmv_issue_ctl( sc, DMV_TRIB_POINT, DMV_TIMER_SEL, (DMV_CNTL_WRITE | DMV_KEY_SELECT) );	dmv_issue_ctl( sc, DMV_TRIB_POINT, DMV_TIMER_BAB, (DMV_CNTL_WRITE | DMV_KEY_BABBLE) );	/* tell device to start protocol */	sc->sc_dmvcs.if_dstate = IFS_STARTING;	dmv_issue_ctl( sc, DMV_TRIB_POINT, 0, dev_strt );        /* queue first NRCV buffers for DMV to fill */        for(rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[sc->sc_bufres.nrcv]; rp++) {		printd("dmv%d: assigning receive buffer\n", unit);                rp->flags |= DBUF_DMVS;                dmv_issue_buf(sc, DMV_CMD_RXBUF, 1, rp->ubinfo, rp->cc);                sc->sc_iused++;        }	/*	 * If in Maintenance, inform owner that device is up.	 */	if ( dev_strt == DMV_CNTL_RQMAINT) {		sc->sc_if.if_flags |= IFF_UP;		sc->sc_dmvcs.if_dstate = IFS_RUNNING;		if ( sc->sc_if.if_addr.sa_family != AF_UNSPEC ) {			struct protosw *pr;			if ((pr=iffamily_to_proto(sc->sc_if.if_addr.sa_family)) && pr->pr_ifstate ) 				(*pr->pr_ifstate)(&sc->sc_if, sc->sc_dmvcs.if_dstate, &sc->sc_dmvcs); 		}	}	splx(s);        ifp->if_flags |= IFF_RUNNING;	if ( sc->sc_dmvcs.if_mode == IFS_MOP )		ifp->if_flags |= IFF_MOP;	else		ifp->if_flags &= ~IFF_MOP;}/* * Start output on interface.  Get another datagram * to send from the interface queue and map it to * the interface before starting output. * * Must be called at pri 5. */dmvstart(dev)        dev_t dev;{        int unit = minor(dev);        register struct dmv_softc *sc = &dmv_softc[unit];        struct mbuf *m;        register struct dmvbufs *rp;	register int n;        /*         * Dequeue up to NXMT requests and map them to the UNIBUS.         * If no more requests, or no dmv buffers available, just return.         */	n = 0;        for(rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[sc->sc_bufres.nxmt]; rp++ ) {                /* find an available buffer */                if ((rp->flags & DBUF_DMVS) == 0) {                        IF_DEQUEUE(&sc->sc_if.if_snd, m);                        if (m == 0)                                return;                        /* mark it dmvs */                        rp->flags |= DBUF_DMVS;                        /*

⌨️ 快捷键说明

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