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