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