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