|
|
1.1 ! root 1: /* @(#)vs.c 7.1 (MIT) 6/5/86 */ ! 2: /**************************************************************************** ! 3: * * ! 4: * Copyright (c) 1983, 1984 by * ! 5: * DIGITAL EQUIPMENT CORPORATION, Maynard, Massachusetts. * ! 6: * All rights reserved. * ! 7: * * ! 8: * This software is furnished on an as-is basis and may be used and copied * ! 9: * only with inclusion of the above copyright notice. This software or any * ! 10: * other copies thereof may be provided or otherwise made available to * ! 11: * others only for non-commercial purposes. No title to or ownership of * ! 12: * the software is hereby transferred. * ! 13: * * ! 14: * The information in this software is subject to change without notice * ! 15: * and should not be construed as a commitment by DIGITAL EQUIPMENT * ! 16: * CORPORATION. * ! 17: * * ! 18: * DIGITAL assumes no responsibility for the use or reliability of its * ! 19: * software on equipment which is not supplied by DIGITAL. * ! 20: * * ! 21: * * ! 22: ****************************************************************************/ ! 23: ! 24: #include "vs.h" ! 25: #if NVS > 0 ! 26: ! 27: #include "../machine/pte.h" ! 28: ! 29: #include "param.h" ! 30: #include "dir.h" ! 31: #include "user.h" ! 32: #include "buf.h" ! 33: #include "systm.h" ! 34: #include "map.h" ! 35: #include "kernel.h" ! 36: #include "ioctl.h" ! 37: ! 38: #include "vsio.h" ! 39: ! 40: #include "proc.h" ! 41: #include "uio.h" ! 42: #include "vmmac.h" ! 43: #include "file.h" ! 44: ! 45: #include "ubareg.h" ! 46: #include "ubavar.h" ! 47: #include "vsreg.h" ! 48: ! 49: #include "../vax/mtpr.h" ! 50: ! 51: #define VSWAITPRI (PZERO+1) ! 52: #define VSMAXEVQ 64 /* must be power of 2 */ ! 53: #define EVROUND(x) ((x) & (VSMAXEVQ - 1)) ! 54: ! 55: ! 56: #define VSBUFFSIZE 3072 ! 57: struct vsBuffArea { ! 58: vsIoAddr vsioa; ! 59: char obuff[VSBUFFSIZE]; ! 60: vsEvent ibuff[VSMAXEVQ]; ! 61: }; ! 62: struct vsBuffArea vsBuff[NVS]; ! 63: ! 64: ! 65: int vsprobe(), vsattach(); ! 66: struct uba_device *vsdinfo[NVS]; ! 67: u_short vsstd[] = { 0 }; ! 68: struct uba_driver vsdriver = ! 69: { vsprobe, 0, vsattach, 0, vsstd, "vs", vsdinfo, 0, 0 }; ! 70: ! 71: #define VSUNIT(dev) (minor(dev)) ! 72: ! 73: struct vs_softc { ! 74: unsigned inited : 1; /* has this ever been inited? */ ! 75: unsigned open : 1; /* only one open, please */ ! 76: unsigned linkAvail : 1; /* link is up */ ! 77: short pgrp; /* process group for SIGHUP */ ! 78: int romVersion; /* rom version */ ! 79: struct vs_fparm offset; /* address base */ ! 80: struct vs_csr csr; /* saved csr0 */ ! 81: struct vs_intr irr; /* saved interrupt reason */ ! 82: struct vs_kbd krr; /* saved keyboard */ ! 83: struct vs_fparm pr; /* saved parameter regs */ ! 84: struct proc *rsel; /* process waiting for select */ ! 85: struct vs_fparm vs_nextgo; /* next packet to go */ ! 86: short vs_status; /* status from previous packet */ ! 87: vsStats stats; /* statistics */ ! 88: int vsBuff_ubinfo; /* ubinfo for vsBuff */ ! 89: }vs_softc[NVS]; ! 90: ! 91: #define TRUE 1 ! 92: #define FALSE 0 ! 93: ! 94: #define printI if (vsIntrPrintfs)printf ! 95: #define printD if (vsDebugPrintfs)printf ! 96: #define printM if (vsMlpPrintfs) vsMlpPrintfs--,printf ! 97: int vsIntrPrintfs = 0; ! 98: int vsDebugPrintfs = 0; ! 99: int vsMlpPrintfs = 0; ! 100: ! 101: /* ! 102: * Tell the system that it's out there, and set up the device's interrupt ! 103: * vector. Since we are supporting vs100s and vs125s, ! 104: * this is a bit kludgey. The vs100 works much ! 105: * as one expects, but the vs125 tries to set all the fiber link ! 106: * related bits when you hit VS_IE, ignoring the way the 100 works. ! 107: * Also, the vs100 will let you set the interrupt vector, but ! 108: * the vs125 ignores this and uses its hard-wired value. ! 109: * And there's no sure fire to tell which variant it is. ! 110: * Ugh. Ugh. Ugh. ! 111: */ ! 112: ! 113: vsprobe(reg) ! 114: caddr_t reg; ! 115: { ! 116: register int br, cvec; /* value-result */ ! 117: register struct vsdevice *vsaddr = (struct vsdevice *)reg; ! 118: ! 119: #ifdef lint ! 120: br = 0; cvec = br; br = cvec; ! 121: vsintr(0); ! 122: #endif ! 123: br = 0x15; ! 124: cvec = (uba_hd[numuba].uh_lastiv -= 4*8); ! 125: /* ! 126: * uh_lastiv is the last free interrupt vector in the ! 127: * unibus addapter header (uba_hd). ! 128: */ ! 129: ! 130: vsaddr->vs_csr0 = cvec >> 2; /* Save the vector for use on next device */ ! 131: vsaddr->vs_irr = 0; /* Csr will only be read if irr == 0 */ ! 132: vsaddr->vs_irr = 0; /* Clear interrupt reason register */ ! 133: vsaddr->vs_pr1 = 0; /* Clear function parameter */ ! 134: vsaddr->vs_pr2 = 0; /* Clear function parameter */ ! 135: vsaddr->vs_ivr = cvec; /* set up vector (no-op for vs125) */ ! 136: ! 137: DELAY(100000); ! 138: if (vsaddr->vs_csr0 & VS_LNK_AVL) ! 139: return(0); /* light won't go off! */ ! 140: vsaddr->vs_csr0 &= ~VS_LNK_TRNS; ! 141: vsaddr->vs_csr0 |= VS_IE; /* enable interrupts */ ! 142: DELAY(200000); ! 143: ! 144: return sizeof(struct vsdevice); ! 145: } ! 146: ! 147: vsattach(uip) ! 148: struct uba_device *uip; ! 149: { ! 150: register struct vs_softc *vsp; ! 151: register struct vsdevice *vsaddr; ! 152: ! 153: vsp = &vs_softc[VSUNIT(uip->ui_unit)]; ! 154: vsp->inited = FALSE; ! 155: vsp->open = FALSE; ! 156: vsBuff[VSUNIT(uip->ui_unit)].vsioa.mbox.bottom = 0; ! 157: vsp->linkAvail = FALSE; ! 158: vsp->romVersion = 0; ! 159: vsp->vs_nextgo.fparm_all = NULL; ! 160: ! 161: vsaddr = (struct vsdevice *) uip->ui_addr; ! 162: vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON); ! 163: } ! 164: ! 165: vsopen(dev, flag) ! 166: dev_t dev; ! 167: int flag; ! 168: { ! 169: register struct vs_softc *vsp; ! 170: register struct uba_device *uip; ! 171: register struct vsdevice *vsaddr; ! 172: int s; ! 173: int ret; ! 174: struct buf vsbuf; ! 175: struct vsBuffArea *vsb; ! 176: caddr_t vsBuffpage; ! 177: int vsBuffnpages; ! 178: ! 179: if (VSUNIT(dev) >= NVS || (vsp = &vs_softc[VSUNIT(dev)])->open || ! 180: (uip = vsdinfo[VSUNIT(dev)]) == 0 || uip->ui_alive == 0) ! 181: return (ENXIO); ! 182: ! 183: vsaddr = (struct vsdevice *) uip->ui_addr; ! 184: vsb = &vsBuff[VSUNIT(dev)]; ! 185: printM("vsopen csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n", ! 186: vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3, ! 187: vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7); ! 188: ! 189: /* ! 190: * Finally! We can now set up the device. ! 191: */ ! 192: ! 193: if (!vsp->inited && !(flag & FNDELAY)) { ! 194: vsInitDev(dev, TRUE); ! 195: if (ret = vsError(vsp)) ! 196: return(ret); ! 197: } ! 198: ! 199: vsp->open = TRUE; /* we're open */ ! 200: vsp->pgrp = u.u_procp->p_pgrp; ! 201: ! 202: /* reset statistics */ ! 203: bzero((caddr_t) &vsp->stats, sizeof(vsStats)); ! 204: ! 205: /* initialize user I/O addresses */ ! 206: vsb->vsioa.ioreg = (short *)vsaddr; ! 207: vsb->vsioa.status = 0; ! 208: vsb->vsioa.obuff = vsb->obuff; ! 209: vsb->vsioa.obufflen = VSBUFFSIZE; ! 210: vsb->vsioa.ibuff = vsb->ibuff; ! 211: vsb->vsioa.ihead = 0; ! 212: vsb->vsioa.itail = 0; ! 213: vsb->vsioa.iqsize = VSMAXEVQ; ! 214: /* map io regs into user address space (assume they don't cross a page) */ ! 215: maptouser(vsaddr); ! 216: /* map vsBuff into user address space */ ! 217: vsBuffpage = (caddr_t)((int)vsb & ~PGOFSET); ! 218: vsBuffnpages = (((int)vsb & PGOFSET) + ! 219: (NBPG-1) + sizeof(struct vsBuffArea)) >> PGSHIFT; ! 220: while (vsBuffnpages>0) { ! 221: maptouser(vsBuffpage); ! 222: vsBuffpage += NBPG; ! 223: vsBuffnpages--; ! 224: } ! 225: /* lock in the buffer */ ! 226: vsbuf.b_error = 0; ! 227: vsbuf.b_proc = u.u_procp; ! 228: vsbuf.b_un.b_addr = vsb->obuff; ! 229: vsbuf.b_flags = B_BUSY; ! 230: vsbuf.b_bcount = VSBUFFSIZE; ! 231: vsp->vsBuff_ubinfo = ubasetup(uip->ui_ubanum, &vsbuf, UBA_CANTWAIT); ! 232: ! 233: vsb->vsioa.reloc = (int) (vsp->offset.fparm_all ! 234: + (vsp->vsBuff_ubinfo & 0x3ffff)); ! 235: return(0); ! 236: } ! 237: ! 238: vsclose(dev) ! 239: dev_t dev; ! 240: { ! 241: register struct uba_device *uip = vsdinfo[VSUNIT(dev)]; ! 242: register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; ! 243: int s, i; ! 244: struct vsdevice *vsaddr; ! 245: struct vsBuffArea *vsb; ! 246: caddr_t vsBuffpage; ! 247: int vsBuffnpages; ! 248: ! 249: vsaddr = (struct vsdevice *) uip->ui_addr; ! 250: printM("vsclose csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n", ! 251: vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3, ! 252: vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7); ! 253: vsb = &vsBuff[VSUNIT(dev)]; ! 254: if (vsDebugPrintfs) { ! 255: printf("vs%d: %d errors, %d unsolicited interrupts", ! 256: VSUNIT(dev), vsp->stats.errors, vsp->stats.unsolIntr); ! 257: printf(", %d link errors", vsp->stats.linkErrors); ! 258: printf(", %d overruns", vsp->stats.overruns); ! 259: printf(", csr0 %x, csr1 %x", vsaddr->vs_csr0, vsaddr->vs_csr1); ! 260: printf("\n"); ! 261: } ! 262: ! 263: vsp->open = FALSE; ! 264: vsp->inited = FALSE; /* init on every open */ ! 265: vsp->vs_nextgo.fparm_all = NULL; ! 266: vsb->vsioa.mbox.bottom = 0; ! 267: /* release the buffer */ ! 268: if (vsp->vsBuff_ubinfo!=0) { ! 269: ubarelse(uip->ui_ubanum, &vsp->vsBuff_ubinfo); ! 270: } ! 271: ! 272: #ifdef notdef ! 273: /* unmap io regs into user address space (assume they don't cross a page) */ ! 274: unmaptouser(vsaddr); ! 275: /* unmap vsBuff into user address space */ ! 276: vsBuffpage = (caddr_t)((int)vsb & ~PGOFSET); ! 277: vsBuffnpages = (((int)vsb&PGOFSET) + ! 278: (NBPG-1)+ sizeof(struct vsBuffArea)) >> PGSHIFT; ! 279: while (vsBuffnpages>0) { ! 280: unmaptouser(vsBuffpage); ! 281: vsBuffpage += NBPG; ! 282: vsBuffnpages--; ! 283: } ! 284: #endif ! 285: } ! 286: ! 287: vsread(dev,uio) ! 288: dev_t dev; ! 289: struct uio *uio; ! 290: { ! 291: return(-1); ! 292: } ! 293: ! 294: vswrite(dev, uio) ! 295: dev_t dev; ! 296: struct uio *uio; ! 297: { ! 298: return(-1); ! 299: } ! 300: ! 301: /*ARGSUSED*/ ! 302: vsioctl(dev, cmd, addr, flag) ! 303: dev_t dev; ! 304: register caddr_t addr; ! 305: { ! 306: register struct uba_device *uip = vsdinfo[VSUNIT(dev)]; ! 307: register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; ! 308: register struct vsdevice *vsaddr = (struct vsdevice *) uip->ui_addr; ! 309: register struct vsBuffArea *vsb = &vsBuff[VSUNIT(dev)]; ! 310: struct vs_fparm vsAddr; ! 311: int s; ! 312: int func; ! 313: int ret; ! 314: ! 315: switch(cmd) { /* things that don't need the device */ ! 316: case VSIOWAITGO: ! 317: /* wait for user I/O operation to complete, then go */ ! 318: s = spl5(); ! 319: if ((ret = vsb->vsioa.status) == 0) { ! 320: vsp->vs_nextgo.fparm_all = ((struct vs_fparm *) addr)->fparm_all; ! 321: do { ! 322: sleep((caddr_t) vsp, VSWAITPRI); ! 323: } while (vsp->vs_nextgo.fparm_all); ! 324: ret = vsp->vs_status; ! 325: } else { ! 326: vsaddr->vs_pr1 = ((struct vs_fparm *)addr)->fparm_low; ! 327: vsaddr->vs_pr2 = ((struct vs_fparm *)addr)->fparm_high; ! 328: vsb->vsioa.status = 0; ! 329: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */ ! 330: vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO); ! 331: } ! 332: splx(s); ! 333: if (ret & VS_ERROR) ! 334: return ((ret & VS_REASON) + 128); ! 335: return(0); ! 336: ! 337: case VSIOUSERWAIT: ! 338: /* wait for user I/O operation to complete */ ! 339: s = spl5(); ! 340: while (vsb->vsioa.status == 0) { ! 341: sleep((caddr_t) vsp, VSWAITPRI); ! 342: } ! 343: splx(s); ! 344: return (0); ! 345: ! 346: case VSIOGETVER: /* get ROM version */ ! 347: if (!vsp->inited) ! 348: return(ENODEV); ! 349: *(int *) addr = vsp->romVersion; ! 350: return(0); ! 351: ! 352: case VSIOGETSTATS: /* get statistics block */ ! 353: *(vsStats *)addr = vsp->stats; ! 354: return(0); ! 355: ! 356: case VSIOGETIOA: /* get io addresses */ ! 357: if (vsp->vsBuff_ubinfo==0) { ! 358: return(EIO); ! 359: } ! 360: *((vsIoAddrAddr *)addr) = &vsb->vsioa; ! 361: return(0); ! 362: ! 363: default: /* a command that could block */ ! 364: if (ret = vsError(vsp)) ! 365: return(ret); ! 366: break; ! 367: } ! 368: ! 369: switch(cmd) { /* Commands that cause an interrupt */ ! 370: case VSIOINIT: /* initialize device */ ! 371: vsInitDev(dev, FALSE); ! 372: return(vsError(vsp)); ! 373: ! 374: case VSIOSTART: /* start microcode */ ! 375: vsAddr.fparm_all = *(caddr_t *)addr; ! 376: s = spl5(); ! 377: vsaddr->vs_pr1 = vsAddr.fparm_low; ! 378: vsaddr->vs_pr2 = vsAddr.fparm_high; ! 379: vsaddr->vs_irr = 0; ! 380: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */ ! 381: vsaddr->vs_csr0 |= (VS_IE | (VS_START << VS_FCSHIFT) | VS_GO); ! 382: sleep((caddr_t) vsp, VSWAITPRI); /* synchronous */ ! 383: splx(s); ! 384: return(vsError(vsp)); ! 385: ! 386: case VSIOABORT: /* abort a command chain */ ! 387: s = spl5(); ! 388: vsaddr->vs_irr = 0; ! 389: vsaddr->vs_csr0 &= ~VS_FCN; ! 390: vsaddr->vs_csr0 |= (VS_IE | (VS_ABORT << VS_FCSHIFT) | VS_GO); ! 391: sleep((caddr_t) vsp, VSWAITPRI); ! 392: splx(s); ! 393: return(vsError(vsp)); ! 394: ! 395: case VSIOPWRUP: /* power-up reset */ ! 396: s = spl5(); ! 397: vsaddr->vs_irr = 0; ! 398: vsaddr->vs_csr0 &= ~VS_FCN; ! 399: vsaddr->vs_csr0 |= (VS_IE | (VS_PWRUP << VS_FCSHIFT) | VS_GO); ! 400: sleep((caddr_t) vsp, VSWAITPRI); ! 401: splx(s); ! 402: return(vsError(vsp)); ! 403: ! 404: case VSIOBBACTL: /* enable/disable BBA */ ! 405: s = spl5(); ! 406: vsaddr->vs_irr = 0; ! 407: vsaddr->vs_csr0 &= ~VS_FCN; ! 408: func = *(int *)addr == VSIO_ON ? VS_ENABBA : VS_DISBBA; ! 409: vsaddr->vs_csr0 |= (VS_IE | (func << VS_FCSHIFT) | VS_GO); ! 410: sleep((caddr_t) vsp, VSWAITPRI); ! 411: splx(s); ! 412: return(vsError(vsp)); ! 413: ! 414: case VSIOFIBCTL: /* turn the fiber lamp on/off */ ! 415: s = spl5(); ! 416: if (*(int *)addr == VSIO_OFF) ! 417: vsaddr->vs_csr0 &= ~VS_XMIT_ON; ! 418: else ! 419: vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON); ! 420: sleep((caddr_t) vsp, VSWAITPRI); ! 421: splx(s); ! 422: return(vsError(vsp)); ! 423: ! 424: case VSIOFIBRETRY: /* set fiber retries */ ! 425: s = spl5(); ! 426: vsaddr->vs_irr = 0; ! 427: vsaddr->vs_csr0 &= ~VS_FCN; ! 428: func = *(int *)addr == VS_FIB_FINITE ? VS_FINITE : VS_INFINITE; ! 429: vsaddr->vs_csr0 |= (VS_IE | (func << VS_FCSHIFT) | VS_GO); ! 430: sleep((caddr_t) vsp, VSWAITPRI); ! 431: splx(s); ! 432: return(vsError(vsp)); ! 433: ! 434: case VSIOSYNC: /* get synchronized with device */ ! 435: break; ! 436: ! 437: default: ! 438: return(ENOTTY); ! 439: } ! 440: ! 441: return(0); ! 442: } ! 443: ! 444: vsintr(dev) ! 445: dev_t dev; ! 446: { ! 447: register struct vsdevice *vsaddr; ! 448: register struct vs_softc *vsp; ! 449: register vsEvent *vep; ! 450: struct uba_device *uip; ! 451: register struct vsBuffArea *vsb; ! 452: int i; ! 453: vsCursor cur; ! 454: ! 455: if (VSUNIT(dev) >= NVS || (uip = vsdinfo[VSUNIT(dev)]) == 0 ! 456: || uip->ui_alive == 0) { ! 457: printI("vs%d stray interrupt\n", VSUNIT(dev)); ! 458: return; ! 459: } ! 460: ! 461: vsaddr = (struct vsdevice *) uip->ui_addr; ! 462: vsp = &vs_softc[VSUNIT(dev)]; ! 463: vsb = &vsBuff[VSUNIT(dev)]; ! 464: #ifdef notdef ! 465: printM("vsintr csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n", ! 466: vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3, ! 467: vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7); ! 468: ! 469: printI("vs%dintr ", VSUNIT(dev)); ! 470: #endif ! 471: ! 472: /* ! 473: * get the information out of the soft registers ! 474: */ ! 475: ! 476: vsp->irr.intr_reg = vsaddr->vs_irr; ! 477: vsp->krr.kbd_reg = vsaddr->vs_krr; ! 478: vsp->pr.fparm_low = vsaddr->vs_pr1; ! 479: vsp->pr.fparm_high = vsaddr->vs_pr2; ! 480: cur.x = vsaddr->vs_cxr; ! 481: cur.y = vsaddr->vs_cyr; ! 482: vsp->csr.csr_reg = vsaddr->vs_csr0; ! 483: ! 484: if (vsp->irr.intr_reason) ! 485: vsaddr->vs_irr = 0; /* clear int reason, if any */ ! 486: ! 487: vsaddr->vs_csr0 &= ~VS_OWN; /* clear owner bit */ ! 488: ! 489: if (vsp->csr.csr_linkTran) { ! 490: vsaddr->vs_csr0 &= ~VS_LNK_TRNS; /* clear the bit */ ! 491: printI("link transition: "); ! 492: if (vsp->csr.csr_linkErr) ! 493: vsp->stats.linkErrors++; ! 494: ! 495: if (vsp->csr.csr_linkAvail == vsp->linkAvail) { /* flash */ ! 496: vsp->stats.flashes++; ! 497: printI("flash\n"); ! 498: } else if (!vsp->csr.csr_linkAvail && vsp->linkAvail) { /* on -> off */ ! 499: vsp->stats.douses++; ! 500: printI("douse\n"); ! 501: vsp->inited = FALSE; ! 502: if (vsp->open && vsp->pgrp) ! 503: gsignal(vsp->pgrp, SIGHUP); ! 504: wakeup((caddr_t) vsp); ! 505: } else { /* off -> on */ ! 506: vsp->stats.ignites++; ! 507: printI("ignite\n"); ! 508: wakeup((caddr_t) vsp); ! 509: } ! 510: ! 511: i = 200; ! 512: while ((vsaddr->vs_csr0 & VS_LNK_TRNS) && i) ! 513: i--; ! 514: if (i == 0) { /* bit stuck */ ! 515: printI("vs%d: Link Transition bit stuck\n", VSUNIT(dev)); ! 516: vsp->inited = FALSE; ! 517: if (vsp->open && vsp->pgrp) ! 518: gsignal(vsp->pgrp, SIGHUP); ! 519: vsaddr->vs_csr0 &= ~VS_XMIT_ON; ! 520: vsp->csr.csr_linkAvail = FALSE; ! 521: } ! 522: ! 523: vsp->linkAvail = vsp->csr.csr_linkAvail; ! 524: ! 525: return; ! 526: } ! 527: ! 528: if (vsp->irr.intr_error) { ! 529: printI("error 0x%x\n", vsp->irr.intr_reg&0xffff); ! 530: vsp->stats.errors++; ! 531: /* set status and wake up user if necessary */ ! 532: if (vsp->vs_nextgo.fparm_all) { ! 533: vsp->vs_status = vsp->irr.intr_reg; ! 534: vsaddr->vs_pr1 = vsp->vs_nextgo.fparm_low; ! 535: vsaddr->vs_pr2 = vsp->vs_nextgo.fparm_high; ! 536: vsp->vs_nextgo.fparm_all = NULL; ! 537: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */ ! 538: vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO); ! 539: } else ! 540: vsb->vsioa.status = vsp->irr.intr_reg; ! 541: wakeup((caddr_t) vsp); ! 542: return; ! 543: } ! 544: ! 545: #ifdef notdef ! 546: printI("reason is %b\n", vsp->irr.intr_reason, VSIRR_BITS); ! 547: #endif ! 548: switch(vsp->irr.intr_reason) { ! 549: case VS_INT_CD: /* command done */ ! 550: /* set status and start a new command if necessary */ ! 551: if (vsp->vs_nextgo.fparm_all) { ! 552: vsp->vs_status = vsp->irr.intr_reg; ! 553: vsaddr->vs_pr1 = vsp->vs_nextgo.fparm_low; ! 554: vsaddr->vs_pr2 = vsp->vs_nextgo.fparm_high; ! 555: vsp->vs_nextgo.fparm_all = NULL; ! 556: vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */ ! 557: vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO); ! 558: } else ! 559: vsb->vsioa.status = vsp->irr.intr_reg; ! 560: break; ! 561: ! 562: case VS_INT_MM: /* mouse moved */ ! 563: ! 564: vsb->vsioa.mouse = cur; ! 565: ! 566: if (!vsp->open) ! 567: return; /* ignore on closed device */ ! 568: ! 569: /* no event if inside box */ ! 570: if (cur.y < vsb->vsioa.mbox.bottom && ! 571: cur.y >= vsb->vsioa.mbox.top && ! 572: cur.x < vsb->vsioa.mbox.right && ! 573: cur.x >= vsb->vsioa.mbox.left) ! 574: return; ! 575: ! 576: /* trash box */ ! 577: vsb->vsioa.mbox.bottom = 0; ! 578: ! 579: if (EVROUND(vsb->vsioa.itail+1) == vsb->vsioa.ihead) ! 580: return; ! 581: i = EVROUND(vsb->vsioa.itail-1); ! 582: if ((vsb->vsioa.itail != vsb->vsioa.ihead) && ! 583: (i != vsb->vsioa.ihead)) { ! 584: vep = &vsb->ibuff[i]; ! 585: if (vep->vse_type == VSE_MMOTION) { ! 586: vep->vse_x = cur.x; ! 587: vep->vse_y = cur.y; ! 588: vep->vse_time = mfpr(TODR); ! 589: return; ! 590: } ! 591: } ! 592: /* put event into queue and do select */ ! 593: vep = &vsb->ibuff[vsb->vsioa.itail]; ! 594: vep->vse_type = VSE_MMOTION; ! 595: vep->vse_x = cur.x; ! 596: vep->vse_y = cur.y; ! 597: vep->vse_time = mfpr(TODR); ! 598: vsb->vsioa.itail = EVROUND(vsb->vsioa.itail+1); ! 599: if (vsp->rsel) { ! 600: selwakeup(vsp->rsel, 0); ! 601: vsp->rsel = 0; ! 602: } ! 603: break; ! 604: ! 605: case VS_INT_BE: /* button event */ ! 606: if (!vsp->open) ! 607: return; /* ignore on closed device */ ! 608: ! 609: if (vsp->krr.kbd_device == VSE_MOUSE) { ! 610: vsb->vsioa.mouse.x = cur.x; ! 611: vsb->vsioa.mouse.y = cur.y; ! 612: } ! 613: /* check for room in the queue */ ! 614: if ((i = EVROUND(vsb->vsioa.itail+1)) == vsb->vsioa.ihead) ! 615: return; ! 616: /* put event into queue and do select */ ! 617: vep = &vsb->ibuff[vsb->vsioa.itail]; ! 618: vep->vse_type = VSE_BUTTON; ! 619: vep->vse_key = vsp->krr.kbd_key; ! 620: vep->vse_direction = vsp->krr.kbd_transition; ! 621: vep->vse_device = vsp->krr.kbd_device; ! 622: vep->vse_time = mfpr(TODR); ! 623: vep->vse_x = vsb->vsioa.mouse.x; ! 624: vep->vse_y = vsb->vsioa.mouse.y; ! 625: vsb->vsioa.itail = i; ! 626: if (vsp->rsel) { ! 627: selwakeup(vsp->rsel, 0); ! 628: vsp->rsel = 0; ! 629: } ! 630: break; ! 631: ! 632: case VS_INT_TM: /* tablet moved */ ! 633: if (!vsp->open) ! 634: return; /* ignore on closed device */ ! 635: ! 636: if (EVROUND(vsb->vsioa.itail+1) == vsb->vsioa.ihead) ! 637: return; ! 638: i = EVROUND(vsb->vsioa.itail-1); ! 639: if ((vsb->vsioa.itail != vsb->vsioa.ihead) && ! 640: (i != vsb->vsioa.ihead)) { ! 641: vep = &vsb->ibuff[i]; ! 642: if (vep->vse_type == VSE_TMOTION) { ! 643: vep->vse_x = cur.x; ! 644: vep->vse_y = cur.y; ! 645: vep->vse_time = mfpr(TODR); ! 646: return; ! 647: } ! 648: } ! 649: /* put event into queue and do select */ ! 650: vep = &vsb->ibuff[vsb->vsioa.itail]; ! 651: vep->vse_type = VSE_TMOTION; ! 652: vep->vse_x = cur.x; ! 653: vep->vse_y = cur.y; ! 654: vep->vse_time = mfpr(TODR); ! 655: vsb->vsioa.itail = EVROUND(vsb->vsioa.itail+1); ! 656: if (vsp->rsel) { ! 657: selwakeup(vsp->rsel, 0); ! 658: vsp->rsel = 0; ! 659: } ! 660: break; ! 661: ! 662: case VS_INT_US: /* unsolicited */ ! 663: vsp->stats.unsolIntr++; ! 664: return; ! 665: ! 666: case VS_INT_ID: /* Initialization done */ ! 667: /* save offset from device */ ! 668: vsp->offset.fparm_all = vsp->pr.fparm_all; ! 669: /* save rom version */ ! 670: vsp->romVersion = cur.x; ! 671: vsp->inited = TRUE; ! 672: break; ! 673: ! 674: case VS_INT_SE: /* ucode started */ ! 675: break; ! 676: ! 677: case VS_INT_PWR: /* power up complete */ ! 678: /* save rom version */ ! 679: vsp->romVersion = cur.x; ! 680: vsp->inited = FALSE; ! 681: if (vsp->open && vsp->pgrp) ! 682: gsignal(vsp->pgrp, SIGHUP); ! 683: break; ! 684: ! 685: default: ! 686: printI("vs%d: unknown interrupt %b\n", VSUNIT(dev), ! 687: vsp->irr.intr_reason, VSIRR_BITS); ! 688: return; ! 689: } ! 690: wakeup((caddr_t) vsp); ! 691: } ! 692: ! 693: vsreset(uban) ! 694: int uban; ! 695: { ! 696: register int i; ! 697: register struct uba_device *uip; ! 698: register struct vs_softc *vsp = vs_softc; ! 699: ! 700: for (i = 0; i < NVS; i++, vsp++) { ! 701: if ((uip = vsdinfo[i]) == 0 || uip->ui_alive == 0 || ! 702: uip->ui_ubanum != uban || vsp->open == 0) ! 703: continue; ! 704: printf(" vs%d", i); ! 705: vsp->inited = FALSE; ! 706: if (vsp->open && vsp->pgrp) ! 707: gsignal(vsp->pgrp, SIGHUP); ! 708: } ! 709: } ! 710: ! 711: vsselect(dev, rw) ! 712: dev_t dev; ! 713: { ! 714: register struct vsBuffArea *vsb = &vsBuff[VSUNIT(dev)]; ! 715: int s = spl5(); ! 716: ! 717: switch(rw) { ! 718: case FREAD: ! 719: if (vsb->vsioa.ihead != vsb->vsioa.itail) { ! 720: splx(s); ! 721: return(1); ! 722: } ! 723: vs_softc[VSUNIT(dev)].rsel = u.u_procp; ! 724: splx(s); ! 725: return(0); ! 726: ! 727: case FWRITE: ! 728: splx(s); ! 729: return(EACCES); ! 730: } ! 731: } ! 732: ! 733: /* ! 734: * Initialize VS100 or SBO. ! 735: * Set XMITON. VS100 will respond with link available. SBO won't, so ! 736: * don't wait forever; assume everything is OK and warn user. ! 737: */ ! 738: ! 739: vsInitFiber(dev) ! 740: dev_t dev; ! 741: { ! 742: struct vsdevice *vsaddr = (struct vsdevice *) vsdinfo[VSUNIT(dev)]->ui_addr; ! 743: register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; ! 744: int s; ! 745: #ifdef VSSBO ! 746: int vsFiberNudge(); ! 747: ! 748: timeout(vsFiberNudge, (caddr_t) dev, 2*hz); ! 749: #endif ! 750: s = spl5(); ! 751: vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON); /* turn link on */ ! 752: sleep((caddr_t) vsp, VSWAITPRI); ! 753: splx(s); ! 754: #ifdef VSSBO ! 755: if (!vsp->linkAvail) { ! 756: uprintf("\007This had better be a vs125!\n"); ! 757: printf("vs%d must be a vs125\n", VSUNIT(dev)); ! 758: vsp->linkAvail = TRUE; ! 759: } ! 760: #endif ! 761: } ! 762: ! 763: #ifdef VSSBO ! 764: vsFiberNudge(dev) ! 765: dev_t dev; ! 766: { ! 767: struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; ! 768: ! 769: if (!vsp->linkAvail) ! 770: wakeup((caddr_t) vsp); ! 771: } ! 772: #endif VSSBO ! 773: ! 774: vsInitDev(dev, retry) ! 775: dev_t dev; ! 776: int retry; ! 777: { ! 778: register struct vsdevice *vsaddr; ! 779: register struct vs_softc *vsp; ! 780: int s; ! 781: int vsInitNudge(); ! 782: ! 783: vsaddr = (struct vsdevice *) vsdinfo[VSUNIT(dev)]->ui_addr; ! 784: vsp = &vs_softc[VSUNIT(dev)]; ! 785: ! 786: if (!vsp->linkAvail) ! 787: vsInitFiber(dev); ! 788: while (1) { ! 789: if (retry) ! 790: timeout(vsInitNudge, (caddr_t) dev, 10*hz); ! 791: s = spl5(); ! 792: vsaddr->vs_irr = 0; ! 793: vsaddr->vs_csr0 &= ~VS_FCN; ! 794: vsaddr->vs_csr0 |= (VS_IE | (VS_INIT << VS_FCSHIFT) | VS_GO); ! 795: sleep((caddr_t) vsp, VSWAITPRI); ! 796: splx(s); ! 797: if (vsp->inited) ! 798: break; ! 799: printM("vs%d: VS_INIT fails\n", VSUNIT(dev)); ! 800: uprintf("vsInitDev %x %x\n",vsaddr->vs_csr0, vsaddr->vs_csr1); ! 801: } ! 802: } ! 803: ! 804: vsInitNudge(dev) ! 805: dev_t dev; ! 806: { ! 807: struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; ! 808: ! 809: if (!vsp->inited) ! 810: wakeup((caddr_t) vsp); ! 811: } ! 812: ! 813: vsError(vsp) ! 814: register struct vs_softc *vsp; ! 815: { ! 816: if (vsp->irr.intr_error) { ! 817: register int ret = vsp->irr.intr_reg; ! 818: ! 819: printD("\treturning 0x%x\n", ret); ! 820: vsp->irr.intr_reg = 0; ! 821: return(ret+128); ! 822: } ! 823: return(0); ! 824: } ! 825: #endif ! 826:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.