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