1 /* @(#)vs.c 1.1 (MIT) 08/30/85 */ 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 827