1 /* 2 * Copyright (c) 1992 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)pm.c 7.4 (Berkeley) 03/15/92 11 * 12 * devGraphics.c -- 13 * 14 * This file contains machine-dependent routines for the graphics device. 15 * 16 * Copyright (C) 1989 Digital Equipment Corporation. 17 * Permission to use, copy, modify, and distribute this software and 18 * its documentation for any purpose and without fee is hereby granted, 19 * provided that the above copyright notice appears in all copies. 20 * Digital Equipment Corporation makes no representations about the 21 * suitability of this software for any purpose. It is provided "as is" 22 * without express or implied warranty. 23 * 24 * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c, 25 * v 9.2 90/02/13 22:16:24 shirriff Exp $ SPRITE (DECWRL)"; 26 */ 27 28 #include "pm.h" 29 #if NPM > 0 30 31 #include "param.h" 32 #include "time.h" 33 #include "kernel.h" 34 #include "ioctl.h" 35 #include "file.h" 36 #include "errno.h" 37 #include "proc.h" 38 #include "mman.h" 39 #include "vm/vm.h" 40 41 #include "machine/machConst.h" 42 #include "machine/machMon.h" 43 #include "machine/dc7085cons.h" 44 #include "machine/pmioctl.h" 45 46 #include "device.h" 47 #include "pmreg.h" 48 #include "font.c" 49 50 #define MAX_ROW 56 51 #define MAX_COL 80 52 53 /* 54 * Macro to translate from a time struct to milliseconds. 55 */ 56 #define TO_MS(tv) ((tv.tv_sec * 1000) + (tv.tv_usec / 1000)) 57 58 static u_short curReg; /* copy of PCCRegs.cmdr since it's read only */ 59 static int isMono; /* true if B&W frame buffer */ 60 static int initialized; /* true if 'probe' was successful */ 61 static int GraphicsOpen; /* true if the graphics device is open */ 62 static int row, col; /* row and col for console cursor */ 63 static struct selinfo pm_selp;/* process waiting for select */ 64 65 /* 66 * These need to be mapped into user space. 67 */ 68 static struct pmuaccess { 69 PM_Info scrInfo; 70 pmEvent events[PM_MAXEVQ]; 71 pmTimeCoord tcs[MOTION_BUFFER_SIZE]; 72 } pmu; 73 74 /* 75 * Font mask bits used by Blitc(). 76 */ 77 static unsigned int fontmaskBits[16] = { 78 0x00000000, 79 0x00000001, 80 0x00000100, 81 0x00000101, 82 0x00010000, 83 0x00010001, 84 0x00010100, 85 0x00010101, 86 0x01000000, 87 0x01000001, 88 0x01000100, 89 0x01000101, 90 0x01010000, 91 0x01010001, 92 0x01010100, 93 0x01010101 94 }; 95 96 /* 97 * Forward references. 98 */ 99 static void Scroll(); 100 static void Blitc(); 101 102 static void ScreenInit(); 103 static void LoadCursor(); 104 static void RestoreCursorColor(); 105 static void CursorColor(); 106 static void PosCursor(); 107 static void InitColorMap(); 108 static void VDACInit(); 109 static void LoadColorMap(); 110 static void EnableVideo(); 111 static void DisableVideo(); 112 113 extern void dcKBDPutc(); 114 extern void (*dcDivertXInput)(); 115 extern void (*dcMouseEvent)(); 116 extern void (*dcMouseButtons)(); 117 118 int pmprobe(); 119 struct driver pmdriver = { 120 "pm", pmprobe, 0, 0, 121 }; 122 123 /* 124 * Test to see if device is present. 125 * Return true if found and initialized ok. 126 */ 127 /*ARGSUSED*/ 128 pmprobe(cp) 129 register struct pmax_ctlr *cp; 130 { 131 132 if (!initialized && !pminit()) 133 return (0); 134 if (isMono) 135 printf("pm0 (monochrome display)\n"); 136 else 137 printf("pm0 (color display)\n"); 138 return (1); 139 } 140 141 /* 142 *---------------------------------------------------------------------- 143 * 144 * pmKbdEvent -- 145 * 146 * Process a received character. 147 * 148 * Results: 149 * None. 150 * 151 * Side effects: 152 * Events added to the queue. 153 * 154 *---------------------------------------------------------------------- 155 */ 156 void 157 pmKbdEvent(ch) 158 int ch; 159 { 160 register pmEvent *eventPtr; 161 int i; 162 163 if (!GraphicsOpen) 164 return; 165 166 /* 167 * See if there is room in the queue. 168 */ 169 i = PM_EVROUND(pmu.scrInfo.qe.eTail + 1); 170 if (i == pmu.scrInfo.qe.eHead) 171 return; 172 173 /* 174 * Add the event to the queue. 175 */ 176 eventPtr = &pmu.events[pmu.scrInfo.qe.eTail]; 177 eventPtr->type = BUTTON_RAW_TYPE; 178 eventPtr->device = KEYBOARD_DEVICE; 179 eventPtr->x = pmu.scrInfo.mouse.x; 180 eventPtr->y = pmu.scrInfo.mouse.y; 181 eventPtr->time = TO_MS(time); 182 eventPtr->key = ch; 183 pmu.scrInfo.qe.eTail = i; 184 selwakeup(&pm_selp); 185 } 186 187 /* 188 *---------------------------------------------------------------------- 189 * 190 * pmMouseEvent -- 191 * 192 * Process a mouse event. 193 * 194 * Results: 195 * None. 196 * 197 * Side effects: 198 * An event is added to the event queue. 199 * 200 *---------------------------------------------------------------------- 201 */ 202 void 203 pmMouseEvent(newRepPtr) 204 register MouseReport *newRepPtr; 205 { 206 unsigned milliSec; 207 int i; 208 pmEvent *eventPtr; 209 210 if (!GraphicsOpen) 211 return; 212 213 milliSec = TO_MS(time); 214 215 /* 216 * Check to see if we have to accelerate the mouse 217 */ 218 if (pmu.scrInfo.mscale >= 0) { 219 if (newRepPtr->dx >= pmu.scrInfo.mthreshold) { 220 newRepPtr->dx += 221 (newRepPtr->dx - pmu.scrInfo.mthreshold) * 222 pmu.scrInfo.mscale; 223 } 224 if (newRepPtr->dy >= pmu.scrInfo.mthreshold) { 225 newRepPtr->dy += 226 (newRepPtr->dy - pmu.scrInfo.mthreshold) * 227 pmu.scrInfo.mscale; 228 } 229 } 230 231 /* 232 * Update mouse position 233 */ 234 if (newRepPtr->state & MOUSE_X_SIGN) { 235 pmu.scrInfo.mouse.x += newRepPtr->dx; 236 if (pmu.scrInfo.mouse.x > pmu.scrInfo.max_cur_x) 237 pmu.scrInfo.mouse.x = pmu.scrInfo.max_cur_x; 238 } else { 239 pmu.scrInfo.mouse.x -= newRepPtr->dx; 240 if (pmu.scrInfo.mouse.x < pmu.scrInfo.min_cur_x) 241 pmu.scrInfo.mouse.x = pmu.scrInfo.min_cur_x; 242 } 243 if (newRepPtr->state & MOUSE_Y_SIGN) { 244 pmu.scrInfo.mouse.y -= newRepPtr->dy; 245 if (pmu.scrInfo.mouse.y < pmu.scrInfo.min_cur_y) 246 pmu.scrInfo.mouse.y = pmu.scrInfo.min_cur_y; 247 } else { 248 pmu.scrInfo.mouse.y += newRepPtr->dy; 249 if (pmu.scrInfo.mouse.y > pmu.scrInfo.max_cur_y) 250 pmu.scrInfo.mouse.y = pmu.scrInfo.max_cur_y; 251 } 252 253 /* 254 * Move the hardware cursor. 255 */ 256 PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y); 257 258 /* 259 * Store the motion event in the motion buffer. 260 */ 261 pmu.tcs[pmu.scrInfo.qe.tcNext].time = milliSec; 262 pmu.tcs[pmu.scrInfo.qe.tcNext].x = pmu.scrInfo.mouse.x; 263 pmu.tcs[pmu.scrInfo.qe.tcNext].y = pmu.scrInfo.mouse.y; 264 if (++pmu.scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE) 265 pmu.scrInfo.qe.tcNext = 0; 266 if (pmu.scrInfo.mouse.y < pmu.scrInfo.mbox.bottom && 267 pmu.scrInfo.mouse.y >= pmu.scrInfo.mbox.top && 268 pmu.scrInfo.mouse.x < pmu.scrInfo.mbox.right && 269 pmu.scrInfo.mouse.x >= pmu.scrInfo.mbox.left) 270 return; 271 272 pmu.scrInfo.mbox.bottom = 0; 273 if (PM_EVROUND(pmu.scrInfo.qe.eTail + 1) == pmu.scrInfo.qe.eHead) 274 return; 275 276 i = PM_EVROUND(pmu.scrInfo.qe.eTail - 1); 277 if ((pmu.scrInfo.qe.eTail != pmu.scrInfo.qe.eHead) && 278 (i != pmu.scrInfo.qe.eHead)) { 279 pmEvent *eventPtr; 280 281 eventPtr = &pmu.events[i]; 282 if (eventPtr->type == MOTION_TYPE) { 283 eventPtr->x = pmu.scrInfo.mouse.x; 284 eventPtr->y = pmu.scrInfo.mouse.y; 285 eventPtr->time = milliSec; 286 eventPtr->device = MOUSE_DEVICE; 287 return; 288 } 289 } 290 /* 291 * Put event into queue and wakeup any waiters. 292 */ 293 eventPtr = &pmu.events[pmu.scrInfo.qe.eTail]; 294 eventPtr->type = MOTION_TYPE; 295 eventPtr->time = milliSec; 296 eventPtr->x = pmu.scrInfo.mouse.x; 297 eventPtr->y = pmu.scrInfo.mouse.y; 298 eventPtr->device = MOUSE_DEVICE; 299 pmu.scrInfo.qe.eTail = PM_EVROUND(pmu.scrInfo.qe.eTail + 1); 300 selwakeup(&pm_selp); 301 } 302 303 /* 304 *---------------------------------------------------------------------- 305 * 306 * pmMouseButtons -- 307 * 308 * Process mouse buttons. 309 * 310 * Results: 311 * None. 312 * 313 * Side effects: 314 * None. 315 * 316 *---------------------------------------------------------------------- 317 */ 318 void 319 pmMouseButtons(newRepPtr) 320 MouseReport *newRepPtr; 321 { 322 static char temp, oldSwitch, newSwitch; 323 int i, j; 324 pmEvent *eventPtr; 325 static MouseReport lastRep; 326 327 if (!GraphicsOpen) 328 return; 329 330 newSwitch = newRepPtr->state & 0x07; 331 oldSwitch = lastRep.state & 0x07; 332 333 temp = oldSwitch ^ newSwitch; 334 if (temp == 0) 335 return; 336 for (j = 1; j < 8; j <<= 1) { 337 if ((j & temp) == 0) 338 continue; 339 340 /* 341 * Check for room in the queue 342 */ 343 i = PM_EVROUND(pmu.scrInfo.qe.eTail+1); 344 if (i == pmu.scrInfo.qe.eHead) 345 return; 346 347 /* 348 * Put event into queue. 349 */ 350 eventPtr = &pmu.events[pmu.scrInfo.qe.eTail]; 351 352 switch (j) { 353 case RIGHT_BUTTON: 354 eventPtr->key = EVENT_RIGHT_BUTTON; 355 break; 356 357 case MIDDLE_BUTTON: 358 eventPtr->key = EVENT_MIDDLE_BUTTON; 359 break; 360 361 case LEFT_BUTTON: 362 eventPtr->key = EVENT_LEFT_BUTTON; 363 } 364 if (newSwitch & j) 365 eventPtr->type = BUTTON_DOWN_TYPE; 366 else 367 eventPtr->type = BUTTON_UP_TYPE; 368 eventPtr->device = MOUSE_DEVICE; 369 370 eventPtr->time = TO_MS(time); 371 eventPtr->x = pmu.scrInfo.mouse.x; 372 eventPtr->y = pmu.scrInfo.mouse.y; 373 } 374 pmu.scrInfo.qe.eTail = i; 375 selwakeup(&pm_selp); 376 377 lastRep = *newRepPtr; 378 pmu.scrInfo.mswitches = newSwitch; 379 } 380 381 /* 382 *---------------------------------------------------------------------- 383 * 384 * Scroll -- 385 * 386 * Scroll the screen. 387 * 388 * Results: 389 * None. 390 * 391 * Side effects: 392 * None. 393 * 394 *---------------------------------------------------------------------- 395 */ 396 static void 397 Scroll() 398 { 399 register int *dest, *src; 400 register int *end; 401 register int temp0, temp1, temp2, temp3; 402 register int i, scanInc, lineCount; 403 int line; 404 405 /* 406 * If the mouse is on we don't scroll so that the bit map remains sane. 407 */ 408 if (GraphicsOpen) { 409 row = 0; 410 return; 411 } 412 413 /* 414 * The following is an optimization to cause the scrolling 415 * of text to be memory limited. Basically the writebuffer is 416 * 4 words (32 bits ea.) long so to achieve maximum speed we 417 * read and write in multiples of 4 words. We also limit the 418 * size to be MAX_COL characters for more speed. 419 */ 420 if (isMono) { 421 lineCount = 5; 422 line = 1920 * 2; 423 scanInc = 44; 424 } else { 425 lineCount = 40; 426 scanInc = 96; 427 line = 1920 * 8; 428 } 429 src = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR + line); 430 dest = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR); 431 end = (int *)(MACH_UNCACHED_FRAME_BUFFER_ADDR + (60 * line) - line); 432 do { 433 i = 0; 434 do { 435 temp0 = src[0]; 436 temp1 = src[1]; 437 temp2 = src[2]; 438 temp3 = src[3]; 439 dest[0] = temp0; 440 dest[1] = temp1; 441 dest[2] = temp2; 442 dest[3] = temp3; 443 dest += 4; 444 src += 4; 445 i++; 446 } while (i < lineCount); 447 src += scanInc; 448 dest += scanInc; 449 } while (src < end); 450 451 /* 452 * Now zero out the last two lines 453 */ 454 bzero(MACH_UNCACHED_FRAME_BUFFER_ADDR + (row * line), 3 * line); 455 } 456 457 /* 458 *---------------------------------------------------------------------- 459 * 460 * pmPutc -- 461 * 462 * Write a character to the console. 463 * 464 * Results: 465 * None. 466 * 467 * Side effects: 468 * None. 469 * 470 *---------------------------------------------------------------------- 471 */ 472 pmPutc(c) 473 register int c; 474 { 475 int s; 476 477 s = splhigh(); /* in case we do any printf's at interrupt time */ 478 if (initialized) { 479 #ifdef DEBUG 480 /* 481 * If the HELP key is pressed, wait for another 482 * HELP key press to start/stop output. 483 */ 484 if (dcDebugGetc() == LK_HELP) { 485 while (dcDebugGetc() != LK_HELP) 486 ; 487 } 488 #endif 489 Blitc(c); 490 } else { 491 void (*f)() = (void (*)())MACH_MON_PUTCHAR; 492 493 (*f)(c); 494 } 495 splx(s); 496 } 497 498 /* 499 *---------------------------------------------------------------------- 500 * 501 * Blitc -- 502 * 503 * Write a character to the screen. 504 * 505 * Results: 506 * None. 507 * 508 * Side effects: 509 * None. 510 * 511 *---------------------------------------------------------------------- 512 */ 513 static void 514 Blitc(c) 515 register int c; 516 { 517 register char *bRow, *fRow; 518 register int i; 519 register int ote = isMono ? 256 : 1024; /* offset to table entry */ 520 int colMult = isMono ? 1 : 8; 521 522 c &= 0xff; 523 524 switch (c) { 525 case '\t': 526 for (i = 8 - (col & 0x7); i > 0; i--) 527 Blitc(' '); 528 break; 529 530 case '\r': 531 col = 0; 532 break; 533 534 case '\b': 535 col--; 536 if (col < 0) 537 col = 0; 538 break; 539 540 case '\n': 541 if (row + 1 >= MAX_ROW) 542 Scroll(); 543 else 544 row++; 545 col = 0; 546 break; 547 548 case '\007': 549 dcKBDPutc(LK_RING_BELL); 550 break; 551 552 default: 553 /* 554 * 0xA1 to 0xFD are the printable characters added with 8-bit 555 * support. 556 */ 557 if (c < ' ' || c > '~' && c < 0xA1 || c > 0xFD) 558 break; 559 /* 560 * If the next character will wrap around then 561 * increment row counter or scroll screen. 562 */ 563 if (col >= MAX_COL) { 564 col = 0; 565 if (row + 1 >= MAX_ROW) 566 Scroll(); 567 else 568 row++; 569 } 570 bRow = (char *)(MACH_UNCACHED_FRAME_BUFFER_ADDR + 571 (row * 15 & 0x3ff) * ote + col * colMult); 572 i = c - ' '; 573 /* 574 * This is to skip the (32) 8-bit 575 * control chars, as well as DEL 576 * and 0xA0 which aren't printable 577 */ 578 if (c > '~') 579 i -= 34; 580 i *= 15; 581 fRow = (char *)((int)pmFont + i); 582 583 /* inline expansion for speed */ 584 if (isMono) { 585 *bRow = *fRow++; bRow += ote; 586 *bRow = *fRow++; bRow += ote; 587 *bRow = *fRow++; bRow += ote; 588 *bRow = *fRow++; bRow += ote; 589 *bRow = *fRow++; bRow += ote; 590 *bRow = *fRow++; bRow += ote; 591 *bRow = *fRow++; bRow += ote; 592 *bRow = *fRow++; bRow += ote; 593 *bRow = *fRow++; bRow += ote; 594 *bRow = *fRow++; bRow += ote; 595 *bRow = *fRow++; bRow += ote; 596 *bRow = *fRow++; bRow += ote; 597 *bRow = *fRow++; bRow += ote; 598 *bRow = *fRow++; bRow += ote; 599 *bRow = *fRow++; bRow += ote; 600 } else { 601 register int j; 602 register unsigned int *pInt; 603 604 pInt = (unsigned int *)bRow; 605 for (j = 0; j < 15; j++) { 606 /* 607 * fontmaskBits converts a nibble 608 * (4 bytes) to a long word 609 * containing 4 pixels corresponding 610 * to each bit in the nibble. Thus 611 * we write two longwords for each 612 * byte in font. 613 * 614 * Remember the font is 8 bits wide 615 * and 15 bits high. 616 * 617 * We add 256 to the pointer to 618 * point to the pixel on the 619 * next scan line 620 * directly below the current 621 * pixel. 622 */ 623 pInt[0] = fontmaskBits[(*fRow) & 0xf]; 624 pInt[1] = fontmaskBits[((*fRow) >> 4) & 0xf]; 625 fRow++; 626 pInt += 256; 627 } 628 } 629 col++; /* increment column counter */ 630 } 631 if (!GraphicsOpen) 632 PosCursor(col * 8, row * 15); 633 } 634 635 /*ARGSUSED*/ 636 pmopen(dev, flag) 637 dev_t dev; 638 int flag; 639 { 640 641 if (!initialized) 642 return (ENXIO); 643 if (GraphicsOpen) 644 return (EBUSY); 645 646 GraphicsOpen = 1; 647 if (!isMono) 648 InitColorMap(); 649 /* 650 * Set up event queue for later 651 */ 652 pmu.scrInfo.qe.eSize = PM_MAXEVQ; 653 pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0; 654 pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE; 655 pmu.scrInfo.qe.tcNext = 0; 656 pmu.scrInfo.qe.timestamp_ms = TO_MS(time); 657 return (0); 658 } 659 660 /*ARGSUSED*/ 661 pmclose(dev, flag) 662 dev_t dev; 663 int flag; 664 { 665 int s; 666 667 if (!GraphicsOpen) 668 return (EBADF); 669 670 GraphicsOpen = 0; 671 if (!isMono) 672 InitColorMap(); 673 s = spltty(); 674 dcDivertXInput = (void (*)())0; 675 dcMouseEvent = (void (*)())0; 676 dcMouseButtons = (void (*)())0; 677 splx(s); 678 ScreenInit(); 679 vmUserUnmap(); 680 bzero((caddr_t)MACH_UNCACHED_FRAME_BUFFER_ADDR, 681 (isMono ? 1024 / 8 : 1024) * 864); 682 PosCursor(col * 8, row * 15); 683 return (0); 684 } 685 686 /*ARGSUSED*/ 687 pmioctl(dev, cmd, data, flag) 688 dev_t dev; 689 caddr_t data; 690 { 691 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR; 692 int s; 693 694 switch (cmd) { 695 case QIOCGINFO: 696 { 697 caddr_t addr; 698 extern caddr_t vmUserMap(); 699 700 /* 701 * Map the all the data the user needs access to into 702 * user space. 703 */ 704 addr = vmUserMap(sizeof(pmu), (unsigned)&pmu); 705 if (addr == (caddr_t)0) 706 goto mapError; 707 *(PM_Info **)data = &((struct pmuaccess *)addr)->scrInfo; 708 pmu.scrInfo.qe.events = ((struct pmuaccess *)addr)->events; 709 pmu.scrInfo.qe.tcs = ((struct pmuaccess *)addr)->tcs; 710 /* 711 * Map the plane mask into the user's address space. 712 */ 713 addr = vmUserMap(4, (unsigned)MACH_PLANE_MASK_ADDR); 714 if (addr == (caddr_t)0) 715 goto mapError; 716 pmu.scrInfo.planemask = (char *)addr; 717 /* 718 * Map the frame buffer into the user's address space. 719 */ 720 addr = vmUserMap(isMono ? 256*1024 : 1024*1024, 721 (unsigned)MACH_UNCACHED_FRAME_BUFFER_ADDR); 722 if (addr == (caddr_t)0) 723 goto mapError; 724 pmu.scrInfo.bitmap = (char *)addr; 725 break; 726 727 mapError: 728 vmUserUnmap(); 729 printf("Cannot map shared data structures\n"); 730 return (EIO); 731 } 732 733 case QIOCPMSTATE: 734 /* 735 * Set mouse state. 736 */ 737 pmu.scrInfo.mouse = *(pmCursor *)data; 738 PosCursor(pmu.scrInfo.mouse.x, pmu.scrInfo.mouse.y); 739 break; 740 741 case QIOCINIT: 742 /* 743 * Initialize the screen. 744 */ 745 ScreenInit(); 746 break; 747 748 case QIOCKPCMD: 749 { 750 pmKpCmd *kpCmdPtr; 751 unsigned char *cp; 752 753 kpCmdPtr = (pmKpCmd *)data; 754 if (kpCmdPtr->nbytes == 0) 755 kpCmdPtr->cmd |= 0x80; 756 if (!GraphicsOpen) 757 kpCmdPtr->cmd |= 1; 758 dcKBDPutc((int)kpCmdPtr->cmd); 759 cp = &kpCmdPtr->par[0]; 760 for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) { 761 if (kpCmdPtr->nbytes == 1) 762 *cp |= 0x80; 763 dcKBDPutc((int)*cp); 764 } 765 break; 766 } 767 768 case QIOCADDR: 769 *(PM_Info **)data = &pmu.scrInfo; 770 break; 771 772 case QIOWCURSOR: 773 LoadCursor((unsigned short *)data); 774 break; 775 776 case QIOWCURSORCOLOR: 777 CursorColor((unsigned int *)data); 778 break; 779 780 case QIOSETCMAP: 781 LoadColorMap((ColorMap *)data); 782 break; 783 784 case QIOKERNLOOP: 785 s = spltty(); 786 dcDivertXInput = pmKbdEvent; 787 dcMouseEvent = pmMouseEvent; 788 dcMouseButtons = pmMouseButtons; 789 splx(s); 790 break; 791 792 case QIOKERNUNLOOP: 793 s = spltty(); 794 dcDivertXInput = (void (*)())0; 795 dcMouseEvent = (void (*)())0; 796 dcMouseButtons = (void (*)())0; 797 splx(s); 798 break; 799 800 case QIOVIDEOON: 801 if (!isMono) 802 RestoreCursorColor(); 803 curReg |= PCC_ENPA; 804 curReg &= ~PCC_FOPB; 805 pcc->cmdr = curReg; 806 break; 807 808 case QIOVIDEOOFF: 809 if (!isMono) 810 VDACInit(); 811 curReg |= PCC_FOPB; 812 curReg &= ~PCC_ENPA; 813 pcc->cmdr = curReg; 814 break; 815 816 default: 817 printf("pm0: Unknown ioctl command %x\n", cmd); 818 return (EINVAL); 819 } 820 return (0); 821 } 822 823 pmselect(dev, flag, p) 824 dev_t dev; 825 int flag; 826 struct proc *p; 827 { 828 829 switch (flag) { 830 case FREAD: 831 if (pmu.scrInfo.qe.eHead != pmu.scrInfo.qe.eTail) 832 return (1); 833 selrecord(p, &pm_selp); 834 break; 835 } 836 837 return (0); 838 } 839 840 static u_char bg_RGB[3]; /* background color for the cursor */ 841 static u_char fg_RGB[3]; /* foreground color for the cursor */ 842 843 /* 844 * The default cursor. 845 */ 846 unsigned short defCursor[32] = { 847 /* plane A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 848 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 849 /* plane B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 850 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF 851 852 }; 853 854 /* 855 * Test to see if device is present. 856 * Return true if found and initialized ok. 857 */ 858 pminit() 859 { 860 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR; 861 862 isMono = *(u_short *)MACH_SYS_CSR_ADDR & MACH_CSR_MONO; 863 if (isMono) { 864 /* check for no frame buffer */ 865 if (badaddr((char *)MACH_UNCACHED_FRAME_BUFFER_ADDR, 4)) 866 return (0); 867 } 868 869 /* 870 * Initialize the screen. 871 */ 872 pcc->cmdr = PCC_FOPB | PCC_VBHI; 873 874 /* 875 * Initialize the cursor register. 876 */ 877 pcc->cmdr = curReg = PCC_ENPA | PCC_ENPB; 878 879 /* 880 * Initialize screen info. 881 */ 882 pmu.scrInfo.max_row = 56; 883 pmu.scrInfo.max_col = 80; 884 pmu.scrInfo.max_x = 1024; 885 pmu.scrInfo.max_y = 864; 886 pmu.scrInfo.max_cur_x = 1023; 887 pmu.scrInfo.max_cur_y = 863; 888 pmu.scrInfo.version = 11; 889 pmu.scrInfo.mthreshold = 4; 890 pmu.scrInfo.mscale = 2; 891 pmu.scrInfo.min_cur_x = -15; 892 pmu.scrInfo.min_cur_y = -15; 893 pmu.scrInfo.qe.timestamp_ms = TO_MS(time); 894 pmu.scrInfo.qe.eSize = PM_MAXEVQ; 895 pmu.scrInfo.qe.eHead = pmu.scrInfo.qe.eTail = 0; 896 pmu.scrInfo.qe.tcSize = MOTION_BUFFER_SIZE; 897 pmu.scrInfo.qe.tcNext = 0; 898 899 /* 900 * Initialize the color map, the screen, and the mouse. 901 */ 902 InitColorMap(); 903 ScreenInit(); 904 Scroll(); 905 906 initialized = 1; 907 return (1); 908 } 909 910 /* 911 * ---------------------------------------------------------------------------- 912 * 913 * ScreenInit -- 914 * 915 * Initialize the screen. 916 * 917 * Results: 918 * None. 919 * 920 * Side effects: 921 * The screen is initialized. 922 * 923 * ---------------------------------------------------------------------------- 924 */ 925 static void 926 ScreenInit() 927 { 928 929 /* 930 * Home the cursor. 931 * We want an LSI terminal emulation. We want the graphics 932 * terminal to scroll from the bottom. So start at the bottom. 933 */ 934 row = 55; 935 col = 0; 936 937 /* 938 * Load the cursor with the default values 939 * 940 */ 941 LoadCursor(defCursor); 942 } 943 944 /* 945 * ---------------------------------------------------------------------------- 946 * 947 * LoadCursor -- 948 * 949 * Routine to load the cursor Sprite pattern. 950 * 951 * Results: 952 * None. 953 * 954 * Side effects: 955 * The cursor is loaded into the hardware cursor. 956 * 957 * ---------------------------------------------------------------------------- 958 */ 959 static void 960 LoadCursor(cur) 961 unsigned short *cur; 962 { 963 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR; 964 register int i; 965 966 curReg |= PCC_LODSA; 967 pcc->cmdr = curReg; 968 for (i = 0; i < 32; i++) { 969 pcc->memory = cur[i]; 970 MachEmptyWriteBuffer(); 971 } 972 curReg &= ~PCC_LODSA; 973 pcc->cmdr = curReg; 974 } 975 976 /* 977 * ---------------------------------------------------------------------------- 978 * 979 * RestoreCursorColor -- 980 * 981 * Routine to restore the color of the cursor. 982 * 983 * Results: 984 * None. 985 * 986 * Side effects: 987 * None. 988 * 989 * ---------------------------------------------------------------------------- 990 */ 991 static void 992 RestoreCursorColor() 993 { 994 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR; 995 register int i; 996 997 vdac->overWA = 0x04; 998 MachEmptyWriteBuffer(); 999 for (i = 0; i < 3; i++) { 1000 vdac->over = bg_RGB[i]; 1001 MachEmptyWriteBuffer(); 1002 } 1003 1004 vdac->overWA = 0x08; 1005 MachEmptyWriteBuffer(); 1006 vdac->over = 0x00; 1007 MachEmptyWriteBuffer(); 1008 vdac->over = 0x00; 1009 MachEmptyWriteBuffer(); 1010 vdac->over = 0x7f; 1011 MachEmptyWriteBuffer(); 1012 1013 vdac->overWA = 0x0c; 1014 MachEmptyWriteBuffer(); 1015 for (i = 0; i < 3; i++) { 1016 vdac->over = fg_RGB[i]; 1017 MachEmptyWriteBuffer(); 1018 } 1019 } 1020 1021 /* 1022 * ---------------------------------------------------------------------------- 1023 * 1024 * CursorColor -- 1025 * 1026 * Set the color of the cursor. 1027 * 1028 * Results: 1029 * None. 1030 * 1031 * Side effects: 1032 * None. 1033 * 1034 * ---------------------------------------------------------------------------- 1035 */ 1036 static void 1037 CursorColor(color) 1038 unsigned int color[]; 1039 { 1040 register int i, j; 1041 1042 for (i = 0; i < 3; i++) 1043 bg_RGB[i] = (u_char)(color[i] >> 8); 1044 1045 for (i = 3, j = 0; i < 6; i++, j++) 1046 fg_RGB[j] = (u_char)(color[i] >> 8); 1047 1048 RestoreCursorColor(); 1049 } 1050 1051 /* 1052 * ---------------------------------------------------------------------------- 1053 * 1054 * InitColorMap -- 1055 * 1056 * Initialize the color map. 1057 * 1058 * Results: 1059 * None. 1060 * 1061 * Side effects: 1062 * The colormap is initialized appropriately whether it is color or 1063 * monochrome. 1064 * 1065 * ---------------------------------------------------------------------------- 1066 */ 1067 static void 1068 InitColorMap() 1069 { 1070 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR; 1071 register int i; 1072 1073 *(char *)MACH_PLANE_MASK_ADDR = 0xff; 1074 MachEmptyWriteBuffer(); 1075 1076 if (isMono) { 1077 vdac->mapWA = 0; MachEmptyWriteBuffer(); 1078 for (i = 0; i < 256; i++) { 1079 vdac->map = (i < 128) ? 0x00 : 0xff; 1080 MachEmptyWriteBuffer(); 1081 vdac->map = (i < 128) ? 0x00 : 0xff; 1082 MachEmptyWriteBuffer(); 1083 vdac->map = (i < 128) ? 0x00 : 0xff; 1084 MachEmptyWriteBuffer(); 1085 } 1086 } else { 1087 vdac->mapWA = 0; MachEmptyWriteBuffer(); 1088 vdac->map = 0; MachEmptyWriteBuffer(); 1089 vdac->map = 0; MachEmptyWriteBuffer(); 1090 vdac->map = 0; MachEmptyWriteBuffer(); 1091 1092 for (i = 1; i < 256; i++) { 1093 vdac->map = 0xff; MachEmptyWriteBuffer(); 1094 vdac->map = 0xff; MachEmptyWriteBuffer(); 1095 vdac->map = 0xff; MachEmptyWriteBuffer(); 1096 } 1097 } 1098 1099 for (i = 0; i < 3; i++) { 1100 bg_RGB[i] = 0x00; 1101 fg_RGB[i] = 0xff; 1102 } 1103 RestoreCursorColor(); 1104 } 1105 1106 /* 1107 * ---------------------------------------------------------------------------- 1108 * 1109 * VDACInit -- 1110 * 1111 * Initialize the VDAC. 1112 * 1113 * Results: 1114 * None. 1115 * 1116 * Side effects: 1117 * None. 1118 * 1119 * ---------------------------------------------------------------------------- 1120 */ 1121 static void 1122 VDACInit() 1123 { 1124 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR; 1125 1126 /* 1127 * 1128 * Initialize the VDAC 1129 */ 1130 vdac->overWA = 0x04; MachEmptyWriteBuffer(); 1131 vdac->over = 0x00; MachEmptyWriteBuffer(); 1132 vdac->over = 0x00; MachEmptyWriteBuffer(); 1133 vdac->over = 0x00; MachEmptyWriteBuffer(); 1134 vdac->overWA = 0x08; MachEmptyWriteBuffer(); 1135 vdac->over = 0x00; MachEmptyWriteBuffer(); 1136 vdac->over = 0x00; MachEmptyWriteBuffer(); 1137 vdac->over = 0x7f; MachEmptyWriteBuffer(); 1138 vdac->overWA = 0x0c; MachEmptyWriteBuffer(); 1139 vdac->over = 0xff; MachEmptyWriteBuffer(); 1140 vdac->over = 0xff; MachEmptyWriteBuffer(); 1141 vdac->over = 0xff; MachEmptyWriteBuffer(); 1142 } 1143 1144 /* 1145 * ---------------------------------------------------------------------------- 1146 * 1147 * LoadColorMap -- 1148 * 1149 * Load the color map. 1150 * 1151 * Results: 1152 * None. 1153 * 1154 * Side effects: 1155 * The color map is loaded. 1156 * 1157 * ---------------------------------------------------------------------------- 1158 */ 1159 static void 1160 LoadColorMap(ptr) 1161 ColorMap *ptr; 1162 { 1163 register VDACRegs *vdac = (VDACRegs *)MACH_COLOR_MAP_ADDR; 1164 1165 if (ptr->index > 256) 1166 return; 1167 1168 vdac->mapWA = ptr->index; MachEmptyWriteBuffer(); 1169 vdac->map = ptr->Entry.red; MachEmptyWriteBuffer(); 1170 vdac->map = ptr->Entry.green; MachEmptyWriteBuffer(); 1171 vdac->map = ptr->Entry.blue; MachEmptyWriteBuffer(); 1172 } 1173 1174 /* 1175 *---------------------------------------------------------------------- 1176 * 1177 * PosCursor -- 1178 * 1179 * Postion the cursor. 1180 * 1181 * Results: 1182 * None. 1183 * 1184 * Side effects: 1185 * None. 1186 * 1187 *---------------------------------------------------------------------- 1188 */ 1189 static void 1190 PosCursor(x, y) 1191 register int x, y; 1192 { 1193 register PCCRegs *pcc = (PCCRegs *)MACH_CURSOR_REG_ADDR; 1194 1195 if (y < pmu.scrInfo.min_cur_y || y > pmu.scrInfo.max_cur_y) 1196 y = pmu.scrInfo.max_cur_y; 1197 if (x < pmu.scrInfo.min_cur_x || x > pmu.scrInfo.max_cur_x) 1198 x = pmu.scrInfo.max_cur_x; 1199 pmu.scrInfo.cursor.x = x; /* keep track of real cursor */ 1200 pmu.scrInfo.cursor.y = y; /* position, indep. of mouse */ 1201 pcc->xpos = PCC_X_OFFSET + x; 1202 pcc->ypos = PCC_Y_OFFSET + y; 1203 } 1204 #endif 1205