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