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

📄 if_dmv.c

📁 open bsd vax module -if function
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988 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_dmv.c	7.12 (Berkeley) 12/16/90 *//* * DMV-11 Driver * * Qbus Sync DDCMP interface - DMV operated in full duplex, point to point mode * * Written by Bob Kridle of Mt Xinu * starting from if_dmc.c version 6.12 dated 4/23/86 */#include "dmv.h"#if NDMV > 0#include "sys/param.h"#include "sys/systm.h"#include "sys/mbuf.h"#include "sys/buf.h"#include "sys/ioctl.h"		/* must precede tty.h */#include "sys/tty.h"#include "sys/protosw.h"#include "sys/socket.h"#include "sys/syslog.h"#include "sys/vmmac.h"#include "sys/errno.h"#include "sys/time.h"#include "sys/kernel.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"#endif#include "../include/cpu.h"#include "../include/mtpr.h"#include "../include/pte.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"#include "if_uba.h"#include "if_dmv.h"int	dmv_timeout = 8;		/* timeout value *//* * Driver information for auto-configuration stuff. */int	dmvprobe(), dmvattach(), dmvinit(), dmvioctl();int	dmvoutput(), dmvreset(), dmvtimeout();struct	uba_device *dmvinfo[NDMV];u_short	dmvstd[] = { 0 };struct	uba_driver dmvdriver =	{ dmvprobe, 0, dmvattach, 0, dmvstd, "dmv", dmvinfo };/* * Don't really know how many buffers/commands can be queued to a DMV-11. * Manual doesn't say... Perhaps we can look at a DEC driver some day. * These numbers ame from DMC/DMR driver. */#define NRCV 5#define NXMT 3 #define NCMDS	(NRCV+NXMT+4)	/* size of command queue */#ifdef DEBUG#define printd(f)   if (sc->sc_if.if_flags & IFF_DEBUG) \	printf("DMVDEBUG: dmv%d: ", unit), printf(f)#else#define	printd(f)	/* nil */#endif/* error reporting intervals */#define	DMV_RPRTE	 1#define	DMV_RPTTE        1#define	DMV_RPSTE	 1#define DMV_RPNXM        1#define DMV_RPMODD       1#define DMV_RPQOVF	 1#define DMV_RPCXRL	 1/* number of errors to accept before trying a reset */#define DMV_RPUNKNOWN	 10struct  dmv_command {	u_char	qp_mask;	/* Which registers to set up */#define	QP_TRIB		0x01#define	QP_SEL4		0x02#define	QP_SEL6		0x04#define	QP_SEL10	0x08	u_char	qp_cmd;	u_char	qp_tributary;	u_short	qp_sel4;	u_short	qp_sel6;	u_short	qp_sel10;	struct	dmv_command *qp_next;	/* next command on queue */};#define	qp_lowbufaddr	qp_struct dmvbufs {	int	ubinfo;		/* from uballoc */	short	cc;		/* buffer size */	short	flags;		/* access control */};#define	DBUF_OURS	0	/* buffer is available */#define	DBUF_DMVS	1	/* buffer claimed by somebody */#define	DBUF_XMIT	4	/* transmit buffer */#define	DBUF_RCV	8	/* receive buffer *//* * 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. */struct dmv_softc {	struct	ifnet sc_if;		/* network-visible interface */	short	sc_oused;		/* output buffers currently in use */	short	sc_iused;		/* input buffers given to DMV */	short	sc_flag;		/* flags */	short	sc_ipl;			/* interrupt priority */	int	sc_ubinfo;		/* UBA mapping info for base table */	int	sc_errors[8];		/* error counters */#define	sc_rte	sc_errors[0]		/* receive threshhold error */#define	sc_xte	sc_errors[1]		/* xmit threshhold error */#define	sc_ste	sc_errors[2]		/* select threshhold error */#define	sc_nxm	sc_errors[3]		/* non-existant memory */#define	sc_modd	sc_errors[4]		/* modem disconnect */#define	sc_qovf	sc_errors[5]		/* command/response queue overflow */#define	sc_cxrl	sc_errors[6]		/* carrier loss */#define sc_unknown sc_errors[7]		/* other errors - look in DMV manual */	struct	dmvbufs sc_rbufs[NRCV];	/* receive buffer info */	struct	dmvbufs sc_xbufs[NXMT];	/* transmit buffer info */	struct	ifubinfo sc_ifuba;	/* UNIBUS resources */	struct	ifrw sc_ifr[NRCV];	/* UNIBUS receive buffer maps */	struct	ifxmt sc_ifw[NXMT];	/* UNIBUS receive buffer maps */	/* command queue stuff */	struct	dmv_command sc_cmdbuf[NCMDS];	struct	dmv_command *sc_qhead;	/* head of command queue */	struct	dmv_command *sc_qtail;	/* tail of command queue */	struct	dmv_command *sc_qactive;	/* command in progress */	struct	dmv_command *sc_qfreeh;	/* head of list of free cmd buffers */	struct	dmv_command *sc_qfreet;	/* tail of list of free cmd buffers */	/* end command queue stuff */} dmv_softc[NDMV];/* flags */#define DMV_RESTART	0x01		/* software restart in progress */#define DMV_ONLINE	0x02		/* device managed to transmit */#define DMV_RUNNING	0x04		/* device initialized *//* 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, ui)	caddr_t reg;	struct uba_device *ui;{	register int br, cvec;	register struct dmvdevice *addr = (struct dmvdevice *)reg;	register int i;#ifdef lint	br = 0; cvec = br; br = cvec;	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->bsel4 != 033) || (addr->bsel6 != 0305))	{		printf("dmvprobe: device init failed, bsel4=%o, bsel6=%o\n",			addr->bsel4, addr->bsel6);		return (0);	}	(void) spl6();	addr->bsel0 = DMV_RQI|DMV_IEI|DMV_IEO;	DELAY(1000000);	dmv_softc[ui->ui_unit].sc_ipl = br = qbgetpri();	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];	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_watchdog = dmvtimeout;	sc->sc_if.if_flags = IFF_POINTOPOINT;	sc->sc_ifuba.iff_flags = UBA_CANTWAIT;	if_attach(&sc->sc_if);}/* * Reset of interface after UNIBUS reset. * If interface is on specified UBA, reset its state. */dmvreset(unit, uban)	int unit, uban;{	register struct uba_device *ui;	register struct dmv_softc *sc = &dmv_softc[unit];	if (unit >= NDMV || (ui = dmvinfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_ubanum != uban)		return;	printf(" dmv%d", unit);	sc->sc_flag = 0;	sc->sc_if.if_flags &= ~IFF_RUNNING;	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;	struct ifaddr *ifa;	int base;	int s;	addr = (struct dmvdevice *)ui->ui_addr;	/*	 * Check to see that an address has been set	 * (both local and destination for an address family).	 */	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)		if (ifa->ifa_addr->sa_family &&		    ifa->ifa_addr->sa_family != AF_LINK &&		    ifa->ifa_dstaddr && ifa->ifa_dstaddr->sa_family)			break;	if (ifa == (struct ifaddr *) 0)		return;	if ((addr->bsel1&DMV_RUN) == 0) {		log(LOG_CRIT, "dmvinit: dmv%d not running\n", unit);		ifp->if_flags &= ~IFF_UP;		return;	}	printd(("dmvinit\n"));	/* initialize UNIBUS resources */	sc->sc_iused = sc->sc_oused = 0;	if ((ifp->if_flags & IFF_RUNNING) == 0) {		if (if_ubaminit(			&sc->sc_ifuba,			ui->ui_ubanum,		    	sizeof(struct dmv_header),			(int)btoc(DMVMTU),			sc->sc_ifr,			NRCV,			sc->sc_ifw,			NXMT	      	) == 0) {			log(LOG_CRIT, "dmvinit: dmv%d can't allocate uba resources\n", unit);			ifp->if_flags &= ~IFF_UP;			return;		}		ifp->if_flags |= IFF_RUNNING;	}	/*	 * Limit packets enqueued until we see if we're on the air.	 */	ifp->if_snd.ifq_maxlen = 3;	/* initialize buffer pool */	/* receives */	ifrw = &sc->sc_ifr[0];	for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {		rp->ubinfo = UBAI_ADDR(ifrw->ifrw_info);		rp->cc = DMVMTU + sizeof (struct dmv_header);		rp->flags = DBUF_OURS|DBUF_RCV;		ifrw++; 	}	/* transmits */	ifxp = &sc->sc_ifw[0];	for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {		rp->ubinfo = UBAI_ADDR(ifxp->ifw_info);		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[NCMDS]; qp++) {		QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);	}	if(sc->sc_flag & DMV_RUNNING)		dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_REQHS,0);	else		dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_ESTTRIB,0);	dmvload( sc, DMV_CNTRLI, (QP_TRIB|QP_SEL6), 1, 0, DMV_REQSUS,0);	sc->sc_flag |= (DMV_RESTART|DMV_RUNNING);	sc->sc_flag &= ~DMV_ONLINE;	addr->bsel0 |= DMV_IEO;}/* * 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 spl 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.	 */	printd(("dmvstart\n"));	n = 0;	for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[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);			/*			 * Have request mapped to UNIBUS for transmission			 * and start the output.			 */			rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m);			if (++sc->sc_oused == 1)				sc->sc_if.if_timer = dmv_timeout;			dmvload(				sc,				DMV_BACCX,				QP_TRIB|QP_SEL4|QP_SEL6|QP_SEL10,				1,				rp->ubinfo,				(rp->ubinfo>>16)&0x3f,				rp->cc			);		}		n++;	}}/* * Utility routine to load the DMV device registers. */dmvload(sc, cmd, mask, tributary, sel4, sel6, sel10)	register struct dmv_softc *sc;	u_char cmd, tributary, mask;	u_short sel4, sel6, sel10;{	register struct dmvdevice *addr;	register int unit, sps;	register struct dmv_command *qp;	unit = sc - dmv_softc;	printd(("dmvload: cmd=%x mask=%x trib=%x sel4=%x sel6=%x sel10=%x\n",		(unsigned) cmd,		(unsigned) mask,		(unsigned) tributary,		(unsigned) sel4,		(unsigned) sel6,		(unsigned) sel10	));	addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr;	sps = spl5();	/* grab a command buffer from the free list */	if ((qp = sc->sc_qfreeh) == (struct dmv_command *)0)		panic("dmv command queue overflow");	DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet);	/* fill in requested info */	qp->qp_cmd = cmd;	qp->qp_mask = mask;	qp->qp_tributary = tributary;	qp->qp_sel4 = sel4;	qp->qp_sel6 = sel6;	qp->qp_sel10 = sel10;		if (sc->sc_qactive) {	/* command in progress */		if (cmd == DMV_BACCR) {  /* supply read buffers first */			QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail);		} else {			QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail);		}	} else {	/* command port free */		sc->sc_qactive = qp;		addr->bsel0 = (DMV_RQI|DMV_IEI|DMV_IEO);	}	splx(sps);}/* * DMV interface input interrupt. * Ready to accept another command, * pull one off the command queue. */dmvrint(unit)	int unit;{	register struct dmv_softc *sc;	register struct dmvdevice *addr;	register struct dmv_command *qp;	register int n;	addr = (struct dmvdevice *)dmvinfo[unit]->ui_addr;	sc = &dmv_softc[unit];	splx(sc->sc_ipl);	printd(("dmvrint\n"));	if ((qp = sc->sc_qactive) == (struct dmv_command *) 0) {		log(LOG_WARNING, "dmvrint: dmv%d no command\n", unit);		return;	}	while (addr->bsel2&DMV_RDI) {		if(qp->qp_mask&QP_SEL4)			addr->wsel4 = qp->qp_sel4;		if(qp->qp_mask&QP_SEL6)			addr->wsel6 = qp->qp_sel6;		if(qp->qp_mask&QP_SEL10) {			addr->wsel10 = qp->qp_sel10;			qp->qp_cmd |= DMV_22BIT;		}		if(qp->qp_mask&QP_TRIB)			addr->wsel2 = qp->qp_cmd|(qp->qp_tributary << 8);		else			addr->bsel2 = qp->qp_cmd;		QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);		if ((sc->sc_qactive = sc->sc_qhead) == (struct dmv_command *)0)			break;		qp = sc->sc_qactive;		DEQUEUE(sc->sc_qhead, sc->sc_qtail);		if (addr->bsel2&DMV_RDO)				break;	}	if (!sc->sc_qactive) {		if(addr->bsel2&DMV_RDI) {			/* clear RQI prior to last command per DMV manual */			addr->bsel0 &= ~DMV_RQI;			addr->wsel6 = DMV_NOP;			addr->bsel2 = DMV_CNTRLI;

⌨️ 快捷键说明

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