|
|
1.1 ! root 1: /* ps.c 6.1 83/08/13 */ ! 2: ! 3: /* ! 4: * Evans and Sutherland Picture System 2 driver ! 5: */ ! 6: ! 7: /* ! 8: * Still to be done: ! 9: * WAIT_HIT ! 10: */ ! 11: ! 12: #include "ps.h" ! 13: #if NPS > 0 ! 14: ! 15: #define EXTERNAL_SYNC ! 16: ! 17: #include "../machine/pte.h" ! 18: ! 19: #include "../h/param.h" ! 20: #include "../h/systm.h" ! 21: #include "../h/ioctl.h" ! 22: #include "../h/map.h" ! 23: #include "../h/buf.h" ! 24: #include "../h/conf.h" ! 25: #include "../h/dir.h" ! 26: #include "../h/user.h" ! 27: #include "../h/uio.h" ! 28: ! 29: #include "../vaxuba/ubareg.h" ! 30: #include "../vaxuba/ubavar.h" ! 31: #include "../vaxuba/psreg.h" ! 32: ! 33: int psprobe(), psattach(), psintr(); ! 34: struct uba_device *psdinfo[NPS]; ! 35: u_short psstd[] = { 0 }; ! 36: struct uba_driver psdriver = ! 37: { psprobe, 0, psattach, 0, psstd, "ps", psdinfo }; ! 38: ! 39: #define PSUNIT(dev) (minor(dev)) ! 40: ! 41: #define MAXAUTOREFRESH (4) ! 42: #define MAXAUTOMAP (4) ! 43: #define MAXDBSIZE (0177777/2) ! 44: ! 45: #define PSPRI (PZERO+1) ! 46: ! 47: #define PSWAIT() {register short int i, j; i=20000; while((i-- != 0)\ ! 48: && (((j=psaddr->ps_iostat)&DIOREADY)==0));} ! 49: ! 50: struct ps { ! 51: char ps_open; ! 52: short int ps_uid; ! 53: struct { ! 54: enum { SINGLE_STEP_RF, AUTO_RF, TIME_RF } state; ! 55: enum { RUNNING_RF, SYNCING_RF, WAITING_MAP, STOPPED_RF } mode; ! 56: unsigned short int sraddrs[MAXAUTOREFRESH]; ! 57: short int nsraddrs; ! 58: short int srcntr; ! 59: char waiting; ! 60: char stop; ! 61: int icnt; ! 62: int timecnt; ! 63: } ps_refresh; ! 64: struct { ! 65: enum { ON_DB, OFF_DB } state; ! 66: unsigned short int dbaddrs[2]; ! 67: unsigned short int dbsize; ! 68: short int rbuffer; ! 69: } ps_dbuffer; ! 70: struct { ! 71: enum { SINGLE_STEP_MAP, AUTO_MAP } state; ! 72: enum { RUNNING_MAP, WAITING_RF, WAITING_START } mode; ! 73: unsigned short int maddrs[MAXAUTOMAP]; ! 74: short int nmaddrs; ! 75: short int mcntr; ! 76: short int outputstart; ! 77: char waiting; ! 78: char stop; ! 79: int icnt; ! 80: } ps_map; ! 81: struct { ! 82: short int ticked; ! 83: short int missed; ! 84: int icnt; ! 85: } ps_clock; ! 86: struct { ! 87: int icnt; ! 88: } ps_hit; ! 89: int ps_strayintr; ! 90: int last_request; ! 91: int strayrequest; ! 92: int ps_icnt; ! 93: } ps[NPS]; ! 94: ! 95: psprobe(reg) ! 96: caddr_t reg; ! 97: { ! 98: register int br, cvec; ! 99: register struct psdevice *psaddr = (struct psdevice *) reg; ! 100: ! 101: psaddr->ps_iostat = PSRESET; ! 102: DELAY(200); ! 103: psaddr->ps_addr = RTCIE; ! 104: PSWAIT(); ! 105: psaddr->ps_data = 01; ! 106: psaddr->ps_iostat = PSIE; ! 107: psaddr->ps_addr = RTCSR; ! 108: PSWAIT(); ! 109: psaddr->ps_data = (SYNC|RUN); ! 110: DELAY(200000); ! 111: psaddr->ps_addr = RTCREQ; ! 112: PSWAIT(); ! 113: psaddr->ps_data = 01; ! 114: psaddr->ps_iostat = 0; ! 115: psaddr->ps_iostat = PSRESET; ! 116: return (sizeof (struct psdevice)); ! 117: } ! 118: ! 119: /*ARGSUSED*/ ! 120: psattach(ui) ! 121: register struct uba_device *ui; ! 122: { ! 123: ! 124: } ! 125: ! 126: psopen(dev) ! 127: dev_t dev; ! 128: { ! 129: register struct ps *psp; ! 130: register struct uba_device *ui; ! 131: register int unit = PSUNIT(dev); ! 132: ! 133: if (unit >= NPS || (psp = &ps[minor(dev)])->ps_open || ! 134: (ui = psdinfo[unit]) == 0 || ui->ui_alive == 0) ! 135: return (ENXIO); ! 136: psp->ps_open = 1; ! 137: psp->ps_uid = u.u_uid; ! 138: psp->ps_strayintr = 0; ! 139: psp->ps_refresh.state = SINGLE_STEP_RF; ! 140: psp->ps_refresh.waiting = 0; ! 141: psp->ps_refresh.stop = 0; ! 142: psp->ps_dbuffer.state = OFF_DB; ! 143: psp->ps_map.state = SINGLE_STEP_MAP; ! 144: psp->ps_map.waiting = 0; ! 145: psp->ps_map.stop = 0; ! 146: psp->ps_clock.ticked = 0; ! 147: psp->ps_refresh.icnt = psp->ps_map.icnt = psp->ps_clock.icnt = 0; ! 148: psp->ps_icnt = 0; ! 149: maptouser(ui->ui_addr); ! 150: return (0); ! 151: } ! 152: ! 153: psclose(dev) ! 154: dev_t dev; ! 155: { ! 156: register struct psdevice *psaddr = ! 157: (struct psdevice *) psdinfo[PSUNIT(dev)]->ui_addr; ! 158: ! 159: ps[PSUNIT(dev)].ps_open = 0; ! 160: psaddr->ps_iostat = 0; /* clear IENABLE */ ! 161: PSWAIT(); ! 162: psaddr->ps_addr = RFSR; /* set in auto refresh mode */ ! 163: PSWAIT(); ! 164: psaddr->ps_data = AUTOREF; ! 165: unmaptouser(psaddr); ! 166: } ! 167: ! 168: /*ARGSUSED*/ ! 169: psread(dev, uio) ! 170: dev_t dev; ! 171: struct uio *uio; ! 172: { ! 173: } ! 174: ! 175: /*ARGSUSED*/ ! 176: pswrite(dev, uio) ! 177: dev_t dev; ! 178: struct uio *uio; ! 179: { ! 180: } ! 181: ! 182: /*ARGSUSED*/ ! 183: psioctl(dev, cmd, data, flag) ! 184: register caddr_t data; ! 185: { ! 186: register struct uba_device *ui = psdinfo[PSUNIT(dev)]; ! 187: register struct ps *psp = &ps[PSUNIT(dev)]; ! 188: int *waddr = *(int **)data; ! 189: int n, arg, i; ! 190: ! 191: switch (cmd) { ! 192: ! 193: case PSIOGETADDR: ! 194: *(caddr_t *)data = ui->ui_addr; ! 195: break; ! 196: ! 197: case PSIOAUTOREFRESH: ! 198: n = fuword(waddr++); ! 199: if (n == -1) ! 200: return (EFAULT); ! 201: if (n < 0 || n > MAXAUTOREFRESH) ! 202: return (EINVAL); ! 203: for (i = 0; i < n; i++) { ! 204: if ((arg = fuword(waddr++)) == -1) ! 205: return (EFAULT); ! 206: psp->ps_refresh.sraddrs[i] = arg; ! 207: } ! 208: psp->ps_refresh.state = AUTO_RF; ! 209: psp->ps_refresh.nsraddrs = n; ! 210: psp->ps_refresh.srcntr = 0; ! 211: psp->ps_refresh.mode = WAITING_MAP; ! 212: break; ! 213: ! 214: case PSIOAUTOMAP: ! 215: n = fuword(waddr++); ! 216: if (n == -1) ! 217: return (EFAULT); ! 218: if (n < 0 || n > MAXAUTOMAP) ! 219: return (EINVAL); ! 220: for (i = 0; i < n; i++) { ! 221: if ((arg = fuword(waddr++)) == -1) ! 222: return (EFAULT); ! 223: psp->ps_map.maddrs[i] = arg; ! 224: } ! 225: if ((arg = fuword(waddr++)) == -1) ! 226: return (EFAULT); ! 227: psp->ps_map.outputstart = arg; ! 228: psp->ps_map.state = AUTO_MAP; ! 229: psp->ps_map.nmaddrs = n; ! 230: psp->ps_map.mcntr = 0; ! 231: psp->ps_map.mode = WAITING_START; ! 232: break; ! 233: ! 234: case PSIOSINGLEREFRESH: ! 235: psp->ps_refresh.state = SINGLE_STEP_RF; ! 236: break; ! 237: ! 238: case PSIOSINGLEMAP: ! 239: psp->ps_map.state = SINGLE_STEP_MAP; ! 240: break; ! 241: ! 242: case PSIODOUBLEBUFFER: ! 243: if ((arg = fuword(waddr++)) == -1) ! 244: return (EFAULT); ! 245: psp->ps_dbuffer.dbaddrs[0] = arg; ! 246: if ((arg = fuword(waddr++)) == -1) ! 247: return (EFAULT); ! 248: if (arg <= 0 || arg > MAXDBSIZE) ! 249: return (EINVAL); ! 250: psp->ps_dbuffer.dbsize = arg; ! 251: psp->ps_dbuffer.dbaddrs[1] = ! 252: psp->ps_dbuffer.dbaddrs[0]+arg; ! 253: psp->ps_dbuffer.state = ON_DB; ! 254: psp->ps_dbuffer.rbuffer = 0; ! 255: break; ! 256: ! 257: case PSIOSINGLEBUFFER: ! 258: psp->ps_dbuffer.state = OFF_DB; ! 259: break; ! 260: ! 261: case PSIOTIMEREFRESH: ! 262: if (psp->ps_refresh.state != SINGLE_STEP_RF) ! 263: return(EINVAL); ! 264: if ((arg = fuword(waddr++)) == -1) ! 265: return(EFAULT); ! 266: psp->ps_refresh.state = TIME_RF; ! 267: psp->ps_refresh.timecnt = arg; ! 268: break; ! 269: ! 270: case PSIOWAITREFRESH: ! 271: if (psp->ps_refresh.mode != RUNNING_RF) /* not running */ ! 272: return (0); /* dont wait */ ! 273: /* fall into ... */ ! 274: ! 275: case PSIOSTOPREFRESH: ! 276: if (cmd == PSIOSTOPREFRESH) { ! 277: if (psp->ps_refresh.mode == STOPPED_RF ! 278: && psp->ps_refresh.state != TIME_RF) ! 279: return (0); ! 280: psp->ps_refresh.stop = 1; ! 281: } ! 282: spl5(); ! 283: psp->ps_refresh.waiting = 1; ! 284: while (psp->ps_refresh.waiting) ! 285: sleep(&psp->ps_refresh.waiting, PSPRI); ! 286: spl0(); ! 287: if (cmd == PSIOSTOPREFRESH) ! 288: psp->ps_refresh.mode = STOPPED_RF; ! 289: if (psp->ps_refresh.state == TIME_RF) ! 290: psp->ps_refresh.state = SINGLE_STEP_RF; ! 291: break; ! 292: ! 293: case PSIOWAITMAP: ! 294: if (psp->ps_map.mode != RUNNING_MAP) /* not running */ ! 295: return (0); /* dont wait */ ! 296: /* fall into ... */ ! 297: ! 298: case PSIOSTOPMAP: ! 299: if (cmd == PSIOSTOPMAP) ! 300: psp->ps_map.stop = 1; ! 301: spl5(); ! 302: psp->ps_map.waiting = 1; ! 303: while (psp->ps_map.waiting) ! 304: sleep(&psp->ps_map.waiting, PSPRI); ! 305: spl0(); ! 306: break; ! 307: ! 308: default: ! 309: return (ENOTTY); ! 310: break; ! 311: } ! 312: return (0); ! 313: } ! 314: ! 315: #define SAVEPSADDR() {register short int i, x;x=spl6();i=psaddr->ps_addr;\ ! 316: while(((i=psaddr->ps_iostat)&DIOREADY)==0);\ ! 317: savepsaddr=psaddr->ps_data;splx(x);} ! 318: #define RESTORPSADDR() {register int x,i;x=spl6();\ ! 319: while(((i=psaddr->ps_iostat)&DIOREADY)==0);\ ! 320: psaddr->ps_addr=savepsaddr;splx(x);} ! 321: ! 322: psclockintr(dev) ! 323: dev_t dev; ! 324: { ! 325: register struct psdevice *psaddr = ! 326: (struct psdevice *) psdinfo[PSUNIT(dev)]->ui_addr; ! 327: register struct ps *psp = &ps[PSUNIT(dev)]; ! 328: int savepsaddr; ! 329: ! 330: if (!psp->ps_open) ! 331: return; ! 332: psp->ps_clock.icnt++; ! 333: SAVEPSADDR(); ! 334: #ifndef EXTERNAL_SYNC ! 335: if (psp->ps_refresh.state == AUTO_RF) { ! 336: if (psp->ps_refresh.mode == SYNCING_RF ! 337: && psp->ps_refresh.state != TIME_RF) { ! 338: psrfnext(psp, psaddr); ! 339: } else { ! 340: psp->ps_clock.ticked++; ! 341: psp->ps_clock.missed++; ! 342: } ! 343: } ! 344: #endif ! 345: PSWAIT(); ! 346: psaddr->ps_addr = RTCREQ; ! 347: PSWAIT(); ! 348: psaddr->ps_data = 01; /* clear the request bits */ ! 349: RESTORPSADDR(); ! 350: } ! 351: ! 352: /*ARGSUSED*/ ! 353: pssystemintr(dev) ! 354: dev_t dev; ! 355: { ! 356: register struct psdevice *psaddr = ! 357: (struct psdevice *) psdinfo[PSUNIT(dev)]->ui_addr; ! 358: register struct ps *psp = &ps[PSUNIT(dev)]; ! 359: short int request; ! 360: register int savepsaddr, x; ! 361: ! 362: if (!psp->ps_open) ! 363: return; ! 364: psp->ps_icnt++; ! 365: SAVEPSADDR(); ! 366: PSWAIT(); ! 367: psaddr->ps_addr = SYSREQ; ! 368: PSWAIT(); ! 369: request = psaddr->ps_data&0377; ! 370: psp->last_request = request; ! 371: PSWAIT(); ! 372: psaddr->ps_addr = SYSREQ; ! 373: PSWAIT(); ! 374: psaddr->ps_data = request&(~(HALT_REQ|MOSTOP_REQ)); /* acknowledge */ ! 375: ! 376: if (request & (MOSTOP_REQ|HALT_REQ)) { /* Map stopped */ ! 377: psp->ps_map.icnt++; ! 378: psmapstop(psaddr); /* kill it dead */ ! 379: if (psp->ps_map.waiting) { ! 380: psp->ps_map.waiting = 0; ! 381: wakeup(&psp->ps_map.waiting); ! 382: if (psp->ps_map.stop) { ! 383: psp->ps_map.stop = 0; ! 384: goto tryrf; ! 385: } ! 386: } ! 387: if (psp->ps_map.state == AUTO_MAP) ! 388: if (!psmapnext(psp, psaddr)) { ! 389: psp->ps_map.mcntr = 0; ! 390: /* prepare for next round */ ! 391: pssetmapbounds(psp, psaddr); ! 392: if (psp->ps_refresh.mode == WAITING_MAP) { ! 393: if (psp->ps_dbuffer.state == ON_DB) ! 394: /* fill other db */ ! 395: psdbswitch(psp, psaddr); ! 396: else ! 397: psp->ps_map.mode = WAITING_RF; ! 398: psrfnext(psp, psaddr); /* start rf */ ! 399: } else ! 400: psp->ps_map.mode = WAITING_RF; ! 401: } ! 402: } ! 403: tryrf: ! 404: if (request & RFSTOP_REQ) { /* Refresh stopped */ ! 405: psp->ps_refresh.icnt++; ! 406: if (psp->ps_refresh.state == TIME_RF) ! 407: if(--psp->ps_refresh.timecnt > 0) ! 408: goto tryhit; ! 409: psrfstop(psaddr, psp); ! 410: if (psp->ps_refresh.waiting) { ! 411: psp->ps_refresh.waiting = 0; ! 412: wakeup(&psp->ps_refresh.waiting); ! 413: if (psp->ps_refresh.stop) { ! 414: psp->ps_refresh.stop = 0; ! 415: goto tryhit; ! 416: } ! 417: } ! 418: if (psp->ps_refresh.state == AUTO_RF) ! 419: if (!psrfnext(psp, psaddr)) { /* at end of refresh cycle */ ! 420: if (psp->ps_map.state == AUTO_MAP && ! 421: psp->ps_map.mode==WAITING_RF) { ! 422: if (psp->ps_dbuffer.state == ON_DB) ! 423: psdbswitch(psp, psaddr); ! 424: else ! 425: psmapnext(psp, psaddr); ! 426: } ! 427: psp->ps_refresh.srcntr = 0; ! 428: #ifdef EXTERNAL_SYNC ! 429: x = spl6(); ! 430: #endif ! 431: if (!psp->ps_clock.ticked || ! 432: !psrfnext(psp, psaddr)) { ! 433: psp->ps_refresh.mode = SYNCING_RF; ! 434: } ! 435: psp->ps_clock.ticked = 0; ! 436: psp->ps_refresh.mode = SYNCING_RF; ! 437: #ifdef EXTERNAL_SYNC ! 438: splx(x); ! 439: #endif ! 440: } ! 441: } ! 442: tryhit: ! 443: if (request & HIT_REQ) { /* Hit request */ ! 444: psp->ps_hit.icnt++; ! 445: } ! 446: if (request == 0) ! 447: psp->ps_strayintr++; ! 448: RESTORPSADDR(); ! 449: } ! 450: ! 451: psrfnext(psp, psaddr) ! 452: register struct ps *psp; ! 453: register struct psdevice *psaddr; ! 454: { ! 455: ! 456: if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs) ! 457: psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++], ! 458: psp, psaddr); ! 459: else if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs ! 460: && psp->ps_dbuffer.state == ON_DB) { ! 461: psrfstart(psp->ps_dbuffer.dbaddrs[psp->ps_dbuffer.rbuffer], ! 462: psp, psaddr); ! 463: psp->ps_refresh.srcntr++; /* flag for after dbuffer */ ! 464: } else ! 465: return(0); ! 466: return(1); ! 467: } ! 468: ! 469: psrfstart(dfaddr, psp, psaddr) ! 470: short int dfaddr; ! 471: register struct ps *psp; ! 472: register struct psdevice *psaddr; ! 473: { ! 474: int dummy; ! 475: ! 476: PSWAIT(); ! 477: psaddr->ps_addr = RFASA; ! 478: PSWAIT(); ! 479: psaddr->ps_data = dfaddr; ! 480: PSWAIT(); ! 481: dummy = psaddr->ps_data; /* just access to get to status reg */ ! 482: PSWAIT(); ! 483: psaddr->ps_data = RFSTART; /* may want to | this value in */ ! 484: psp->ps_refresh.mode = RUNNING_RF; ! 485: } ! 486: ! 487: psrfstop(psaddr, psp) ! 488: register struct psdevice *psaddr; ! 489: register struct ps *psp; ! 490: { ! 491: ! 492: PSWAIT(); ! 493: psaddr->ps_addr = RFSR; ! 494: PSWAIT(); ! 495: psaddr->ps_data = 0; ! 496: } ! 497: ! 498: psdbswitch(psp, psaddr) ! 499: register struct ps *psp; ! 500: register struct psdevice *psaddr; ! 501: { ! 502: ! 503: psp->ps_dbuffer.rbuffer = !psp->ps_dbuffer.rbuffer; ! 504: pssetmapbounds(psp, psaddr); ! 505: psmapnext(psp, psaddr); ! 506: } ! 507: ! 508: psmapnext(psp, psaddr) ! 509: register struct ps *psp; ! 510: register struct psdevice *psaddr; ! 511: { ! 512: ! 513: if (psp->ps_map.mcntr < psp->ps_map.nmaddrs) ! 514: psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++], psp, psaddr); ! 515: else ! 516: return(0); ! 517: return(1); ! 518: } ! 519: ! 520: pssetmapbounds(psp, psaddr) ! 521: register struct ps *psp; ! 522: register struct psdevice *psaddr; ! 523: { ! 524: unsigned short int start; ! 525: ! 526: PSWAIT(); ! 527: psaddr->ps_addr = MAOL; ! 528: PSWAIT(); ! 529: if (psp->ps_dbuffer.state == ON_DB) { ! 530: psaddr->ps_data = (start = psp->ps_dbuffer.dbaddrs[!psp->ps_dbuffer.rbuffer]) ! 531: +psp->ps_dbuffer.dbsize-2; /* 2 for a refresh halt command */ ! 532: PSWAIT(); ! 533: psaddr->ps_data = start; ! 534: } else { ! 535: start = psaddr->ps_data; /* dummy: don't update limit */ ! 536: PSWAIT(); ! 537: psaddr->ps_data = psp->ps_map.outputstart; ! 538: } ! 539: } ! 540: ! 541: psmapstart(dfaddr, psp, psaddr) ! 542: int dfaddr; ! 543: register struct ps *psp; ! 544: register struct psdevice *psaddr; ! 545: { ! 546: int data; ! 547: ! 548: PSWAIT(); ! 549: psaddr->ps_addr = MAIA; ! 550: PSWAIT(); ! 551: psaddr->ps_data = dfaddr; ! 552: PSWAIT(); ! 553: psaddr->ps_data = MAO|MAI; /* may want more here */ ! 554: psp->ps_map.mode = RUNNING_MAP; ! 555: } ! 556: ! 557: psmapstop(psaddr) ! 558: register struct psdevice *psaddr; ! 559: { ! 560: ! 561: PSWAIT(); ! 562: psaddr->ps_addr = MASR; ! 563: PSWAIT(); ! 564: psaddr->ps_data = 0; /* zero MAI bit */ ! 565: PSWAIT(); ! 566: psaddr->ps_addr = MAIA; ! 567: PSWAIT(); ! 568: psaddr->ps_data = 0; /* zero input address register */ ! 569: PSWAIT(); ! 570: psaddr->ps_addr = SYSREQ; ! 571: PSWAIT(); ! 572: psaddr->ps_data = HALT_REQ|MOSTOP_REQ; /* overkill?? */ ! 573: } ! 574: ! 575: /*ARGSUSED*/ ! 576: psdeviceintr(dev) ! 577: dev_t dev; ! 578: { ! 579: ! 580: printf("ps device intr\n"); ! 581: } ! 582: ! 583: /*ARGSUSED*/ ! 584: psdmaintr(dev) ! 585: dev_t dev; ! 586: { ! 587: ! 588: printf("ps dma intr\n"); ! 589: } ! 590: ! 591: psreset(uban) ! 592: int uban; ! 593: { ! 594: } ! 595: ! 596: psextsync(PC, PS) { ! 597: register int n; ! 598: register struct psdevice *psaddr; ! 599: register struct ps *psp; ! 600: register int savepsaddr; ! 601: ! 602: #ifdef EXTERNAL_SYNC ! 603: for (psp = ps, n = 0; n < NPS; psp++, n++) { ! 604: if (!psp->ps_open) ! 605: continue; ! 606: if(psp->ps_refresh.mode == SYNCING_RF ! 607: && psp->ps_refresh.state != TIME_RF) { ! 608: psaddr = (struct psdevice *) psdinfo[n]->ui_addr; ! 609: SAVEPSADDR(); ! 610: psrfnext(psp, psaddr); ! 611: RESTORPSADDR(); ! 612: } else { ! 613: psp->ps_clock.ticked++; ! 614: psp->ps_clock.missed++; ! 615: } ! 616: } ! 617: #endif ! 618: } ! 619: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.