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 620