|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* Copyright (c) 1993 NeXT Computer, Inc. All rights reserved. ! 25: * ! 26: * IOSVGADisplay.m - Implements common methods for SVGA display driver class. ! 27: * ! 28: * ! 29: * HISTORY ! 30: * 07 July 93 Scott Forstall ! 31: * Created from earlier work by Joe Pasqua and Gary Crum. ! 32: */ ! 33: ! 34: #define KERNEL_PRIVATE 1 ! 35: #define DRIVER_PRIVATE 1 ! 36: ! 37: /* Notes: ! 38: * This class implements the evScreen protocol for all IOSVGADisplays. Well, ! 39: * almost. The setBrightness method doesn't do anything. Subclasses must ! 40: * override this and implement it as appropriate for the device. ! 41: * ! 42: * To find things that need to be fixed, search for FIX, to find questions ! 43: * to be resolved, search for QUESTION, to find stuff that still needs to be ! 44: * done, search for TO DO. ! 45: */ ! 46: ! 47: #import <string.h> ! 48: #import <stdlib.h> ! 49: #import <bsd/dev/i386/VGAConsole.h> ! 50: #import <stdio.h> ! 51: #import <driverkit/EventDriver.h> ! 52: #import <bsd/dev/evio.h> ! 53: #import <bsd/dev/i386/kmDevice.h> ! 54: #import <driverkit/KernBus.h> ! 55: #import <driverkit/KernBusMemory.h> ! 56: #import <driverkit/IODisplayPrivate.h> ! 57: #import <driverkit/IOSVGADisplay.h> ! 58: #import <driverkit/IOVGAShared.h> ! 59: #import <driverkit/i386/directDevice.h> ! 60: #import <driverkit/i386/driverTypes.h> ! 61: ! 62: ! 63: // ! 64: // BEGIN: Defines used in this file ! 65: // ! 66: ! 67: #define CURSOR_WIDTH_IN_PIXELS 16 ! 68: #define PPXMASK ((unsigned int)0x0000000f) ! 69: ! 70: #if (SWAPBITS == DEVICE_CONSISTENT) ! 71: #define LSHIFT >> ! 72: #define RSHIFT << ! 73: #define LSHIFTEQ >>= ! 74: #define RSHIFTEQ <<= ! 75: #else (SWAPBITS == DEVICE_CONSISTENT) ! 76: #define LSHIFT << ! 77: #define RSHIFT >> ! 78: #define LSHIFTEQ <<= ! 79: #define RSHIFTEQ >>= ! 80: #endif (SWAPBITS == DEVICE_CONSISTENT) ! 81: ! 82: #define CLEAR_SEMAPHORE(shmem) \ ! 83: ev_unlock(&shmem->cursorSema) ! 84: #define SET_SEMAPHORE(shmem) \ ! 85: if (!ev_try_lock(&shmem->cursorSema)) return self ! 86: #define RECTS_INTERSECT(one, two) \ ! 87: (((one.minx < two.maxx) && (two.minx < one.maxx)) && \ ! 88: ((one.miny < two.maxy) && (two.miny < one.maxy))) ! 89: ! 90: // ! 91: // END: Defines used in this file ! 92: // ! 93: ! 94: ! 95: @implementation IOSVGADisplay ! 96: ! 97: // ! 98: // BEGIN: Implementation of private routines for SVGA ! 99: // ! 100: ! 101: ! 102: - (VGAShmem_t *)_shmem ! 103: // Description: Return IOSVGADisplay's shared memory which is ! 104: // stored in a private instance variable. ! 105: { ! 106: return (VGAShmem_t *)_priv; ! 107: } ! 108: ! 109: ! 110: - (IOReturn)_registerWithED ! 111: // Description: Register this display device with the event driver. ! 112: // Set up and initialize the shared memory. ! 113: { ! 114: int shmem_size; ! 115: Bounds bounds; ! 116: int token; ! 117: VGAShmem_t *shmem; ! 118: ! 119: token = [[EventDriver instance] registerScreen:self ! 120: bounds:&bounds ! 121: shmem:&(self->_priv) ! 122: size:&shmem_size]; ! 123: shmem = [self _shmem]; ! 124: ! 125: if ( token == -1 ) { ! 126: return IO_R_INVALID_ARG; ! 127: } ! 128: ! 129: // We allow the shmem_size to be less than sizeof(VGAShmem_t) ! 130: // so that we need not consume the extra space that some of the ! 131: // larger cursor variants require if we are really a lower bitdepth. ! 132: if ( shmem_size > sizeof(VGAShmem_t) ) { ! 133: IOLog("%s: shmem_size > sizeof (VGAShmem_t)(%d<>%d)\n", ! 134: [self name], shmem_size, sizeof (VGAShmem_t)); ! 135: [[EventDriver instance] unregisterScreen:token]; ! 136: return IO_R_INVALID_ARG; ! 137: } ! 138: ! 139: // Init shared memory area ! 140: bzero( (char *)shmem, shmem_size ); ! 141: shmem->cursorShow = 1; ! 142: shmem->screenBounds = bounds; ! 143: [self setToken:token]; ! 144: ! 145: return IO_R_SUCCESS; ! 146: } ! 147: ! 148: ! 149: - (void)_readBpp4planar: (unsigned short *)fb toBpp2packed32: (unsigned int *)dst ! 150: // Description: reads in a 4-planar representation, converts it into a ! 151: // packed-32 representation, and writes the result into ! 152: // dst. ! 153: { ! 154: unsigned int v, i; ! 155: ! 156: [self setReadPlane: 1]; ! 157: i = 0xffff ^ *fb; ! 158: v = (i & 0x8000) << 2 | (i & 0x4000) << 5 | (i & 0x2000) << 8 ! 159: | (i & 0x1000) << 11 | (i & 0x0800) << 14 | (i & 0x0400) << 17 ! 160: | (i & 0x0200) << 20 | (i & 0x0100) << 23 | (i & 0x0080) >> 6 ! 161: | (i & 0x0040) >> 3 | (i & 0x0020) | (i & 0x0010) << 3 ! 162: | (i & 0x0008) << 6 | (i & 0x0004) << 9 | (i & 0x0002) << 12 ! 163: | (i & 0x0001) << 15; ! 164: ! 165: [self setReadPlane: 0]; ! 166: i = 0xffff ^ *fb; ! 167: v |= (i & 0x8000) << 1 | (i & 0x4000) << 4 | (i & 0x2000) << 7 ! 168: | (i & 0x1000) << 10 | (i & 0x0800) << 13 | (i & 0x0400) << 16 ! 169: | (i & 0x0200) << 19 | (i & 0x0100) << 22 | (i & 0x0080) >> 7 ! 170: | (i & 0x0040) >> 4 | (i & 0x0020) >> 1 | (i & 0x0010) << 2 ! 171: | (i & 0x0008) << 5 | (i & 0x0004) << 8 | (i & 0x0002) << 11 ! 172: | (i & 0x0001) << 14; ! 173: ! 174: *dst = v; ! 175: } ! 176: ! 177: - (void)_writeBpp2packed32: (unsigned int *)dst toBpp4planar: (unsigned short *)fb ! 178: // Description: reads in a packed-32 representation, converts it into a ! 179: // 4-planar representation, and writes the result into ! 180: // fb. ! 181: { ! 182: unsigned int i, dstvalue; ! 183: unsigned short fbvalue; ! 184: unsigned char fblo, fbhi; ! 185: ! 186: [self setWritePlane: 1]; ! 187: dstvalue = *dst; ! 188: i = dstvalue & 0xAAAA; ! 189: fblo = 0xff ^ (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12) ! 190: | ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6) ! 191: | ((i & 0x0080) >> 3) | (i & 0x0020) ! 192: | ((i & 0x0008) << 3) | ((i & 0x0002) << 6)); ! 193: i = (dstvalue >> 16) & 0xAAAA; ! 194: fbhi = 0xff ^ (char) (((i & 0x8000) >> 15) | ((i & 0x2000) >> 12) ! 195: | ((i & 0x0800) >> 9) | ((i & 0x0200) >> 6) ! 196: | ((i & 0x0080) >> 3) | (i & 0x0020) ! 197: | ((i & 0x0008) << 3) | ((i & 0x0002) << 6)); ! 198: fbvalue = (((unsigned short)fbhi) << 8) | fblo; ! 199: *fb = fbvalue; ! 200: ! 201: [self setWritePlane: 0]; ! 202: dstvalue = *dst; ! 203: i = dstvalue & 0x5555; ! 204: fblo = 0xff ^ (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11) ! 205: | ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5) ! 206: | ((i & 0x0040) >> 2) | ((i & 0x0010) << 1) ! 207: | ((i & 0x0004) << 4) | ((i & 0x0001) << 7)); ! 208: i = (dstvalue >> 16) & 0x5555; ! 209: fbhi = 0xff ^ (char) (((i & 0x4000) >> 14) | ((i & 0x1000) >> 11) ! 210: | ((i & 0x0400) >> 8) | ((i & 0x0100) >> 5) ! 211: | ((i & 0x0040) >> 2) | ((i & 0x0010) << 1) ! 212: | ((i & 0x0004) << 4) | ((i & 0x0001) << 7)); ! 213: fbvalue = (((unsigned short)fbhi) << 8) | fblo; ! 214: *fb = fbvalue; ! 215: } ! 216: ! 217: ! 218: - (void)_VGADisplayCursor: (IODisplayInfo *)dpy shmem: (VGAShmem_t *)shmem ! 219: // Description: Displays the cursor on the framebuffer by first saving ! 220: // what's underneath the cursor, then drawing the cursor there. ! 221: // NOTE:The topleft of the cursorRect passed in is not ! 222: // necessarily the cursor location.The cursorRect is adjusted to ! 223: // compensate for the cursor hotspot.If the frame buffer is ! 224: // cacheable, flush at the end of the drawing operation. A ! 225: // saveRect is stored which defines the actual area of the screen ! 226: // that is saved.This is used by RemoveCursor in restoring the ! 227: // screen data later. ! 228: { ! 229: Bounds screenBounds = shmem->screenBounds; ! 230: Bounds saveRect; /* cursor save rectangle (local) */ ! 231: unsigned int *cursPtr; /* cursor data pointer */ ! 232: unsigned int *vramPtr; /* screen data pointer */ ! 233: unsigned int *savePtr; /* saved screen data pointer */ ! 234: unsigned int *maskPtr; /* cursor mask pointer */ ! 235: int i, doLeft, doRight, skew, rSkew; ! 236: static unsigned int vramBuf[2]; ! 237: unsigned short *this_segment, *fb; ! 238: unsigned int fb_x_offset_shorts; ! 239: unsigned int fb_shorts_per_line; ! 240: unsigned int fb_lines_per_segment; ! 241: unsigned int fb_segment; ! 242: unsigned int fb_next_segment_y; ! 243: int y; ! 244: int miny, maxy; /* absolute min and max y--not relative address */ ! 245: /* e.g. 0 <= miny <= SCREEN_HEIGHT */ ! 246: ! 247: [self savePlaneAndSegmentSettings]; ! 248: ! 249: saveRect = shmem->cursorRect; ! 250: vramPtr = (unsigned int *)vramBuf; ! 251: ! 252: // ! 253: // Clip saveRect vertical within screen bounds ! 254: // ! 255: if (saveRect.miny < screenBounds.miny) { ! 256: saveRect.miny = screenBounds.miny; ! 257: } ! 258: if (saveRect.maxy > screenBounds.maxy) { ! 259: saveRect.maxy = screenBounds.maxy; ! 260: } ! 261: i = shmem->cursorRect.minx - screenBounds.minx; ! 262: saveRect.minx = i - (i & PPXMASK) + screenBounds.minx; ! 263: saveRect.maxx = saveRect.minx + CURSORWIDTH*2; ! 264: shmem->saveRect = saveRect; ! 265: ! 266: // ! 267: // skew is in bits ! 268: // ! 269: skew = (shmem->cursorRect.minx & PPXMASK)<<1; ! 270: rSkew = 32-skew; ! 271: ! 272: // ! 273: // Set up pointers for saving and drawing ! 274: // ! 275: cursPtr = shmem->cursor.bw.image[shmem->frame]; ! 276: maskPtr = shmem->cursor.bw.mask[shmem->frame]; ! 277: savePtr = shmem->cursor.bw.save; ! 278: i = saveRect.miny - shmem->cursorRect.miny; ! 279: cursPtr += i; ! 280: maskPtr += i; ! 281: ! 282: // ! 283: // Since we are drawing an int at a time, and it may ! 284: // cross an int boundary, we draw it in two pieces (left ! 285: // and right) which are offset by skew. ! 286: // ! 287: doLeft = (saveRect.minx >= screenBounds.minx); ! 288: doRight = (saveRect.maxx <= screenBounds.maxx); ! 289: ! 290: // ! 291: // VGA related assignments ! 292: // ! 293: // QUESTION--isn't this a little fishy?? Should this be the address we mapped? ! 294: this_segment = (unsigned short *)(0xa0000); ! 295: fb_x_offset_shorts = (saveRect.minx - screenBounds.minx) >> 4; ! 296: fb_shorts_per_line = dpy->width >> 4; ! 297: fb_lines_per_segment = 0x10000 / (dpy->width >> 3); ! 298: ! 299: miny = saveRect.miny - screenBounds.miny; ! 300: maxy = saveRect.maxy - screenBounds.miny; ! 301: ! 302: fb = this_segment + ! 303: ((miny % fb_lines_per_segment) * fb_shorts_per_line) + ! 304: fb_x_offset_shorts; ! 305: fb_segment = miny / fb_lines_per_segment; ! 306: fb_next_segment_y = (fb_lines_per_segment * (fb_segment + 1)); ! 307: ! 308: [self setWriteSegment: fb_segment]; ! 309: [self setReadSegment: fb_segment]; ! 310: ! 311: for ( y = miny; ! 312: y < maxy; ! 313: y++) { ! 314: register unsigned int workreg; ! 315: ! 316: // ! 317: // Change VGA segment if necessary. ! 318: // ! 319: if (y == fb_next_segment_y) { ! 320: fb = this_segment + ! 321: ((y % fb_lines_per_segment) * fb_shorts_per_line) + ! 322: fb_x_offset_shorts; ! 323: fb_segment++; ! 324: fb_next_segment_y += fb_lines_per_segment; ! 325: ! 326: [self setWriteSegment: fb_segment]; ! 327: [self setReadSegment: fb_segment]; ! 328: } ! 329: ! 330: if (doLeft) { ! 331: [self _readBpp4planar:fb toBpp2packed32:vramPtr]; ! 332: *savePtr++ = workreg = *vramPtr; ! 333: *vramPtr = (workreg&(~((*maskPtr) RSHIFT skew))) | ! 334: ((*cursPtr) RSHIFT skew); ! 335: [self _writeBpp2packed32:vramPtr toBpp4planar:fb]; ! 336: } ! 337: if (doRight) { ! 338: if (!skew) { ! 339: savePtr++; ! 340: } else { ! 341: [self _readBpp4planar:(fb+1) toBpp2packed32:(vramPtr+1)]; ! 342: *savePtr++ = workreg = *(vramPtr+1); ! 343: *(vramPtr+1)= (workreg&(~((*maskPtr) LSHIFT rSkew))) | ! 344: ((*cursPtr) LSHIFT rSkew); ! 345: [self _writeBpp2packed32:(vramPtr+1) toBpp4planar:(fb+1)]; ! 346: } ! 347: } ! 348: ! 349: // ! 350: // Advance fb (pointer into VGA framebuffer) one line. ! 351: // ! 352: fb += fb_shorts_per_line; ! 353: ! 354: cursPtr++; ! 355: maskPtr++; ! 356: } ! 357: ! 358: [self restorePlaneAndSegmentSettings]; ! 359: } ! 360: ! 361: ! 362: - (void)_VGARemoveCursor: (IODisplayInfo *)dpy shmem: (VGAShmem_t *)shmem ! 363: // Description: RemoveCursor erases the cursor by replacing the background ! 364: // image that was saved by the previous call to DisplayCursor. ! 365: // If the frame buffer is cacheable, flush at the end of the ! 366: // drawing operation. ! 367: { ! 368: int doLeft, doRight; ! 369: unsigned int lmask = 0, rmask = 0; ! 370: unsigned int *vramPtr; ! 371: unsigned int *savePtr; ! 372: Bounds screenBounds = shmem->screenBounds; ! 373: Bounds saveRect = shmem->saveRect; ! 374: #if __BIG_ENDIAN__ ! 375: static const unsigned int mask_array[16] = { ! 376: 0xFFFFFFFF,0x3FFFFFFF,0x0FFFFFFF,0x03FFFFFF, ! 377: 0x00FFFFFF,0x003FFFFF,0x000FFFFF,0x0003FFFF, ! 378: 0x0000FFFF,0x00003FFF,0x00000FFF,0x000003FF, ! 379: 0x000000FF,0x0000003f,0x0000000F,0x00000003 ! 380: }; ! 381: #else ! 382: static unsigned int mask_array[17] = { ! 383: 0xFFFFFFFF,0xFFFFFFFC,0xFFFFFFF0,0xFFFFFFC0, ! 384: 0xFFFFFF00,0xFFFFFC00,0xFFFFF000,0xFFFFC000, ! 385: 0xFFFF0000,0xFFFC0000,0xFFF00000,0xFFC00000, ! 386: 0xFF000000,0xFC000000,0xF0000000,0xC0000000,0x00000000}; ! 387: #endif ! 388: static unsigned int vramBuf[2]; ! 389: unsigned short *this_segment, *fb; ! 390: unsigned int fb_x_offset_shorts; ! 391: unsigned int fb_shorts_per_line; ! 392: unsigned int fb_lines_per_segment; ! 393: unsigned int fb_segment; ! 394: unsigned int fb_next_segment_y; ! 395: int y; ! 396: int skew; ! 397: int miny, maxy; /* absolute min and max y--not relative address */ ! 398: /* e.g. 0 <= miny <= SCREEN_HEIGHT */ ! 399: ! 400: [self savePlaneAndSegmentSettings]; ! 401: ! 402: vramPtr = (unsigned int *)vramBuf; ! 403: ! 404: // ! 405: // VGA related assignments ! 406: // ! 407: // QUESTION--isn't this a little fishy?? Should this be the address we mapped? ! 408: this_segment = (unsigned short *)(0xa0000); ! 409: fb_x_offset_shorts = (saveRect.minx - screenBounds.minx) >> 4; ! 410: fb_shorts_per_line = dpy->width >> 4; ! 411: ! 412: miny = saveRect.miny - screenBounds.miny; ! 413: maxy = saveRect.maxy - screenBounds.miny; ! 414: ! 415: // ! 416: // VGA bank size is 64K ! 417: // ! 418: fb_lines_per_segment = 0x10000 / (dpy->width >> 3); ! 419: fb = this_segment + ! 420: ((miny % fb_lines_per_segment) * fb_shorts_per_line) + ! 421: fb_x_offset_shorts; ! 422: fb_segment = miny / fb_lines_per_segment; ! 423: fb_next_segment_y = (fb_lines_per_segment * (fb_segment + 1)); ! 424: ! 425: [self setWriteSegment: fb_segment]; ! 426: [self setReadSegment: fb_segment]; ! 427: ! 428: // ! 429: // skew is in bits ! 430: // ! 431: skew = (shmem->cursorRect.minx & PPXMASK)<<1; ! 432: ! 433: savePtr = shmem->cursor.bw.save; ! 434: if (doLeft = (saveRect.minx >= screenBounds.minx)) { ! 435: lmask = mask_array[shmem->oldCursorRect.minx - saveRect.minx]; ! 436: } ! 437: if (doRight = (saveRect.maxx <= screenBounds.maxx)) { ! 438: rmask = ~mask_array[16-(saveRect.maxx - shmem->oldCursorRect.maxx)]; ! 439: } ! 440: ! 441: for ( y = miny; ! 442: y < maxy; ! 443: y++) { ! 444: ! 445: // ! 446: // Change VGA segment if necessary. ! 447: // ! 448: if (y == fb_next_segment_y) { ! 449: fb = this_segment + ! 450: ((y % fb_lines_per_segment) * fb_shorts_per_line) + ! 451: fb_x_offset_shorts; ! 452: fb_segment++; ! 453: fb_next_segment_y += fb_lines_per_segment; ! 454: ! 455: [self setWriteSegment: fb_segment]; ! 456: [self setReadSegment: fb_segment]; ! 457: } ! 458: ! 459: if (doLeft) { ! 460: [self _readBpp4planar:fb toBpp2packed32:vramPtr]; ! 461: *vramPtr = (*vramPtr&(~lmask))|(*savePtr++&lmask); ! 462: [self _writeBpp2packed32:vramPtr toBpp4planar:fb]; ! 463: } ! 464: ! 465: if (doRight) { ! 466: if (!skew) { ! 467: savePtr++; ! 468: } else { ! 469: [self _readBpp4planar:(fb+1) toBpp2packed32:(vramPtr+1)]; ! 470: *(vramPtr+1)=(*(vramPtr+1)&(~rmask))|(*savePtr++&rmask); ! 471: [self _writeBpp2packed32:(vramPtr+1) toBpp4planar:(fb+1)]; ! 472: } ! 473: } ! 474: ! 475: // ! 476: // Advance fb (pointer into VGA framebuffer) one line. ! 477: // ! 478: fb += fb_shorts_per_line; ! 479: ! 480: } ! 481: ! 482: [self restorePlaneAndSegmentSettings]; ! 483: } ! 484: ! 485: - (void)_displayCursor: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem ! 486: // Description: Private routine to display the cursor. Sets up the ! 487: // cursor rect. ! 488: { ! 489: Point hs; ! 490: hs = shmem->hotSpot[shmem->frame]; ! 491: shmem->cursorRect.maxx = ! 492: (shmem->cursorRect.minx = (shmem->cursorLoc).x - hs.x) + 16; ! 493: shmem->cursorRect.maxy = ! 494: (shmem->cursorRect.miny = (shmem->cursorLoc).y - hs.y) + 16; ! 495: [self _VGADisplayCursor:d shmem:shmem]; ! 496: shmem->oldCursorRect = shmem->cursorRect; ! 497: } ! 498: ! 499: - (void)_sysHideCursor: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem ! 500: // Description: Private routing to hide the cursor. ! 501: { ! 502: if (!shmem->cursorShow++) { ! 503: [self _VGARemoveCursor:d shmem:shmem]; ! 504: } ! 505: } ! 506: ! 507: - (void)_sysShowCursor: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem ! 508: // Description: Private routine to show the cursor ! 509: { ! 510: if (shmem->cursorShow) ! 511: if (!--shmem->cursorShow) ! 512: [self _displayCursor:d shmem:shmem]; ! 513: } ! 514: ! 515: - (void)_checkShield: (IODisplayInfo *)d shmem: (VGAShmem_t *)shmem ! 516: // Description: QUESTION ! 517: { ! 518: Point hs; ! 519: int intersect; ! 520: Bounds tempRect; ! 521: ! 522: // ! 523: // Calculate temp cursorRect ! 524: // ! 525: hs = shmem->hotSpot[shmem->frame]; ! 526: tempRect.maxx = (tempRect.minx = (shmem->cursorLoc).x - hs.x) + 16; ! 527: tempRect.maxy = (tempRect.miny = (shmem->cursorLoc).y - hs.y) + 16; ! 528: ! 529: intersect = RECTS_INTERSECT(tempRect, shmem->shieldRect); ! 530: if (intersect != shmem->shielded) { ! 531: (shmem->shielded = intersect) ? [self _sysHideCursor:d shmem:shmem] : ! 532: [self _sysShowCursor:d shmem:shmem]; ! 533: } ! 534: } ! 535: ! 536: ! 537: static const char * ! 538: find_parameter(const char *parameter, const char *string) ! 539: // Description: Find parameter in string and return what follows ! 540: // it. E.g. for string = "Width: 10" and ! 541: // parameter = "Width:" return "10". ! 542: { ! 543: int c; ! 544: size_t length; ! 545: ! 546: length = strlen(parameter); ! 547: while (*string != 0) { ! 548: if (strncmp(string, parameter, length) == 0) { ! 549: string += length; ! 550: while ((c = *string) != '\0' && (c == ' ' || c == '\t')) ! 551: string++; ! 552: return (c != 0) ? string : 0; ! 553: } ! 554: string++; ! 555: } ! 556: return 0; ! 557: } ! 558: ! 559: ! 560: - (void)_generateName: (char *)name andUnit:(IOObjectNumber *)unit ! 561: // Description: Used to generate a name for a new Display object. ! 562: // "name" is a char array of size IO_STRING_LENGTH ! 563: { ! 564: static int nextSVGAUnit = 0; ! 565: ! 566: *unit = nextSVGAUnit++; ! 567: sprintf(name, "SVGADisplay%d", *unit); ! 568: } ! 569: ! 570: ! 571: // ! 572: // END: Implementation of private routines for SVGA ! 573: // ! 574: ! 575: ! 576: ! 577: // ! 578: // BEGIN: Implementation of the evScreen protocol ! 579: // ! 580: ! 581: ! 582: - hideCursor: (int)token ! 583: { ! 584: SET_SEMAPHORE([self _shmem]); ! 585: [self _sysHideCursor:[self displayInfo] shmem:[self _shmem]]; ! 586: CLEAR_SEMAPHORE([self _shmem]); ! 587: return self; ! 588: } ! 589: ! 590: - moveCursor:(Point*)cursorLoc frame:(int)frame token:(int)t ! 591: { ! 592: VGAShmem_t *shmem; ! 593: ! 594: shmem = [self _shmem]; ! 595: SET_SEMAPHORE(shmem); ! 596: shmem->frame = frame; ! 597: shmem->cursorLoc = *cursorLoc; ! 598: if (!shmem->cursorShow++) { ! 599: [self _VGARemoveCursor:[self displayInfo] shmem:shmem]; ! 600: } ! 601: if (shmem->cursorObscured) { ! 602: shmem->cursorObscured = 0; ! 603: if (shmem->cursorShow) ! 604: --shmem->cursorShow; ! 605: } ! 606: if (shmem->shieldFlag) { ! 607: [self _checkShield:[self displayInfo] shmem:shmem]; ! 608: } ! 609: if (shmem->cursorShow) { ! 610: if (!--shmem->cursorShow) { ! 611: [self _displayCursor:[self displayInfo] shmem:shmem]; ! 612: } ! 613: } ! 614: CLEAR_SEMAPHORE(shmem); ! 615: return self; ! 616: } ! 617: ! 618: - showCursor:(Point*)cursorLoc frame:(int)frame token:(int)t ! 619: { ! 620: VGAShmem_t *shmem; ! 621: ! 622: shmem = [self _shmem]; ! 623: SET_SEMAPHORE(shmem); ! 624: shmem->frame = frame; ! 625: shmem->cursorLoc = *cursorLoc; ! 626: if (shmem->shieldFlag) { ! 627: [self _checkShield:[self displayInfo] shmem:shmem]; ! 628: } ! 629: [self _sysShowCursor:[self displayInfo] shmem:shmem]; ! 630: CLEAR_SEMAPHORE(shmem); ! 631: return self; ! 632: } ! 633: ! 634: // ! 635: // END: Implementation of the evScreen protocol ! 636: // ! 637: ! 638: ! 639: // ! 640: // BEGIN: EXPORTED methods ! 641: // ! 642: ! 643: - (void)setReadSegment: (unsigned char)segmentNum ! 644: // Description: Select which 64K segment we intend to read from - ! 645: // this must be overridden by a subclasser. ! 646: { ! 647: } ! 648: ! 649: ! 650: - (void)setWriteSegment: (unsigned char)segmentNum ! 651: // Description: Select which 64K segment we intend to write from - ! 652: // this must be overridden by a subclasser. ! 653: { ! 654: } ! 655: ! 656: ! 657: - (void)setReadPlane: (unsigned char)planeNum ! 658: // Description: Select which of 4 bit planes to read from in planar ! 659: // modes - only one plane can be active at a time. ! 660: { ! 661: } ! 662: ! 663: ! 664: - (void)setWritePlane: (unsigned char)planeNum ! 665: // Description: Select one of 4 bit planes to write to in planar modes, ! 666: // although more than one plane can be active at a time, ! 667: // this routine only allows access to 1 plane at a time. ! 668: { ! 669: } ! 670: ! 671: ! 672: - (void)savePlaneAndSegmentSettings ! 673: // Description: Save plane and segment settings. These methods must ! 674: // be implemented by subclasses in a device specific way. ! 675: { ! 676: } ! 677: ! 678: ! 679: - (void)restorePlaneAndSegmentSettings ! 680: // Description: Restore plane and segment settings. These methods must ! 681: // be implemented by subclasses in a device specific way. ! 682: { ! 683: } ! 684: ! 685: ! 686: - (void)enterSVGAMode ! 687: // Description: Put the display into SVGA mode. This typically happens ! 688: // when the window server starts running. This method is ! 689: // implemented by subclasses in a device specific way. ! 690: { ! 691: } ! 692: ! 693: ! 694: - (void)revertToVGAMode ! 695: // Description: Get the device out of whatever advanced mode it was using ! 696: // and back into a state where it can be used as a standard ! 697: // VGA device. This method is implemented by subclasses in a ! 698: // device specific way. ! 699: { ! 700: } ! 701: ! 702: ! 703: task_t (task_self)(void); // from /NextDeveloper/Headers/mach/mach_traps.h ! 704: ! 705: - (vm_address_t)mapFrameBufferAtPhysicalAddress:(unsigned int)addr ! 706: length:(int)length; ! 707: // Description: Look up the physical memory location for this device instance ! 708: // and map it into VM for use by the device driver. If problems ! 709: // occur, the method returns (vm_address_t)0. If addr is not 0, ! 710: // then it is used as the physical memory address and ! 711: // length is used as the length. ! 712: { ! 713: vm_address_t vmLocation; ! 714: IOReturn result = IO_R_SUCCESS; ! 715: ! 716: if (addr != 0) // Override configuration XXX BOGUS!!! ! 717: { ! 718: // This is totally bogus. I cannot believe that it is ! 719: // public API. NB: This mapping cannot be freed using ! 720: // unmapMemoryRange:from: in IOEISADirectDevice. ! 721: if (_KernBusMemoryCreateMapping(addr, ! 722: length, ! 723: &vmLocation, ! 724: current_task_EXTERNAL(), ! 725: YES, ! 726: IO_WriteThrough) != KERN_SUCCESS) ! 727: result = IO_R_NO_MEMORY; ! 728: } ! 729: else ! 730: { ! 731: result = [self mapMemoryRange:0 //QUESTION--what is this??? ! 732: to:&vmLocation ! 733: findSpace:YES ! 734: cache:IO_WriteThrough]; ! 735: } ! 736: ! 737: if (result != IO_R_SUCCESS) ! 738: { ! 739: IOLog("IOSVGADisplay/mapFrameBuffer: Can't map memory (%s)\n", ! 740: [self stringFromReturn:result]); ! 741: return (vm_address_t)0; ! 742: } ! 743: ! 744: return vmLocation; ! 745: } ! 746: ! 747: ! 748: ! 749: - (int)selectMode:(const IODisplayInfo *)modeList ! 750: count:(int)count ! 751: valid:(const BOOL *)isValid ! 752: // Description: Choose a mode from the list `modeList' (containing `count' ! 753: // modes) based on the value of the `DisplayMode' key in the ! 754: // device's config table. If `isValid' is nonzero, each element ! 755: // specifies whether or not the corresponding mode is valid. ! 756: { ! 757: const char *displayMode; ! 758: IOConfigTable *configTable; ! 759: int k, width, height; ! 760: int screenWidth, screenHeight, memorySize, ramdacSpeed; ! 761: int scanRate; ! 762: unsigned int modeUnavailableFlag; ! 763: IOBitsPerPixel bitsPerPixel; ! 764: IOColorSpace colorSpace; ! 765: int refreshRate; ! 766: const char *s; ! 767: ! 768: /* Get the string describing the display mode. */ ! 769: ! 770: configTable = [[self deviceDescription] configTable]; ! 771: if (configTable == nil) ! 772: return -1; ! 773: displayMode = [configTable valueForStringKey:"Display Mode"]; ! 774: if (displayMode == 0) { ! 775: /* Historical: for 3.1 drivers only. */ ! 776: displayMode = [configTable valueForStringKey:"DisplayMode"]; ! 777: if (displayMode == 0) ! 778: return -1; ! 779: } ! 780: ! 781: /* Parse the string. It should be of the form ! 782: * Width:# Height:# ColorSpace:(BW:#|RGB:###/#) Refresh:# Hz ! 783: * where `Width' and `Height' specify the width and height of the ! 784: * framebuffer, `ColorSpace' specifies the color space for the ! 785: * framebuffer, and `Refresh' specifies the refresh rate in Hz. ! 786: * The color space parameter should be either BW followed by the ! 787: * bits/pixel, or RGB followed by the bits/component for each ! 788: * component followed by the bits/pixel. ! 789: * ! 790: * For example, here is the display mode specification for the ! 791: * RGB mode of the S3: ! 792: * Width: 800 Height: 600 ColorSpace: RGB:555/16 Refresh: 60 Hz ! 793: */ ! 794: ! 795: height = width = 0; ! 796: s = find_parameter("Width:", displayMode); ! 797: if (s != 0) { ! 798: width = strtol(s, 0, 10); ! 799: } ! 800: ! 801: s = find_parameter("Height:", displayMode); ! 802: if (s != 0) { ! 803: height = strtol(s, 0, 10); ! 804: } ! 805: ! 806: s = find_parameter("Refresh:", displayMode); ! 807: if (s == 0) ! 808: return -1; ! 809: refreshRate = strtol(s, 0, 10); ! 810: ! 811: s = find_parameter("ColorSpace:", displayMode); ! 812: if (s == 0) ! 813: return -1; ! 814: if (strncmp(s, "BW:2", 4) == 0) { ! 815: bitsPerPixel = IO_2BitsPerPixel; ! 816: colorSpace = IO_OneIsBlackColorSpace; ! 817: } else if (strncmp(s, "BW:8", 4) == 0) { ! 818: bitsPerPixel = IO_8BitsPerPixel; ! 819: colorSpace = IO_OneIsWhiteColorSpace; ! 820: } else if (strncmp(s, "RGB:256/8", 9) == 0) { ! 821: bitsPerPixel = IO_8BitsPerPixel; ! 822: colorSpace = IO_RGBColorSpace; ! 823: } else if (strncmp(s, "RGB:444/16", 10) == 0) { ! 824: bitsPerPixel = IO_12BitsPerPixel; ! 825: colorSpace = IO_RGBColorSpace; ! 826: } else if (strncmp(s, "RGB:555/16", 10) == 0) { ! 827: bitsPerPixel = IO_15BitsPerPixel; ! 828: colorSpace = IO_RGBColorSpace; ! 829: } else if (strncmp(s, "RGB:888/32", 10) == 0) { ! 830: bitsPerPixel = IO_24BitsPerPixel; ! 831: colorSpace = IO_RGBColorSpace; ! 832: } else { ! 833: return -1; ! 834: } ! 835: ! 836: ! 837: /* ! 838: * Now look for 4.0 style optional parameters. The display mode ! 839: * specification looks like "Resolution:1280x1024 Screen:1600x1200 ! 840: * Refresh:60Hz ColorSpace:RGB:444/16 Memory:4MB RAMDAC:175Hz Sync:1000"; ! 841: */ ! 842: ! 843: s = find_parameter("Resolution:", displayMode); ! 844: if (s != 0) { ! 845: char *end; ! 846: width = strtol(s, &end, 10); ! 847: height = strtol(end+1, 0, 10); ! 848: } ! 849: ! 850: if ((height == 0) || (width == 0)) ! 851: return -1; ! 852: ! 853: s = find_parameter("Screen:", displayMode); ! 854: if (s != 0) { ! 855: char *end; ! 856: screenWidth = strtol(s, &end, 10); ! 857: height = strtol(end+1, 0, 10); ! 858: } else { ! 859: screenWidth = width; ! 860: screenHeight = height; ! 861: } ! 862: ! 863: /* These parameters are not used by the superclass. */ ! 864: s = find_parameter("Memory:", displayMode); ! 865: if (s != 0) { ! 866: memorySize = strtol(s, 0, 10); ! 867: } ! 868: ! 869: s = find_parameter("RAMDAC:", displayMode); ! 870: if (s != 0) { ! 871: ramdacSpeed = strtol(s, 0, 10); ! 872: } ! 873: ! 874: s = find_parameter("Sync:", displayMode); ! 875: if (s != 0) { ! 876: scanRate = strtol(s, 0, 10); ! 877: } ! 878: ! 879: modeUnavailableFlag = 0; ! 880: s = find_parameter("Available:", displayMode); ! 881: if (s != 0) { ! 882: modeUnavailableFlag = strtol(s, 0, 10); ! 883: } ! 884: ! 885: ! 886: /* Now try to match these parameters with the list of modes. */ ! 887: for (k = 0; k < count; k++) { ! 888: if (isValid != 0 && !isValid[k]) ! 889: continue; ! 890: if (modeUnavailableFlag != 0) ! 891: continue; ! 892: if (modeList[k].width == width ! 893: && modeList[k].height == height ! 894: && modeList[k].colorSpace == colorSpace ! 895: && modeList[k].bitsPerPixel == bitsPerPixel ! 896: && modeList[k].refreshRate == refreshRate) { ! 897: switch (bitsPerPixel) { ! 898: case IO_2BitsPerPixel: s = "BW:2"; break; ! 899: case IO_8BitsPerPixel: ! 900: if (colorSpace == IO_RGBColorSpace) s = "RGB:256/8"; ! 901: else s = "BW:8"; ! 902: break; ! 903: case IO_12BitsPerPixel: s = "RGB:444/16"; break; ! 904: case IO_15BitsPerPixel: s = "RGB:555/16"; break; ! 905: case IO_24BitsPerPixel: s = "RGB:888/32"; break; ! 906: default: s = "Unknown color space"; break; ! 907: } ! 908: IOLog("Display: Mode selected: %d x %d @ %d Hz (%s)\n", ! 909: width, height, refreshRate, s); ! 910: return k; ! 911: } ! 912: } ! 913: IOLog("Display: Requested mode is not available.\n"); ! 914: return -1; ! 915: } ! 916: ! 917: ! 918: - (int)selectMode: (const IODisplayInfo *)modeList count:(int)count ! 919: // Description: Equivalent to the above with `isValid' set to zero. ! 920: { ! 921: return [self selectMode:modeList count:count valid:0]; ! 922: } ! 923: ! 924: ! 925: + (BOOL)probe:deviceDescription ! 926: // Description: Create an instance of subclass to be associated with ! 927: // specified deviceDescription. Returns whether or not ! 928: // successful. ! 929: { ! 930: IOSVGADisplay *inst; ! 931: ! 932: // Create an instance and initialize some basic instance variables. ! 933: inst = [[self alloc] initFromDeviceDescription:deviceDescription]; ! 934: if (inst == nil) { ! 935: return NO; ! 936: } ! 937: ! 938: [inst setDeviceKind:"frame buffer"]; ! 939: ! 940: [inst registerDevice]; ! 941: ! 942: return YES; ! 943: } ! 944: ! 945: ! 946: ! 947: ! 948: - initFromDeviceDescription:deviceDescription ! 949: // Description: Initialize per specified deviceDescription. Returns ! 950: // nil on error ! 951: { ! 952: char name[IO_STRING_LENGTH]; ! 953: IOObjectNumber unit; ! 954: ! 955: if ([super initFromDeviceDescription:deviceDescription] == nil) { ! 956: return [super free]; ! 957: } ! 958: ! 959: [self _generateName:name andUnit:&unit]; ! 960: [self setUnit:unit]; ! 961: [self setName:name]; ! 962: return self; ! 963: } ! 964: ! 965: ! 966: ! 967: - setBrightness:(int)level token:(int)t ! 968: // Description: Setting the brighness is a device-specific operation ! 969: // which must be implemented by a subclass. This just ! 970: // checks if a legal level was sent. ! 971: { ! 972: if ( level < EV_SCREEN_MIN_BRIGHTNESS ! 973: || level > EV_SCREEN_MAX_BRIGHTNESS ) ! 974: { ! 975: IOLog("%s: Invalid arg to setBrightness:%d\n", ! 976: [self name], level ); ! 977: } ! 978: return self; ! 979: } ! 980: ! 981: - (IOReturn)getIntValues:(unsigned *)parameterArray ! 982: forParameter:(IOParameterName)parameterName ! 983: count:(unsigned int *)count ! 984: // Description: Get and set parameters. These include support ! 985: // for getting the frame buffer parameters, registering it ! 986: // with the event system, returning the registration token. ! 987: { ! 988: unsigned int fb_dimensions[VGA_FB_DIMENSIONS_SIZE]; ! 989: IOReturn r; ! 990: int i; ! 991: unsigned *returnedCount = count; ! 992: unsigned maxCount = *count; ! 993: ! 994: if ( strcmp(parameterName, VGA_FB_MAP) == 0 ) ! 995: { ! 996: parameterArray[0] = 0; ! 997: [self enterSVGAMode]; ! 998: [kmId registerDisplay:self]; ! 999: *returnedCount = 1; ! 1000: return IO_R_SUCCESS; ! 1001: } ! 1002: else if ( strcmp(parameterName, VGA_FB_DIMENSIONS) == 0 ) ! 1003: { ! 1004: IODisplayInfo *display = [self displayInfo]; ! 1005: ! 1006: fb_dimensions[VGA_FB_WIDTH] = display->width; ! 1007: fb_dimensions[VGA_FB_HEIGHT] = display->height; ! 1008: fb_dimensions[VGA_FB_ROWBYTES] = display->rowBytes; ! 1009: ! 1010: *returnedCount = 0; ! 1011: for( i=0; i<VGA_FB_DIMENSIONS_SIZE; i++) { ! 1012: if (*returnedCount == maxCount) ! 1013: break; ! 1014: parameterArray[i] = fb_dimensions[i]; ! 1015: (*returnedCount)++; ! 1016: } ! 1017: return IO_R_SUCCESS; ! 1018: ! 1019: } ! 1020: else if ( strcmp(parameterName, VGA_FB_REGISTER) == 0 ) ! 1021: { ! 1022: r = [self _registerWithED]; ! 1023: *returnedCount = 0; ! 1024: if ( maxCount > 0 ) ! 1025: { ! 1026: *returnedCount = 1; ! 1027: parameterArray[0] = [self token]; ! 1028: } ! 1029: return r; ! 1030: } ! 1031: else ! 1032: { ! 1033: r = [super getIntValues:parameterArray ! 1034: forParameter:parameterName ! 1035: count:returnedCount]; ! 1036: return r; ! 1037: } ! 1038: } ! 1039: ! 1040: ! 1041: - (IOReturn)setIntValues:(unsigned *)parameterArray ! 1042: forParameter:(IOParameterName)parameterName ! 1043: count:(unsigned int)count ! 1044: // Description: Set parameters. This can be used to unregister the frame ! 1045: // buffer as well as set the transfer function. ! 1046: { ! 1047: if ( strcmp(parameterName, VGA_FB_UNMAP) == 0 ) { ! 1048: // [self _unmap]; ! 1049: [self revertToVGAMode]; ! 1050: return IO_R_SUCCESS; ! 1051: } else if ( strcmp(parameterName, VGA_FB_UNREGISTER) == 0 ) { ! 1052: if ( count != 1 ) ! 1053: return IO_R_INVALID_ARG; ! 1054: [[EventDriver instance] unregisterScreen:parameterArray[0]]; ! 1055: return IO_R_SUCCESS; ! 1056: ! 1057: } else { ! 1058: return [super setIntValues:parameterArray ! 1059: forParameter:parameterName ! 1060: count:count]; ! 1061: } ! 1062: } ! 1063: ! 1064: - (IOConsoleInfo *)allocateConsoleInfo; ! 1065: // Description: Allocates a console support info structure based on this ! 1066: // display. This structure, and the functions in it, are used ! 1067: // to display alert and console windows. ! 1068: { ! 1069: return SVGAAllocateConsole([self displayInfo]); ! 1070: } ! 1071: ! 1072: // ! 1073: // END: EXPORTED methods ! 1074: // ! 1075: ! 1076: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.