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