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