📄 vs.c
字号:
/* @(#)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 + -