1 /* @(#)vs.c 7.6 (MIT) 04/05/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 case FWRITE: 747 splx(s); 748 return(EACCES); 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 829