1 /* @(#)vs.c 7.5 (MIT) 02/17/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 #include "tsleep.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 + UBAI_ADDR(vsp->vsBuff_ubinfo)); 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 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_WAIT, 0); 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 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_USRWAIT, 0); 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 /* synchronous */ 383 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_START, 0); 384 splx(s); 385 return(vsError(vsp)); 386 387 case VSIOABORT: /* abort a command chain */ 388 s = spl5(); 389 vsaddr->vs_irr = 0; 390 vsaddr->vs_csr0 &= ~VS_FCN; 391 vsaddr->vs_csr0 |= (VS_IE | (VS_ABORT << VS_FCSHIFT) | VS_GO); 392 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_ABORT, 0); 393 splx(s); 394 return(vsError(vsp)); 395 396 case VSIOPWRUP: /* power-up reset */ 397 s = spl5(); 398 vsaddr->vs_irr = 0; 399 vsaddr->vs_csr0 &= ~VS_FCN; 400 vsaddr->vs_csr0 |= (VS_IE | (VS_PWRUP << VS_FCSHIFT) | VS_GO); 401 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_PWRUP, 0); 402 splx(s); 403 return(vsError(vsp)); 404 405 case VSIOBBACTL: /* enable/disable BBA */ 406 s = spl5(); 407 vsaddr->vs_irr = 0; 408 vsaddr->vs_csr0 &= ~VS_FCN; 409 func = *(int *)addr == VSIO_ON ? VS_ENABBA : VS_DISBBA; 410 vsaddr->vs_csr0 |= (VS_IE | (func << VS_FCSHIFT) | VS_GO); 411 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_IOBCTL, 0); 412 splx(s); 413 return(vsError(vsp)); 414 415 case VSIOFIBCTL: /* turn the fiber lamp on/off */ 416 s = spl5(); 417 if (*(int *)addr == VSIO_OFF) 418 vsaddr->vs_csr0 &= ~VS_XMIT_ON; 419 else 420 vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON); 421 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_FIB, 0); 422 splx(s); 423 return(vsError(vsp)); 424 425 case VSIOFIBRETRY: /* set fiber retries */ 426 s = spl5(); 427 vsaddr->vs_irr = 0; 428 vsaddr->vs_csr0 &= ~VS_FCN; 429 func = *(int *)addr == VS_FIB_FINITE ? VS_FINITE : VS_INFINITE; 430 vsaddr->vs_csr0 |= (VS_IE | (func << VS_FCSHIFT) | VS_GO); 431 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_FIBRET, 0); 432 splx(s); 433 return(vsError(vsp)); 434 435 case VSIOSYNC: /* get synchronized with device */ 436 break; 437 438 default: 439 return(ENOTTY); 440 } 441 442 return(0); 443 } 444 445 vsintr(dev) 446 dev_t dev; 447 { 448 register struct vsdevice *vsaddr; 449 register struct vs_softc *vsp; 450 register vsEvent *vep; 451 struct uba_device *uip; 452 register struct vsBuffArea *vsb; 453 int i; 454 vsCursor cur; 455 456 if (VSUNIT(dev) >= NVS || (uip = vsdinfo[VSUNIT(dev)]) == 0 457 || uip->ui_alive == 0) { 458 printI("vs%d stray interrupt\n", VSUNIT(dev)); 459 return; 460 } 461 462 vsaddr = (struct vsdevice *) uip->ui_addr; 463 vsp = &vs_softc[VSUNIT(dev)]; 464 vsb = &vsBuff[VSUNIT(dev)]; 465 #ifdef notdef 466 printM("vsintr csr0=%x, csr1=%x, csr2=%x, csr3=%x, csr4=%x, csr5=%x, csr6=%x, csr7=%x\n", 467 vsaddr->vs_csr0, vsaddr->vs_csr1, vsaddr->vs_csr2, vsaddr->vs_csr3, 468 vsaddr->vs_csr4, vsaddr->vs_csr5, vsaddr->vs_csr6, vsaddr->vs_csr7); 469 470 printI("vs%dintr ", VSUNIT(dev)); 471 #endif 472 473 /* 474 * get the information out of the soft registers 475 */ 476 477 vsp->irr.intr_reg = vsaddr->vs_irr; 478 vsp->krr.kbd_reg = vsaddr->vs_krr; 479 vsp->pr.fparm_low = vsaddr->vs_pr1; 480 vsp->pr.fparm_high = vsaddr->vs_pr2; 481 cur.x = vsaddr->vs_cxr; 482 cur.y = vsaddr->vs_cyr; 483 vsp->csr.csr_reg = vsaddr->vs_csr0; 484 485 if (vsp->irr.intr_reason) 486 vsaddr->vs_irr = 0; /* clear int reason, if any */ 487 488 vsaddr->vs_csr0 &= ~VS_OWN; /* clear owner bit */ 489 490 if (vsp->csr.csr_linkTran) { 491 vsaddr->vs_csr0 &= ~VS_LNK_TRNS; /* clear the bit */ 492 printI("link transition: "); 493 if (vsp->csr.csr_linkErr) 494 vsp->stats.linkErrors++; 495 496 if (vsp->csr.csr_linkAvail == vsp->linkAvail) { /* flash */ 497 vsp->stats.flashes++; 498 printI("flash\n"); 499 } else if (!vsp->csr.csr_linkAvail && vsp->linkAvail) { /* on -> off */ 500 vsp->stats.douses++; 501 printI("douse\n"); 502 vsp->inited = FALSE; 503 if (vsp->open && vsp->pgrp) 504 gsignal(vsp->pgrp, SIGHUP); 505 wakeup((caddr_t) vsp); 506 } else { /* off -> on */ 507 vsp->stats.ignites++; 508 printI("ignite\n"); 509 wakeup((caddr_t) vsp); 510 } 511 512 i = 200; 513 while ((vsaddr->vs_csr0 & VS_LNK_TRNS) && i) 514 i--; 515 if (i == 0) { /* bit stuck */ 516 printI("vs%d: Link Transition bit stuck\n", VSUNIT(dev)); 517 vsp->inited = FALSE; 518 if (vsp->open && vsp->pgrp) 519 gsignal(vsp->pgrp, SIGHUP); 520 vsaddr->vs_csr0 &= ~VS_XMIT_ON; 521 vsp->csr.csr_linkAvail = FALSE; 522 } 523 524 vsp->linkAvail = vsp->csr.csr_linkAvail; 525 526 return; 527 } 528 529 if (vsp->irr.intr_error) { 530 printI("error 0x%x\n", vsp->irr.intr_reg&0xffff); 531 vsp->stats.errors++; 532 /* set status and wake up user if necessary */ 533 if (vsp->vs_nextgo.fparm_all) { 534 vsp->vs_status = vsp->irr.intr_reg; 535 vsaddr->vs_pr1 = vsp->vs_nextgo.fparm_low; 536 vsaddr->vs_pr2 = vsp->vs_nextgo.fparm_high; 537 vsp->vs_nextgo.fparm_all = NULL; 538 vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */ 539 vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO); 540 } else 541 vsb->vsioa.status = vsp->irr.intr_reg; 542 wakeup((caddr_t) vsp); 543 return; 544 } 545 546 #ifdef notdef 547 printI("reason is %b\n", vsp->irr.intr_reason, VSIRR_BITS); 548 #endif 549 switch(vsp->irr.intr_reason) { 550 case VS_INT_CD: /* command done */ 551 /* set status and start a new command if necessary */ 552 if (vsp->vs_nextgo.fparm_all) { 553 vsp->vs_status = vsp->irr.intr_reg; 554 vsaddr->vs_pr1 = vsp->vs_nextgo.fparm_low; 555 vsaddr->vs_pr2 = vsp->vs_nextgo.fparm_high; 556 vsp->vs_nextgo.fparm_all = NULL; 557 vsaddr->vs_csr0 &= ~VS_FCN; /* clear bits */ 558 vsaddr->vs_csr0 |= (VS_IE | (VS_SEND << VS_FCSHIFT) | VS_GO); 559 } else 560 vsb->vsioa.status = vsp->irr.intr_reg; 561 break; 562 563 case VS_INT_MM: /* mouse moved */ 564 565 vsb->vsioa.mouse = cur; 566 567 if (!vsp->open) 568 return; /* ignore on closed device */ 569 570 /* no event if inside box */ 571 if (cur.y < vsb->vsioa.mbox.bottom && 572 cur.y >= vsb->vsioa.mbox.top && 573 cur.x < vsb->vsioa.mbox.right && 574 cur.x >= vsb->vsioa.mbox.left) 575 return; 576 577 /* trash box */ 578 vsb->vsioa.mbox.bottom = 0; 579 580 if (EVROUND(vsb->vsioa.itail+1) == vsb->vsioa.ihead) 581 return; 582 i = EVROUND(vsb->vsioa.itail-1); 583 if ((vsb->vsioa.itail != vsb->vsioa.ihead) && 584 (i != vsb->vsioa.ihead)) { 585 vep = &vsb->ibuff[i]; 586 if (vep->vse_type == VSE_MMOTION) { 587 vep->vse_x = cur.x; 588 vep->vse_y = cur.y; 589 vep->vse_time = mfpr(TODR); 590 return; 591 } 592 } 593 /* put event into queue and do select */ 594 vep = &vsb->ibuff[vsb->vsioa.itail]; 595 vep->vse_type = VSE_MMOTION; 596 vep->vse_x = cur.x; 597 vep->vse_y = cur.y; 598 vep->vse_time = mfpr(TODR); 599 vsb->vsioa.itail = EVROUND(vsb->vsioa.itail+1); 600 if (vsp->rsel) { 601 selwakeup(vsp->rsel, 0); 602 vsp->rsel = 0; 603 } 604 break; 605 606 case VS_INT_BE: /* button event */ 607 if (!vsp->open) 608 return; /* ignore on closed device */ 609 610 if (vsp->krr.kbd_device == VSE_MOUSE) { 611 vsb->vsioa.mouse.x = cur.x; 612 vsb->vsioa.mouse.y = cur.y; 613 } 614 /* check for room in the queue */ 615 if ((i = EVROUND(vsb->vsioa.itail+1)) == vsb->vsioa.ihead) 616 return; 617 /* put event into queue and do select */ 618 vep = &vsb->ibuff[vsb->vsioa.itail]; 619 vep->vse_type = VSE_BUTTON; 620 vep->vse_key = vsp->krr.kbd_key; 621 vep->vse_direction = vsp->krr.kbd_transition; 622 vep->vse_device = vsp->krr.kbd_device; 623 vep->vse_time = mfpr(TODR); 624 vep->vse_x = vsb->vsioa.mouse.x; 625 vep->vse_y = vsb->vsioa.mouse.y; 626 vsb->vsioa.itail = i; 627 if (vsp->rsel) { 628 selwakeup(vsp->rsel, 0); 629 vsp->rsel = 0; 630 } 631 break; 632 633 case VS_INT_TM: /* tablet moved */ 634 if (!vsp->open) 635 return; /* ignore on closed device */ 636 637 if (EVROUND(vsb->vsioa.itail+1) == vsb->vsioa.ihead) 638 return; 639 i = EVROUND(vsb->vsioa.itail-1); 640 if ((vsb->vsioa.itail != vsb->vsioa.ihead) && 641 (i != vsb->vsioa.ihead)) { 642 vep = &vsb->ibuff[i]; 643 if (vep->vse_type == VSE_TMOTION) { 644 vep->vse_x = cur.x; 645 vep->vse_y = cur.y; 646 vep->vse_time = mfpr(TODR); 647 return; 648 } 649 } 650 /* put event into queue and do select */ 651 vep = &vsb->ibuff[vsb->vsioa.itail]; 652 vep->vse_type = VSE_TMOTION; 653 vep->vse_x = cur.x; 654 vep->vse_y = cur.y; 655 vep->vse_time = mfpr(TODR); 656 vsb->vsioa.itail = EVROUND(vsb->vsioa.itail+1); 657 if (vsp->rsel) { 658 selwakeup(vsp->rsel, 0); 659 vsp->rsel = 0; 660 } 661 break; 662 663 case VS_INT_US: /* unsolicited */ 664 vsp->stats.unsolIntr++; 665 return; 666 667 case VS_INT_ID: /* Initialization done */ 668 /* save offset from device */ 669 vsp->offset.fparm_all = vsp->pr.fparm_all; 670 /* save rom version */ 671 vsp->romVersion = cur.x; 672 vsp->inited = TRUE; 673 break; 674 675 case VS_INT_SE: /* ucode started */ 676 break; 677 678 case VS_INT_PWR: /* power up complete */ 679 /* save rom version */ 680 vsp->romVersion = cur.x; 681 vsp->inited = FALSE; 682 if (vsp->open && vsp->pgrp) 683 gsignal(vsp->pgrp, SIGHUP); 684 break; 685 686 default: 687 printI("vs%d: unknown interrupt %b\n", VSUNIT(dev), 688 vsp->irr.intr_reason, VSIRR_BITS); 689 return; 690 } 691 wakeup((caddr_t) vsp); 692 } 693 694 vsreset(uban) 695 int uban; 696 { 697 register int i; 698 register struct uba_device *uip; 699 register struct vs_softc *vsp = vs_softc; 700 701 for (i = 0; i < NVS; i++, vsp++) { 702 if ((uip = vsdinfo[i]) == 0 || uip->ui_alive == 0 || 703 uip->ui_ubanum != uban || vsp->open == 0) 704 continue; 705 printf(" vs%d", i); 706 vsp->inited = FALSE; 707 if (vsp->open && vsp->pgrp) 708 gsignal(vsp->pgrp, SIGHUP); 709 } 710 } 711 712 vsselect(dev, rw) 713 dev_t dev; 714 { 715 register struct vsBuffArea *vsb = &vsBuff[VSUNIT(dev)]; 716 int s = spl5(); 717 718 switch(rw) { 719 case FREAD: 720 if (vsb->vsioa.ihead != vsb->vsioa.itail) { 721 splx(s); 722 return(1); 723 } 724 vs_softc[VSUNIT(dev)].rsel = u.u_procp; 725 splx(s); 726 return(0); 727 728 case FWRITE: 729 splx(s); 730 return(EACCES); 731 } 732 } 733 734 /* 735 * Initialize VS100 or SBO. 736 * Set XMITON. VS100 will respond with link available. SBO won't, so 737 * don't wait forever; assume everything is OK and warn user. 738 */ 739 740 vsInitFiber(dev) 741 dev_t dev; 742 { 743 struct vsdevice *vsaddr = (struct vsdevice *) vsdinfo[VSUNIT(dev)]->ui_addr; 744 register struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; 745 int s; 746 #ifdef VSSBO 747 int vsFiberNudge(); 748 749 timeout(vsFiberNudge, (caddr_t) dev, 2*hz); 750 #endif 751 s = spl5(); 752 vsaddr->vs_csr0 |= (VS_IE | VS_XMIT_ON); /* turn link on */ 753 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_INITF, 0); 754 splx(s); 755 #ifdef VSSBO 756 if (!vsp->linkAvail) { 757 uprintf("\007This had better be a vs125!\n"); 758 printf("vs%d must be a vs125\n", VSUNIT(dev)); 759 vsp->linkAvail = TRUE; 760 } 761 #endif 762 } 763 764 #ifdef VSSBO 765 vsFiberNudge(dev) 766 dev_t dev; 767 { 768 struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; 769 770 if (!vsp->linkAvail) 771 wakeup((caddr_t) vsp); 772 } 773 #endif VSSBO 774 775 vsInitDev(dev, retry) 776 dev_t dev; 777 int retry; 778 { 779 register struct vsdevice *vsaddr; 780 register struct vs_softc *vsp; 781 int s; 782 int vsInitNudge(); 783 784 vsaddr = (struct vsdevice *) vsdinfo[VSUNIT(dev)]->ui_addr; 785 vsp = &vs_softc[VSUNIT(dev)]; 786 787 if (!vsp->linkAvail) 788 vsInitFiber(dev); 789 while (1) { 790 if (retry) 791 timeout(vsInitNudge, (caddr_t) dev, 10*hz); 792 s = spl5(); 793 vsaddr->vs_irr = 0; 794 vsaddr->vs_csr0 &= ~VS_FCN; 795 vsaddr->vs_csr0 |= (VS_IE | (VS_INIT << VS_FCSHIFT) | VS_GO); 796 tsleep((caddr_t) vsp, VSWAITPRI, SLP_VS_INITDEV, 0); 797 splx(s); 798 if (vsp->inited) 799 break; 800 printM("vs%d: VS_INIT fails\n", VSUNIT(dev)); 801 uprintf("vsInitDev %x %x\n",vsaddr->vs_csr0, vsaddr->vs_csr1); 802 } 803 } 804 805 vsInitNudge(dev) 806 dev_t dev; 807 { 808 struct vs_softc *vsp = &vs_softc[VSUNIT(dev)]; 809 810 if (!vsp->inited) 811 wakeup((caddr_t) vsp); 812 } 813 814 vsError(vsp) 815 register struct vs_softc *vsp; 816 { 817 if (vsp->irr.intr_error) { 818 register int ret = vsp->irr.intr_reg; 819 820 printD("\treturning 0x%x\n", ret); 821 vsp->irr.intr_reg = 0; 822 return(ret+128); 823 } 824 return(0); 825 } 826 #endif 827 828