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