|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1982, 1986 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)ps.c 7.7 (Berkeley) 5/9/91 ! 34: */ ! 35: ! 36: /* ! 37: * Evans and Sutherland Picture System 2 driver -- Bill Reeves. ! 38: */ ! 39: ! 40: /* ! 41: * Still to be done: ! 42: * WAIT_HIT ! 43: */ ! 44: ! 45: #include "ps.h" ! 46: #if NPS > 0 ! 47: ! 48: #define EXTERNAL_SYNC ! 49: ! 50: #include "../include/pte.h" ! 51: ! 52: #include "sys/param.h" ! 53: #include "sys/systm.h" ! 54: #include "sys/ioctl.h" ! 55: #include "sys/map.h" ! 56: #include "sys/buf.h" ! 57: #include "sys/conf.h" ! 58: #include "sys/user.h" ! 59: #include "sys/uio.h" ! 60: ! 61: #include "ubareg.h" ! 62: #include "ubavar.h" ! 63: #include "psreg.h" ! 64: ! 65: int psprobe(), psattach(), psextsync(); ! 66: int psclockintr(), pssystemintr(), psdeviceintr(), psdmaintr(); ! 67: struct uba_device *psdinfo[NPS]; ! 68: u_short psstd[] = { 0 }; ! 69: struct uba_driver psdriver = ! 70: { psprobe, 0, psattach, 0, psstd, "ps", psdinfo }; ! 71: ! 72: #define PSUNIT(dev) (minor(dev)) ! 73: ! 74: #define MAXAUTOREFRESH 4 ! 75: #define MAXAUTOMAP 4 ! 76: #define MAXDBSIZE (0177777/2) ! 77: ! 78: #define PSPRI (PZERO+1) ! 79: ! 80: #define PSWAIT(psaddr) { \ ! 81: register short i = 20000, j; \ ! 82: while (i-- != 0 && ((j = psaddr->ps_iostat) & DIOREADY) == 0) \ ! 83: ;\ ! 84: } ! 85: ! 86: struct psrefresh { ! 87: enum { ! 88: SINGLE_STEP_RF, ! 89: AUTO_RF, ! 90: TIME_RF ! 91: } state; ! 92: enum { ! 93: RUNNING_RF, ! 94: SYNCING_RF, ! 95: WAITING_MAP, ! 96: STOPPED_RF ! 97: } mode; ! 98: u_short sraddrs[MAXAUTOREFRESH]; ! 99: short nsraddrs; ! 100: short srcntr; ! 101: char waiting; ! 102: char stop; ! 103: int icnt; ! 104: int timecnt; ! 105: }; ! 106: ! 107: struct psdbuffer { ! 108: enum { ! 109: ON_DB, ! 110: OFF_DB ! 111: } state; ! 112: u_short dbaddrs[2]; ! 113: u_short dbsize; ! 114: short rbuffer; ! 115: }; ! 116: ! 117: struct psmap { ! 118: enum { ! 119: SINGLE_STEP_MAP, ! 120: AUTO_MAP ! 121: } state; ! 122: enum { ! 123: RUNNING_MAP, ! 124: WAITING_RF, ! 125: WAITING_START, ! 126: STOPPED_MAP ! 127: } mode; ! 128: u_short maddrs[MAXAUTOMAP]; ! 129: short nmaddrs; ! 130: short mcntr; ! 131: short outputstart; ! 132: char waiting; ! 133: char stop; ! 134: int icnt; ! 135: }; ! 136: ! 137: /* ! 138: * PS2 software state. ! 139: */ ! 140: struct ps { ! 141: char ps_open; /* device is open */ ! 142: uid_t ps_uid; /* uid of device owner */ ! 143: struct psrefresh ps_refresh; /* refresh state */ ! 144: struct psdbuffer ps_dbuffer; /* double buffering state */ ! 145: struct psmap ps_map; /* segment map state */ ! 146: int ps_clockticks; /* clock ints between refresh */ ! 147: int ps_clockmiss; /* clock ints w/o refresh */ ! 148: int ps_clockcnt; /* count of clock interrupts */ ! 149: int ps_hitcnt; /* count of hit interrupts */ ! 150: int ps_strayintr; /* count of stray interrupts */ ! 151: int ps_icnt; /* count of system interrupts */ ! 152: /* BEGIN GROT */ ! 153: int ps_lastrequest; ! 154: int ps_lastrequest2; ! 155: int ps_lastfunnyrequest; ! 156: int ps_funnycnt; ! 157: /* END GROT */ ! 158: } ps[NPS]; ! 159: ! 160: psprobe(reg) ! 161: caddr_t reg; ! 162: { ! 163: register int br, cvec; ! 164: register struct psdevice *psaddr = (struct psdevice *)reg; ! 165: ! 166: #ifdef lint ! 167: br = 0; cvec = br; br = cvec; ! 168: psclockintr((dev_t)0); pssystemintr((dev_t)0); ! 169: psdeviceintr((dev_t)0); psdmaintr((dev_t)0); ! 170: psextsync(0, 0); ! 171: #endif ! 172: psaddr->ps_iostat = PSRESET; ! 173: DELAY(200); ! 174: psaddr->ps_addr = RTCIE; ! 175: PSWAIT(psaddr); psaddr->ps_data = 01; ! 176: psaddr->ps_iostat = PSIE; ! 177: psaddr->ps_addr = RTCSR; ! 178: PSWAIT(psaddr); psaddr->ps_data = SYNC|RUN; ! 179: DELAY(200000); ! 180: psaddr->ps_addr = RTCREQ; ! 181: PSWAIT(psaddr); psaddr->ps_data = 01; ! 182: psaddr->ps_iostat = 0; ! 183: psaddr->ps_iostat = PSRESET; ! 184: return (sizeof (struct psdevice)); ! 185: } ! 186: ! 187: /*ARGSUSED*/ ! 188: psattach(ui) ! 189: struct uba_device *ui; ! 190: { ! 191: ! 192: } ! 193: ! 194: psopen(dev) ! 195: dev_t dev; ! 196: { ! 197: register struct ps *psp; ! 198: register struct uba_device *ui; ! 199: register int unit = PSUNIT(dev); ! 200: ! 201: if (unit >= NPS || (psp = &ps[minor(dev)])->ps_open || ! 202: (ui = psdinfo[unit]) == 0 || ui->ui_alive == 0) ! 203: return (ENXIO); ! 204: psp->ps_open = 1; ! 205: psp->ps_uid = u.u_uid; ! 206: psp->ps_strayintr = 0; ! 207: psp->ps_refresh.state = SINGLE_STEP_RF; ! 208: psp->ps_refresh.mode = STOPPED_RF; ! 209: psp->ps_refresh.waiting = 0; ! 210: psp->ps_refresh.stop = 0; ! 211: psp->ps_dbuffer.state = OFF_DB; ! 212: psp->ps_map.state = SINGLE_STEP_MAP; ! 213: psp->ps_map.mode = STOPPED_MAP; ! 214: psp->ps_map.waiting = 0; ! 215: psp->ps_map.stop = 0; ! 216: psp->ps_clockticks = 0; ! 217: psp->ps_clockmiss = 0; ! 218: psp->ps_refresh.icnt = psp->ps_map.icnt = psp->ps_clockcnt = 0; ! 219: psp->ps_hitcnt = 0; ! 220: psp->ps_icnt = 0; ! 221: maptouser(ui->ui_addr); ! 222: return (0); ! 223: } ! 224: ! 225: psclose(dev) ! 226: dev_t dev; ! 227: { ! 228: register struct psdevice *psaddr = ! 229: (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; ! 230: ! 231: ps[PSUNIT(dev)].ps_open = 0; ! 232: psaddr->ps_iostat = 0; /* clear IENABLE */ ! 233: PSWAIT(psaddr); psaddr->ps_addr = RFSR; /* set in auto refresh mode */ ! 234: PSWAIT(psaddr); psaddr->ps_data = AUTOREF; ! 235: unmaptouser((caddr_t)psaddr); ! 236: return (0); ! 237: } ! 238: ! 239: /*ARGSUSED*/ ! 240: psread(dev, uio) ! 241: dev_t dev; ! 242: struct uio *uio; ! 243: { ! 244: } ! 245: ! 246: /*ARGSUSED*/ ! 247: pswrite(dev, uio) ! 248: dev_t dev; ! 249: struct uio *uio; ! 250: { ! 251: } ! 252: ! 253: /*ARGSUSED*/ ! 254: psioctl(dev, cmd, data, flag) ! 255: register caddr_t data; ! 256: { ! 257: register struct uba_device *ui = psdinfo[PSUNIT(dev)]; ! 258: register struct ps *psp = &ps[PSUNIT(dev)]; ! 259: int *waddr = *(int **)data; ! 260: int n, arg, i, error = 0; ! 261: ! 262: switch (cmd) { ! 263: ! 264: case PSIOGETADDR: ! 265: *(caddr_t *)data = ui->ui_addr; ! 266: break; ! 267: ! 268: case PSIOAUTOREFRESH: ! 269: n = fuword((caddr_t)waddr++); ! 270: if (n == -1) ! 271: return (EFAULT); ! 272: if (n < 0 || n > MAXAUTOREFRESH) ! 273: return (EINVAL); ! 274: for (i = 0; i < n; i++) { ! 275: if ((arg = fuword((caddr_t)waddr++)) == -1) ! 276: return (EFAULT); ! 277: psp->ps_refresh.sraddrs[i] = arg; ! 278: } ! 279: psp->ps_refresh.state = AUTO_RF; ! 280: psp->ps_refresh.nsraddrs = n; ! 281: psp->ps_refresh.srcntr = 0; ! 282: psp->ps_refresh.mode = WAITING_MAP; ! 283: break; ! 284: ! 285: case PSIOAUTOMAP: ! 286: n = fuword((caddr_t)waddr++); ! 287: if (n == -1) ! 288: return (EFAULT); ! 289: if (n < 0 || n > MAXAUTOMAP) ! 290: return (EINVAL); ! 291: for (i = 0; i < n; i++) { ! 292: if ((arg = fuword((caddr_t)waddr++)) == -1) ! 293: return (EFAULT); ! 294: psp->ps_map.maddrs[i] = arg; ! 295: } ! 296: if ((arg = fuword((caddr_t)waddr++)) == -1) ! 297: return (EFAULT); ! 298: psp->ps_map.outputstart = arg; ! 299: psp->ps_map.state = AUTO_MAP; ! 300: psp->ps_map.nmaddrs = n; ! 301: psp->ps_map.mcntr = 0; ! 302: psp->ps_map.mode = WAITING_START; ! 303: break; ! 304: ! 305: case PSIOSINGLEREFRESH: ! 306: psp->ps_refresh.state = SINGLE_STEP_RF; ! 307: break; ! 308: ! 309: case PSIOSINGLEMAP: ! 310: psp->ps_map.state = SINGLE_STEP_MAP; ! 311: break; ! 312: ! 313: case PSIODOUBLEBUFFER: ! 314: if ((arg = fuword((caddr_t)waddr++)) == -1) ! 315: return (EFAULT); ! 316: psp->ps_dbuffer.dbaddrs[0] = arg; ! 317: if ((arg = fuword((caddr_t)waddr++)) == -1) ! 318: return (EFAULT); ! 319: if (arg <= 0 || arg > MAXDBSIZE) ! 320: return (EINVAL); ! 321: psp->ps_dbuffer.dbsize = arg; ! 322: psp->ps_dbuffer.dbaddrs[1] = psp->ps_dbuffer.dbaddrs[0]+arg; ! 323: psp->ps_dbuffer.state = ON_DB; ! 324: psp->ps_dbuffer.rbuffer = 0; ! 325: break; ! 326: ! 327: case PSIOSINGLEBUFFER: ! 328: psp->ps_dbuffer.state = OFF_DB; ! 329: break; ! 330: ! 331: case PSIOTIMEREFRESH: ! 332: if (psp->ps_refresh.state != SINGLE_STEP_RF) ! 333: return (EINVAL); ! 334: if ((arg = fuword((caddr_t)waddr++)) == -1) ! 335: return (EFAULT); ! 336: psp->ps_refresh.state = TIME_RF; ! 337: psp->ps_refresh.timecnt = arg; ! 338: break; ! 339: ! 340: case PSIOWAITREFRESH: ! 341: if (psp->ps_refresh.mode != RUNNING_RF) /* not running */ ! 342: return (0); /* dont wait */ ! 343: /* fall into ... */ ! 344: ! 345: case PSIOSTOPREFRESH: ! 346: if (cmd == PSIOSTOPREFRESH) { ! 347: if (psp->ps_refresh.mode == STOPPED_RF && ! 348: psp->ps_refresh.state != TIME_RF) ! 349: return (0); ! 350: psp->ps_refresh.stop = 1; ! 351: } ! 352: (void) spl5(); ! 353: psp->ps_refresh.waiting = 1; ! 354: while (psp->ps_refresh.waiting) ! 355: if (error = tsleep(&psp->ps_refresh.waiting, ! 356: PSPRI | PCATCH, devwait, 0)) ! 357: break; ! 358: (void) spl0(); ! 359: if (error) ! 360: return (error); ! 361: if (cmd == PSIOSTOPREFRESH) ! 362: psp->ps_refresh.mode = STOPPED_RF; ! 363: if (psp->ps_refresh.state == TIME_RF) ! 364: psp->ps_refresh.state = SINGLE_STEP_RF; ! 365: break; ! 366: ! 367: case PSIOWAITMAP: ! 368: if (psp->ps_map.mode != RUNNING_MAP) /* not running */ ! 369: return (0); /* dont wait */ ! 370: /* fall into ... */ ! 371: ! 372: case PSIOSTOPMAP: ! 373: if (cmd == PSIOSTOPMAP) ! 374: psp->ps_map.stop = 1; ! 375: (void) spl5(); ! 376: psp->ps_map.waiting = 1; ! 377: while (psp->ps_map.waiting) ! 378: if (error = tsleep(&psp->ps_map.waiting, PSPRI | PCATCH, ! 379: devwait, 0)) ! 380: break; ! 381: (void) spl0(); ! 382: break; ! 383: ! 384: default: ! 385: return (ENOTTY); ! 386: break; ! 387: } ! 388: return (error); ! 389: } ! 390: ! 391: #define SAVEPSADDR(psaddr, savepsaddr) { \ ! 392: register short i, xx1; \ ! 393: xx1 = splclock(); \ ! 394: i = psaddr->ps_addr; \ ! 395: while ((psaddr->ps_iostat & DIOREADY) == 0) \ ! 396: ; \ ! 397: savepsaddr = psaddr->ps_data; \ ! 398: splx(xx1); \ ! 399: } ! 400: #define RESTORPSADDR(psaddr, savepsaddr) { \ ! 401: register short xx2; \ ! 402: xx2 = splclock(); \ ! 403: while ((psaddr->ps_iostat & DIOREADY) == 0) \ ! 404: ;\ ! 405: psaddr->ps_addr = savepsaddr; \ ! 406: splx(xx2); \ ! 407: } ! 408: ! 409: psclockintr(dev) ! 410: dev_t dev; ! 411: { ! 412: register struct psdevice *psaddr = ! 413: (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; ! 414: register struct ps *psp = &ps[PSUNIT(dev)]; ! 415: int savepsaddr; ! 416: ! 417: if (!psp->ps_open) ! 418: return; ! 419: psp->ps_clockcnt++; ! 420: SAVEPSADDR(psaddr, savepsaddr); ! 421: #ifndef EXTERNAL_SYNC ! 422: if (psp->ps_refresh.state == AUTO_RF) { ! 423: if (psp->ps_refresh.mode == SYNCING_RF && ! 424: psp->ps_refresh.state != TIME_RF) { ! 425: (void) psrfnext(psp, psaddr); ! 426: } else { ! 427: psp->ps_clockticks++; ! 428: psp->ps_clockmiss++; ! 429: } ! 430: } ! 431: #endif ! 432: PSWAIT(psaddr); psaddr->ps_addr = RTCREQ; ! 433: PSWAIT(psaddr); psaddr->ps_data = 01; /* clear the request bits */ ! 434: RESTORPSADDR(psaddr, savepsaddr); ! 435: } ! 436: ! 437: /*ARGSUSED*/ ! 438: pssystemintr(dev) ! 439: dev_t dev; ! 440: { ! 441: register struct psdevice *psaddr = ! 442: (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; ! 443: register struct ps *psp = &ps[PSUNIT(dev)]; ! 444: short request, tmp; ! 445: register int savepsaddr, x; ! 446: ! 447: if (!psp->ps_open) ! 448: return; ! 449: psp->ps_icnt++; ! 450: SAVEPSADDR(psaddr, savepsaddr); ! 451: PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; ! 452: PSWAIT(psaddr); request = psaddr->ps_data; ! 453: request = request&0377; ! 454: psp->ps_lastrequest2 = psp->ps_lastrequest; ! 455: psp->ps_lastrequest = request; ! 456: if (request &~ (HALT_REQ|RFSTOP_REQ|HIT_REQ)) { ! 457: psp->ps_lastfunnyrequest = request; ! 458: psp->ps_funnycnt++; ! 459: } ! 460: PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; ! 461: tmp = request&(~(HALT_REQ|MOSTOP_REQ)); /* acknowledge */ ! 462: PSWAIT(psaddr); psaddr->ps_data = tmp; ! 463: ! 464: if (request & (MOSTOP_REQ|HALT_REQ)) { /* Map stopped */ ! 465: psp->ps_map.icnt++; ! 466: psmapstop(psaddr, psp, request);/* kill it dead */ ! 467: if (psp->ps_map.waiting) { ! 468: psp->ps_map.waiting = 0; ! 469: wakeup(&psp->ps_map.waiting); ! 470: if (psp->ps_map.stop) { ! 471: psp->ps_map.stop = 0; ! 472: goto tryrf; ! 473: } ! 474: } ! 475: if (psp->ps_map.state == AUTO_MAP && !psmapnext(psp, psaddr)) { ! 476: psp->ps_map.mcntr = 0; ! 477: /* prepare for next round */ ! 478: pssetmapbounds(psp, psaddr); ! 479: if (psp->ps_refresh.state == AUTO_RF) { ! 480: if (psp->ps_refresh.mode == WAITING_MAP){ ! 481: if (psp->ps_dbuffer.state == ON_DB) ! 482: /* fill other db */ ! 483: psdbswitch(psp, psaddr); ! 484: else ! 485: psp->ps_map.mode = WAITING_RF; ! 486: #ifdef EXTERNAL_SYNC ! 487: x = splclock(); ! 488: #endif ! 489: (void) psrfnext(psp, psaddr); ! 490: #ifdef EXTERNAL_SYNC ! 491: splx(x); ! 492: #endif ! 493: } else ! 494: psp->ps_map.mode = WAITING_RF; ! 495: } else { /* no auto refresh */ ! 496: if (psp->ps_dbuffer.state == ON_DB) ! 497: /* fill other db */ ! 498: psdbswitch(psp, psaddr); ! 499: else ! 500: (void) psmapnext(psp, psaddr); ! 501: } ! 502: } ! 503: } ! 504: tryrf: ! 505: if (request & RFSTOP_REQ) { /* Refresh stopped */ ! 506: psp->ps_refresh.icnt++; ! 507: if (psp->ps_refresh.state == TIME_RF) ! 508: if (--psp->ps_refresh.timecnt > 0) ! 509: goto tryhit; ! 510: psrfstop(psaddr, psp); ! 511: if (psp->ps_refresh.waiting) { ! 512: psp->ps_refresh.waiting = 0; ! 513: wakeup(&psp->ps_refresh.waiting); ! 514: if (psp->ps_refresh.stop) { ! 515: psp->ps_refresh.stop = 0; ! 516: goto tryhit; ! 517: } ! 518: } ! 519: if (psp->ps_refresh.state == AUTO_RF) ! 520: if (!psrfnext(psp, psaddr)) { /* at end of refresh cycle */ ! 521: if (psp->ps_map.state == AUTO_MAP && ! 522: psp->ps_map.mode == WAITING_RF) { ! 523: if (psp->ps_dbuffer.state == ON_DB) ! 524: psdbswitch(psp, psaddr); ! 525: else ! 526: (void) psmapnext(psp, psaddr); ! 527: } ! 528: psp->ps_refresh.srcntr = 0; ! 529: #ifdef EXTERNAL_SYNC ! 530: x = splclock(); ! 531: #endif ! 532: psp->ps_refresh.mode = SYNCING_RF; ! 533: if (psp->ps_clockticks) ! 534: (void) psrfnext(psp, psaddr); ! 535: psp->ps_clockticks = 0; ! 536: #ifdef EXTERNAL_SYNC ! 537: splx(x); ! 538: #endif ! 539: } ! 540: } ! 541: tryhit: ! 542: if (request & HIT_REQ) /* Hit request */ ! 543: psp->ps_hitcnt++; ! 544: if (request == 0) ! 545: psp->ps_strayintr++; ! 546: RESTORPSADDR(psaddr, savepsaddr); ! 547: } ! 548: ! 549: psrfnext(psp, psaddr) ! 550: register struct ps *psp; ! 551: register struct psdevice *psaddr; ! 552: { ! 553: u_short start, last; ! 554: ! 555: if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs) { ! 556: psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++], ! 557: 0, psp, psaddr); ! 558: return (1); ! 559: } ! 560: if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs && ! 561: psp->ps_dbuffer.state == ON_DB) { ! 562: start = psp->ps_dbuffer.dbaddrs[psp->ps_dbuffer.rbuffer]; ! 563: last = start+psp->ps_dbuffer.dbsize; ! 564: psrfstart(start, last, psp, psaddr); ! 565: psp->ps_refresh.srcntr++; /* flag for after dbuffer */ ! 566: return (1); ! 567: } ! 568: return (0); ! 569: } ! 570: ! 571: psrfstart(dfaddr, last, psp, psaddr) ! 572: u_short dfaddr, last; ! 573: register struct ps *psp; ! 574: register struct psdevice *psaddr; ! 575: { ! 576: short dummy; ! 577: ! 578: PSWAIT(psaddr); psaddr->ps_addr = RFASA; ! 579: PSWAIT(psaddr); psaddr->ps_data = dfaddr; ! 580: PSWAIT(psaddr); ! 581: if (last != 0) ! 582: psaddr->ps_data = last; ! 583: else ! 584: dummy = psaddr->ps_data;/* just access to get to status reg */ ! 585: PSWAIT(psaddr); psaddr->ps_data = RFSTART; /* may want | here */ ! 586: psp->ps_refresh.mode = RUNNING_RF; ! 587: } ! 588: ! 589: /*ARGSUSED*/ ! 590: psrfstop(psaddr, psp) ! 591: register struct psdevice *psaddr; ! 592: register struct ps *psp; ! 593: { ! 594: ! 595: PSWAIT(psaddr); psaddr->ps_addr = RFSR; ! 596: PSWAIT(psaddr); psaddr->ps_data = 0; ! 597: } ! 598: ! 599: psdbswitch(psp, psaddr) ! 600: register struct ps *psp; ! 601: register struct psdevice *psaddr; ! 602: { ! 603: ! 604: psp->ps_dbuffer.rbuffer = !psp->ps_dbuffer.rbuffer; ! 605: pssetmapbounds(psp, psaddr); ! 606: (void) psmapnext(psp, psaddr); ! 607: } ! 608: ! 609: psmapnext(psp, psaddr) ! 610: register struct ps *psp; ! 611: register struct psdevice *psaddr; ! 612: { ! 613: ! 614: if (psp->ps_map.mcntr < psp->ps_map.nmaddrs) { ! 615: psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++], ! 616: psp, psaddr); ! 617: return (1); ! 618: } ! 619: return (0); ! 620: } ! 621: ! 622: pssetmapbounds(psp, psaddr) ! 623: register struct ps *psp; ! 624: register struct psdevice *psaddr; ! 625: { ! 626: u_short start, last; ! 627: ! 628: PSWAIT(psaddr); psaddr->ps_addr = MAOL; ! 629: PSWAIT(psaddr); ! 630: if (psp->ps_dbuffer.state == ON_DB) { ! 631: start = psp->ps_dbuffer.dbaddrs[!psp->ps_dbuffer.rbuffer]; ! 632: last = start+psp->ps_dbuffer.dbsize-2; /* 2 for halt cmd */ ! 633: psaddr->ps_data = last; ! 634: PSWAIT(psaddr); psaddr->ps_data = start; ! 635: } else { ! 636: start = psaddr->ps_data; /* dummy: don't update limit */ ! 637: PSWAIT(psaddr); psaddr->ps_data = psp->ps_map.outputstart; ! 638: } ! 639: } ! 640: ! 641: psmapstart(dfaddr, psp, psaddr) ! 642: u_short dfaddr; ! 643: register struct ps *psp; ! 644: register struct psdevice *psaddr; ! 645: { ! 646: ! 647: PSWAIT(psaddr); psaddr->ps_addr = MAIA; ! 648: PSWAIT(psaddr); psaddr->ps_data = dfaddr; ! 649: PSWAIT(psaddr); psaddr->ps_data = MAO|MAI; /* may want more here */ ! 650: psp->ps_map.mode = RUNNING_MAP; ! 651: } ! 652: ! 653: int pskillcnt = 1; ! 654: ! 655: psmapstop(psaddr, psp, request) ! 656: register struct psdevice *psaddr; ! 657: register struct ps *psp; ! 658: short request; ! 659: { ! 660: register int i; ! 661: ! 662: request &= HALT_REQ|MOSTOP_REQ; /* overkill?? */ ! 663: for (i = 0; i < pskillcnt; i++) { ! 664: PSWAIT(psaddr); psaddr->ps_addr = MASR; ! 665: PSWAIT(psaddr); psaddr->ps_data = IOUT; /* zero MAI & MAO */ ! 666: PSWAIT(psaddr); psaddr->ps_addr = MAIA; ! 667: PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 input addr reg */ ! 668: PSWAIT(psaddr); psaddr->ps_addr = MAOA; ! 669: PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 output addr reg */ ! 670: PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; ! 671: PSWAIT(psaddr); psaddr->ps_data = request; ! 672: } ! 673: psp->ps_map.mode = STOPPED_MAP; ! 674: } ! 675: ! 676: /*ARGSUSED*/ ! 677: psdeviceintr(dev) ! 678: dev_t dev; ! 679: { ! 680: ! 681: printf("ps device intr\n"); ! 682: } ! 683: ! 684: /*ARGSUSED*/ ! 685: psdmaintr(dev) ! 686: dev_t dev; ! 687: { ! 688: ! 689: printf("ps dma intr\n"); ! 690: } ! 691: ! 692: /*ARGSUSED*/ ! 693: psreset(uban) ! 694: int uban; ! 695: { ! 696: ! 697: } ! 698: ! 699: /*ARGSUSED*/ ! 700: psextsync(PC, PS) ! 701: { ! 702: register int n; ! 703: register struct psdevice *psaddr; ! 704: register struct ps *psp; ! 705: register int savepsaddr; ! 706: ! 707: #ifdef EXTERNAL_SYNC ! 708: for (psp = ps, n = 0; n < NPS; psp++, n++) { ! 709: if (!psp->ps_open) ! 710: continue; ! 711: if (psp->ps_refresh.mode == SYNCING_RF && ! 712: psp->ps_refresh.state != TIME_RF) { ! 713: psaddr = (struct psdevice *)psdinfo[n]->ui_addr; ! 714: SAVEPSADDR(psaddr, savepsaddr); ! 715: (void) psrfnext(psp, psaddr); ! 716: RESTORPSADDR(psaddr, savepsaddr); ! 717: } else { ! 718: psp->ps_clockticks++; ! 719: psp->ps_clockmiss++; ! 720: } ! 721: } ! 722: #endif ! 723: } ! 724: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.