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