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

📄 vs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* @(#)vs.c	7.8 (MIT) 12/16/90 */ /**************************************************************************** *									    * *  Copyright (c) 1983, 1984 by						    * *  DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts.		    * *  All rights reserved.						    * * 									    * *  This software is furnished on an as-is basis and may be used and copied * *  only with inclusion of the above copyright notice. This software or any * *  other copies thereof may be provided or otherwise made available to     * *  others only for non-commercial purposes.  No title to or 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 "vs.h"#if NVS > 0#include "../include/pte.h"#include "sys/param.h"#include "sys/user.h"#include "sys/buf.h"#include "sys/systm.h"#include "sys/map.h"#include "sys/kernel.h"#include "sys/ioctl.h"#include "vsio.h" #include "sys/proc.h"#include "sys/uio.h"#include "sys/vmmac.h"#include "sys/file.h"#include "ubareg.h"#include "ubavar.h"#include "vsreg.h"#include "../include/mtpr.h"#define	VSWAITPRI	(PZERO+1)#define	VSMAXEVQ	64	/* must be power of 2 */#define EVROUND(x)	((x) & (VSMAXEVQ - 1))#define VSBUFFSIZE	3072struct vsBuffArea {	vsIoAddr vsioa;	char	obuff[VSBUFFSIZE];	vsEvent ibuff[VSMAXEVQ];};struct vsBuffArea vsBuff[NVS];int vsprobe(), vsattach();struct uba_device *vsdinfo[NVS];u_short vsstd[] = { 0 };struct uba_driver vsdriver =	{ vsprobe, 0, vsattach, 0, vsstd, "vs", vsdinfo, 0, 0 };#define	VSUNIT(dev)	(minor(dev))struct vs_softc {	unsigned inited : 1;		/* has this ever been inited? */	unsigned open : 1;		/* only one open, please */	unsigned linkAvail : 1;		/* link is up */	short	pgrp;			/* process group for SIGHUP */	int	romVersion;		/* rom version */	struct vs_fparm	offset;		/* address base */	struct vs_csr	csr;		/* saved csr0 */	struct vs_intr	irr;		/* saved interrupt reason */	struct vs_kbd	krr;		/* saved keyboard */	struct vs_fparm	pr;		/* saved parameter regs */	struct proc *rsel;		/* process waiting for select */	struct vs_fparm vs_nextgo;	/* next packet to go */	short vs_status;		/* status from previous packet */	vsStats stats;			/* statistics */	int vsBuff_ubinfo;		/* ubinfo for vsBuff */}vs_softc[NVS];#define	TRUE	1#define	FALSE	0#define	printI	if (vsIntrPrintfs)printf#define	printD	if (vsDebugPrintfs)printf#define	printM	if (vsMlpPrintfs) vsMlpPrintfs--,printfint	vsIntrPrintfs = 0;int	vsDebugPrintfs = 0;int	vsMlpPrintfs = 0;/*  * Tell the system that it's out there, and set up the device's interrupt * vector. Since we are supporting vs100s and vs125s, * this is a bit kludgey. The vs100 works much * as one expects, but the vs125 tries to set all the fiber link * related bits when you hit VS_IE, ignoring the way the 100 works. * Also, the vs100 will let you set the interrupt vector, but * the vs125 ignores this and uses its hard-wired value. * And there's no sure fire to tell which variant it is. * Ugh. Ugh. Ugh. */vsprobe(reg)caddr_t reg;{	register int br, cvec;		/* value-result */	register struct vsdevice *vsaddr = (struct vsdevice *)reg;#ifdef	lint	br = 0; cvec = br; br = cvec;	vsintr(0);#endif	br = 0x15;	cvec = (uba_hd[numuba].uh_lastiv -= 4*8);	/* 	 * uh_lastiv is the last free interrupt vector in the	 * unibus addapter header (uba_hd).	 */	vsaddr->vs_csr0 = cvec >> 2;	/* Save the vector for use on next device */	vsaddr->vs_irr = 0;		/* Csr will only be read if irr == 0 */	vsaddr->vs_irr = 0;		/* Clear interrupt reason register */	vsaddr->vs_pr1  = 0;		/* Clear function parameter */	vsaddr->vs_pr2  = 0;		/* Clear function parameter */	vsaddr->vs_ivr = cvec;		/* set up vector (no-op for vs125) */	DELAY(100000);	if (vsaddr->vs_csr0 & VS_LNK_AVL)		return(0);	/* light won't go off! */	vsaddr->vs_csr0 &= ~VS_LNK_TRNS;	vsaddr->vs_csr0 |= VS_IE;	/* enable interrupts */	DELAY(200000);	return sizeof(struct vsdevice);}vsattach(uip)struct uba_device *uip;{	register struct vs_softc *vsp;	register struct vsdevice *vsaddr;	vsp = &vs_softc[VSUNIT(uip->ui_unit)];	vsp->inited  = FALSE;	vsp->open = FALSE;	vsBuff[VSUNIT(uip->ui_unit)].vsioa.mbox.bottom = 0;	vsp->linkAvail = FALSE;	vsp->romVersion = 0;	vsp->vs_nextgo.fparm_all = NULL;		vsaddr = (struct vsdevice *) uip->ui_addr;	vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON);}vsopen(dev, flag)dev_t dev;int flag;{	register struct vs_softc *vsp;	register struct uba_device *uip;	register struct vsdevice *vsaddr;	int s;	int ret;	struct buf vsbuf;	struct vsBuffArea *vsb;	caddr_t vsBuffpage;	int vsBuffnpages;	if (VSUNIT(dev) >= NVS || (vsp = &vs_softc[VSUNIT(dev)])->open ||	    (uip = vsdinfo[VSUNIT(dev)]) == 0 || uip->ui_alive == 0)		return (ENXIO);	vsaddr = (struct vsdevice *) uip->ui_addr;	vsb = &vsBuff[VSUNIT(dev)];	printM("vsopen csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n",		vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3,		vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7);	/* 	 * Finally! We can now set up the device.	 */	if (!vsp->inited && !(flag & FNDELAY)) {		ret = vsInitDev(dev, TRUE);		if (ret)			return (ret);		if (ret = vsError(vsp))			return(ret);	}	vsp->open = TRUE;		/* we're open */	vsp->pgrp = u.u_procp->p_pgrp;	/* reset statistics */	bzero((caddr_t) &vsp->stats, sizeof(vsStats));	/* initialize user I/O addresses */	vsb->vsioa.ioreg = (short *)vsaddr;	vsb->vsioa.status = 0;	vsb->vsioa.obuff = vsb->obuff;	vsb->vsioa.obufflen = VSBUFFSIZE;	vsb->vsioa.ibuff = vsb->ibuff;	vsb->vsioa.ihead = 0;	vsb->vsioa.itail = 0;	vsb->vsioa.iqsize = VSMAXEVQ;	/* map io regs into user address space (assume they don't cross a page) */	maptouser(vsaddr);	/* map vsBuff into user address space */	vsBuffpage = (caddr_t)((int)vsb & ~PGOFSET);	vsBuffnpages = (((int)vsb & PGOFSET) +			 (NBPG-1) + sizeof(struct vsBuffArea)) >> PGSHIFT;	while (vsBuffnpages>0) {	    maptouser(vsBuffpage);	    vsBuffpage += NBPG;	    vsBuffnpages--;	}	/* lock in the buffer */	vsbuf.b_error = 0;	vsbuf.b_proc = u.u_procp;	vsbuf.b_un.b_addr = vsb->obuff;	vsbuf.b_flags = B_BUSY;	vsbuf.b_bcount = VSBUFFSIZE;	vsp->vsBuff_ubinfo = ubasetup(uip->ui_ubanum, &vsbuf, UBA_CANTWAIT);	vsb->vsioa.reloc = (int) (vsp->offset.fparm_all			+ UBAI_ADDR(vsp->vsBuff_ubinfo));	return(0);}vsclose(dev)dev_t dev;{	register struct uba_device *uip = vsdinfo[VSUNIT(dev)];	register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)];	int s, i;	struct vsdevice *vsaddr;	struct vsBuffArea *vsb;	caddr_t vsBuffpage;	int vsBuffnpages;		vsaddr = (struct vsdevice *) uip->ui_addr;	printM("vsclose csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n",		vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3,		vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7);		vsb = &vsBuff[VSUNIT(dev)];	if (vsDebugPrintfs) {		printf("vs%d: %d errors, %d unsolicited interrupts",			VSUNIT(dev), vsp->stats.errors, vsp->stats.unsolIntr);		printf(", %d link errors", vsp->stats.linkErrors);		printf(", %d overruns", vsp->stats.overruns);		printf(", csr0 %x, csr1 %x", vsaddr->vs_csr0, vsaddr->vs_csr1);		printf("\n");	}	vsp->open = FALSE;	vsp->inited = FALSE;		/* init on every open */	vsp->vs_nextgo.fparm_all = NULL;	vsb->vsioa.mbox.bottom = 0;	/* release the buffer */	if (vsp->vsBuff_ubinfo!=0) {		ubarelse(uip->ui_ubanum, &vsp->vsBuff_ubinfo);	}#ifdef notdef	/* unmap io regs into user address space (assume they don't cross a page) */	unmaptouser(vsaddr);	/* unmap vsBuff into user address space */	vsBuffpage = (caddr_t)((int)vsb & ~PGOFSET);	vsBuffnpages = (((int)vsb&PGOFSET) +			 (NBPG-1)+ sizeof(struct vsBuffArea)) >> PGSHIFT;	while (vsBuffnpages>0) {	    unmaptouser(vsBuffpage);	    vsBuffpage += NBPG;	    vsBuffnpages--;	}#endif	return (0);}vsread(dev,uio)dev_t   dev;struct uio      *uio;{        return(-1);}vswrite(dev, uio)dev_t   dev;struct uio      *uio;{        return(-1);}/*ARGSUSED*/vsioctl(dev, cmd, addr, flag)dev_t dev;register caddr_t addr;{	register struct uba_device *uip = vsdinfo[VSUNIT(dev)];	register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)];	register struct vsdevice *vsaddr = (struct vsdevice *) uip->ui_addr;	register struct vsBuffArea *vsb = &vsBuff[VSUNIT(dev)];	struct vs_fparm vsAddr;	int s, error = 0;	int func;	int ret;	switch(cmd) {			/* things that don't need the device */	case VSIOWAITGO:		/* wait for user I/O operation to complete, then go */		s = spl5();		if ((ret = vsb->vsioa.status) == 0) {			vsp->vs_nextgo.fparm_all = ((struct vs_fparm *) addr)->fparm_all;			do {				error = tsleep((caddr_t)vsp, VSWAITPRI | PCATCH,				    devwait, 0);			} while (vsp->vs_nextgo.fparm_all && error == 0);			ret = vsp->vs_status;		} else {			vsaddr->vs_pr1 = ((struct vs_fparm *)addr)->fparm_low;			vsaddr->vs_pr2 = ((struct vs_fparm *)addr)->fparm_high;			vsb->vsioa.status = 0;			vsaddr->vs_csr0 &= ~VS_FCN;	/* clear bits */			vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO);		}		splx(s);		if (error)			return (error);		if (ret & VS_ERROR)			return ((ret & VS_REASON) + 128);		return(0);	case VSIOUSERWAIT:		/* wait for user I/O operation to complete */		s = spl5();		while (vsb->vsioa.status == 0) {			error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH,			    devio, 0);		}		splx(s);		return (error);	case VSIOGETVER:		/* get ROM version */		if (!vsp->inited)			return(ENODEV);		*(int *) addr = vsp->romVersion;		return(0);	case VSIOGETSTATS:		/* get statistics block */		*(vsStats *)addr = vsp->stats;		return(0);	case VSIOGETIOA:		/* get io addresses */		if (vsp->vsBuff_ubinfo==0) {		    return(EIO);		}		*((vsIoAddrAddr *)addr) = &vsb->vsioa;		return(0);	default:			/* a command that could block */		if (ret = vsError(vsp))			return(ret);		break;	}	switch(cmd) {			/* Commands that cause an interrupt */	case VSIOINIT:			/* initialize device */		vsInitDev(dev, FALSE);		return(vsError(vsp));	case VSIOSTART:			/* start microcode */		vsAddr.fparm_all = *(caddr_t *)addr;		s = spl5();		vsaddr->vs_pr1 = vsAddr.fparm_low;		vsaddr->vs_pr2 = vsAddr.fparm_high;		vsaddr->vs_irr = 0;		vsaddr->vs_csr0 &= ~VS_FCN;	/* clear bits */		vsaddr->vs_csr0 |= (VS_IE | (VS_START << VS_FCSHIFT) | VS_GO);		/* synchronous */		error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);		splx(s);		if (error)			return (error);		return(vsError(vsp));	case VSIOABORT:			/* abort a command chain */		s = spl5();		vsaddr->vs_irr = 0;		vsaddr->vs_csr0 &= ~VS_FCN;		vsaddr->vs_csr0 |= (VS_IE | (VS_ABORT << VS_FCSHIFT) | VS_GO);		error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);		splx(s);		if (error)			return (error);		return(vsError(vsp));	case VSIOPWRUP:			/* power-up reset */		s = spl5();		vsaddr->vs_irr = 0;		vsaddr->vs_csr0 &= ~VS_FCN;		vsaddr->vs_csr0 |= (VS_IE | (VS_PWRUP << VS_FCSHIFT) | VS_GO);		error = tsleep((caddr_t) vsp, VSWAITPRI | PCATCH, devwait, 0);		splx(s);		if (error)			return (error);		return(vsError(vsp));

⌨️ 快捷键说明

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