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