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

Defined functions

vsError defined in line 813; used 9 times
vsFiberNudge defined in line 764; used 2 times
vsInitDev defined in line 774; used 2 times
vsInitFiber defined in line 739; used 1 times
vsInitNudge defined in line 804; used 2 times
vsattach defined in line 147; used 2 times
vsclose defined in line 238; never used
vsintr defined in line 444; used 1 times
vsioctl defined in line 302; never used
vsopen defined in line 165; never used
vsprobe defined in line 113; used 2 times
vsread defined in line 287; never used
vsreset defined in line 693; never used
vsselect defined in line 711; never used
vswrite defined in line 294; never used

Defined variables

vsBuff defined in line 62; used 6 times
vsDebugPrintfs defined in line 98; used 2 times
vsIntrPrintfs defined in line 97; used 1 times
  • in line 94
vsMlpPrintfs defined in line 99; used 2 times
  • in line 96(2)
vs_softc defined in line 89; used 11 times
vsdinfo defined in line 66; used 8 times
vsdriver defined in line 68; never used
vsstd defined in line 67; used 1 times
  • in line 69

Defined struct's

vsBuffArea defined in line 57; used 16 times
vs_softc defined in line 73; used 22 times

Defined macros

EVROUND defined in line 53; used 7 times
FALSE defined in line 92; used 11 times
TRUE defined in line 91; used 4 times
VSBUFFSIZE defined in line 56; used 3 times
VSMAXEVQ defined in line 52; used 3 times
VSUNIT defined in line 71; used 31 times
VSWAITPRI defined in line 51; used 10 times
printD defined in line 95; used 1 times
printI defined in line 94; used 10 times
printM defined in line 96; used 4 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2211
Valid CSS Valid XHTML 1.0 Strict