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