|
|
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) 1992-96 NeXT Software, Inc. All rights reserved. ! 25: * ! 26: * IOFrameBufferDisplay.m - Implements common methods for "standard" frame ! 27: * buffers. ! 28: * ! 29: * ! 30: * HISTORY ! 31: * 26 Oct 95 Dean Reece ! 32: * Moved strtol() out of this class into its own file (strtol.c) ! 33: * 24 Oct 95 Rakesh Dubey ! 34: * Added mode change feature. ! 35: * 01 Sep 92 Joe Pasqua ! 36: * Created. ! 37: */ ! 38: ! 39: #define KERNEL_PRIVATE 1 ! 40: #define DRIVER_PRIVATE 1 ! 41: ! 42: /* Notes: ! 43: * The definition of a standard frame buffer is anything with direct ! 44: * 32 bit access to a 2 & 8 bit gray, 8 & 16 & 32 bit color. For 16 bit ! 45: * displays we support both 4/4/4 and 5/5/5 samples per channel. ! 46: * ! 47: * This class implements the evScreen protocol for all StdFBDisplays. Well, ! 48: * almost. The setBrightness method doesn't do anything. Subclasses must ! 49: * override this and implement it as appropriate for the device. ! 50: * ! 51: * To find things that need to be fixed, search for FIX, to find questions ! 52: * to be resolved, search for ASK, to find stuff that still needs to be ! 53: * done, search for TO DO. ! 54: */ ! 55: ! 56: #import <string.h> ! 57: #import <stdlib.h> ! 58: #ifdef i386 ! 59: #import <bsd/dev/i386/FBConsole.h> ! 60: #endif ! 61: ! 62: #ifdef ppc ! 63: #import <bsd/dev/ppc/FBConsole.h> ! 64: #endif ! 65: ! 66: #import <driverkit/EventDriver.h> ! 67: #import <bsd/dev/evio.h> ! 68: ! 69: #ifdef i386 ! 70: #import <bsd/dev/i386/kmDevice.h> ! 71: #endif ! 72: #ifdef ppc ! 73: #import <bsd/dev/ppc/kmDevice.h> ! 74: #endif ! 75: ! 76: #import <driverkit/KernBus.h> ! 77: #import <driverkit/KernBusMemory.h> ! 78: #import <driverkit/IODisplayPrivate.h> ! 79: #import <driverkit/IOFrameBufferDisplay.h> ! 80: #import <driverkit/IOFrameBufferShared.h> ! 81: #import <driverkit/IODirectDevicePrivate.h> ! 82: #import <driverkit/displayDefs.h> ! 83: #ifdef i386 ! 84: #import <driverkit/i386/directDevice.h> ! 85: #import <driverkit/i386/driverTypes.h> ! 86: #endif ! 87: #ifdef ppc ! 88: #import <driverkit/ppc/directDevice.h> ! 89: #import <driverkit/ppc/driverTypes.h> ! 90: #endif ! 91: ! 92: #define CLEARSEMA(shmem) ev_unlock(&shmem->cursorSema) ! 93: #define SETSEMA(shmem) \ ! 94: if (!ev_try_lock(&shmem->cursorSema)) return self; ! 95: #define TOUCHBOUNDS(one, two) \ ! 96: (((one.minx < two.maxx) && (two.minx < one.maxx)) && \ ! 97: ((one.miny < two.maxy) && (two.miny < one.maxy))) ! 98: ! 99: #define RBMASK 0xF0F0 /* Short, or 16 bit format */ ! 100: #define GAMASK 0x0F0F /* Short, or 16 bit format */ ! 101: #define AMASK 0x000F /* Short, or 16 bit format */ ! 102: ! 103: #define GetShmem(instance) ((StdFBShmem_t *)(instance->priv)) ! 104: ! 105: extern long int strtol(const char *nptr, char **endptr, int base); ! 106: ! 107: @interface IOFrameBufferDisplay(Private) ! 108: - (BOOL)_commitToPendingMode; ! 109: @end ! 110: ! 111: @implementation IOFrameBufferDisplay ! 112: ! 113: // ! 114: // BEGIN: Generic utility routines and methods ! 115: // ! 116: - (IOReturn)_registerWithED ! 117: // Description: Register this display device with the event driver. ! 118: { ! 119: int token; ! 120: int shmem_size; ! 121: Bounds bounds; ! 122: StdFBShmem_t *shmem; ! 123: ! 124: token = [[EventDriver instance] registerScreen:self ! 125: bounds:&bounds ! 126: shmem:&(self->priv) ! 127: size:&shmem_size]; ! 128: shmem = GetShmem(self); ! 129: if ( token == -1 ) ! 130: return IO_R_INVALID_ARG; ! 131: // We allow the shmem_size to be less than sizeof(StdFBShmem_t) ! 132: // so that we need not consume the extra space that some of the ! 133: // larger cursor variants require if we are really a lower bitdepth. ! 134: if ( shmem_size > sizeof(StdFBShmem_t) ) ! 135: { ! 136: IOLog("%s: shmem_size > sizeof (StdFBShmem_t)(%d<>%d)\n", ! 137: [self name], shmem_size, sizeof (StdFBShmem_t)); ! 138: [[EventDriver instance] unregisterScreen:token]; ! 139: return IO_R_INVALID_ARG; ! 140: } ! 141: // Init shared memory area ! 142: memset((char *)shmem, 0, shmem_size); ! 143: shmem->cursorShow = 1; ! 144: shmem->screenBounds = bounds; ! 145: [self setToken:token]; ! 146: ! 147: return IO_R_SUCCESS; ! 148: } ! 149: ! 150: #define short34to35WithGamma(x) \ ! 151: ( (_bm34To35SampleTable[((x) & 0x00F0) >> 4]) \ ! 152: | (_bm34To35SampleTable[((x) & 0x0F00) >> 8] << 5) \ ! 153: | (_bm34To35SampleTable[(x) >> 12] << 10) ) ! 154: ! 155: #define short35to34WithGamma(x) \ ! 156: ( 0x000F \ ! 157: | (_bm35To34SampleTable[x & 0x001F] << 4) \ ! 158: | (_bm35To34SampleTable[(x & 0x03E0) >> 5] << 8) \ ! 159: | (_bm35To34SampleTable[(x & 0x7C00) >> 10] << 12) ) ! 160: ! 161: static void StdFBDisplayCursor16(IOFrameBufferDisplay *inst) ! 162: // Description: Displays the cursor on the framebuffer by first saving ! 163: // what's underneath the cursor, then drawing the cursor there. ! 164: // NOTE:The topleft of the cursorRect passed in is not ! 165: // necessarily the cursor location.The cursorRect is adjusted to ! 166: // compensate for the cursor hotspot.If the frame buffer is ! 167: // cacheable, flush at the end of the drawing operation. A ! 168: // saveRect is stored which defines the actual area of the screen ! 169: // that is saved.This is used by RemoveCursor in restoring the ! 170: // screen data later. ! 171: { ! 172: IODisplayInfo *dpy; ! 173: StdFBShmem_t *shmem; ! 174: vm_offset_t startPtr; /* Starting screen data pointer */ ! 175: unsigned int vramRow; ! 176: Bounds saveRect; ! 177: short i, j, width, cursRow; ! 178: unsigned short *vramPtr; /* screen data pointer */ ! 179: unsigned short *savePtr; /* saved screen data pointer */ ! 180: unsigned short s, d, f; ! 181: volatile unsigned short *cursPtr; ! 182: unsigned char *_bm34To35SampleTable; ! 183: unsigned char *_bm35To34SampleTable; ! 184: ! 185: dpy = [inst displayInfo]; ! 186: shmem = GetShmem(inst); ! 187: saveRect = shmem->cursorRect; ! 188: /* Clip saveRect vertical within screen bounds */ ! 189: if (saveRect.miny < shmem->screenBounds.miny) ! 190: saveRect.miny = shmem->screenBounds.miny; ! 191: if (saveRect.maxy > shmem->screenBounds.maxy) ! 192: saveRect.maxy = shmem->screenBounds.maxy; ! 193: if (saveRect.minx < shmem->screenBounds.minx) ! 194: saveRect.minx = shmem->screenBounds.minx; ! 195: if (saveRect.maxx > shmem->screenBounds.maxx) ! 196: saveRect.maxx = shmem->screenBounds.maxx; ! 197: shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */ ! 198: ! 199: vramRow = dpy->totalWidth; /* Scanline width in pixels */ ! 200: vramPtr = (unsigned short *)dpy->frameBuffer + ! 201: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) + ! 202: (saveRect.minx - shmem->screenBounds.minx); ! 203: startPtr = (vm_offset_t) vramPtr; ! 204: width = saveRect.maxx - saveRect.minx; ! 205: vramRow -= width; ! 206: ! 207: cursRow = CURSORWIDTH - width; ! 208: savePtr = shmem->cursor.rgb.save; ! 209: cursPtr = shmem->cursor.rgb.image[shmem->frame]; ! 210: cursPtr += (saveRect.miny - shmem->cursorRect.miny) * CURSORWIDTH + ! 211: (saveRect.minx - shmem->cursorRect.minx); ! 212: ! 213: if (dpy->bitsPerPixel == IO_12BitsPerPixel) ! 214: { ! 215: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) { ! 216: for (j = width; --j != -1; ) { ! 217: d = *savePtr++ = *vramPtr; ! 218: if ( (s = *cursPtr++) == 0 ) ! 219: { /* Transparent black area. Leave dst as is. */ ! 220: ++vramPtr; ! 221: continue; ! 222: } ! 223: if ( (f = (~s) & (unsigned int)AMASK) == 0 ) ! 224: { /* Opaque cursor pixel. Mark it. */ ! 225: *vramPtr++ = s; ! 226: continue; ! 227: } ! 228: /* Alpha is not 0 or 1.0. Sover the cursor. */ ! 229: *vramPtr++ = s + (((((d & RBMASK)>>4)*f + GAMASK) & RBMASK) ! 230: | ((((d & GAMASK)*f+GAMASK)>>4) & GAMASK)); ! 231: } ! 232: cursPtr += cursRow; /* starting point of next cursor line */ ! 233: vramPtr += vramRow; /* starting point of next screen line */ ! 234: } ! 235: } ! 236: else // dpy->bitsPerPixel == IO_15BitsPerPixel ! 237: { ! 238: // These tables should always be set by the Window Server before ! 239: // it enables cursor drawing. If they're not set, it's an error. ! 240: if ( (_bm34To35SampleTable = inst->_bm34To35SampleTable) == NULL ! 241: || (_bm35To34SampleTable = inst->_bm35To34SampleTable) == NULL ) ! 242: return; ! 243: for (i = saveRect.maxy - saveRect.miny; --i>=0; ) { ! 244: for (j = width; --j>=0; ) { ! 245: d = *savePtr++ = *vramPtr; ! 246: if ( (s = *cursPtr++) == 0 ) ! 247: { /* Transparent black area. Leave dst as is. */ ! 248: ++vramPtr; ! 249: continue; ! 250: } ! 251: if ( (f = (~s) & (unsigned int)AMASK) == 0 ) ! 252: { /* Opaque cursor pixel. Mark it. */ ! 253: *vramPtr++ = short34to35WithGamma(s); ! 254: continue; ! 255: } ! 256: /* Alpha is not 0 or 1.0. Sover the cursor. */ ! 257: d = short35to34WithGamma(d); ! 258: d = s + (((((d & RBMASK)>>4)*f + GAMASK) & RBMASK) ! 259: | ((((d & GAMASK)*f+GAMASK)>>4) & GAMASK)); ! 260: *vramPtr++ = short34to35WithGamma(d); ! 261: } ! 262: cursPtr += cursRow; /* starting point of next cursor line */ ! 263: vramPtr += vramRow; /* starting point of next screen line */ ! 264: } ! 265: } ! 266: } ! 267: ! 268: static inline unsigned int MUL32(unsigned int a, unsigned int b) ! 269: { ! 270: unsigned int v, w; ! 271: ! 272: v = ((a & 0xff00ff00) >> 8) * b; ! 273: v += ((v & 0xff00ff00) >> 8) + 0x00010001; ! 274: w = (a & 0x00ff00ff) * b; ! 275: w += ((w & 0xff00ff00) >> 8) + 0x00010001; ! 276: ! 277: return (v & 0xff00ff00) | ((w >> 8) & 0x00ff00ff); ! 278: } ! 279: ! 280: static inline unsigned char map32to256( unsigned char *directToLogical, unsigned int s) ! 281: { ! 282: unsigned char logicalValue; ! 283: ! 284: if ((s ^ (s>>8)) & 0x00ffff00) { ! 285: logicalValue = directToLogical[(s>>24) + 0] + ! 286: directToLogical[((s>>16)&0xff) + 256] + ! 287: directToLogical[((s>>8)&0xff) + 512]; ! 288: } else { ! 289: logicalValue = directToLogical[(s>>24) + 768]; ! 290: } ! 291: return( directToLogical[ logicalValue + 1024 ]); // final conversion from NeXT palette ! 292: // to actual palette ! 293: } ! 294: ! 295: static void StdFBDisplayCursor8(IOFrameBufferDisplay *inst) ! 296: // Description: Displays the cursor on the framebuffer by first saving ! 297: // what's underneath the cursor, then drawing the cursor there. ! 298: // NOTE:The topleft of the cursorRect passed in is not ! 299: // necessarily the cursor location.The cursorRect is adjusted to ! 300: // compensate for the cursor hotspot.If the frame buffer is ! 301: // cacheable, flush at the end of the drawing operation. A ! 302: // saveRect is stored which defines the actual area of the screen ! 303: // that is saved.This is used by RemoveCursor in restoring the ! 304: // screen data later. ! 305: { ! 306: IODisplayInfo *dpy; ! 307: StdFBShmem_t *shmem; ! 308: vm_offset_t startPtr; /* Starting screen data pointer */ ! 309: unsigned int vramRow; ! 310: Bounds saveRect; ! 311: short i, j, width, cursRow; ! 312: unsigned char *vramPtr; /* screen data pointer */ ! 313: unsigned char *savePtr; /* saved screen data pointer */ ! 314: unsigned short s, d; ! 315: unsigned char dst, alpha; ! 316: unsigned int rgb32val; ! 317: volatile unsigned char *cursPtr; ! 318: volatile unsigned char *maskPtr; /* cursor mask pointer */ ! 319: unsigned int *_bm256To38SampleTable = inst->_bm256To38SampleTable; ! 320: unsigned char *_bm38To256SampleTable = inst->_bm38To256SampleTable; ! 321: ! 322: dpy = [inst displayInfo]; ! 323: shmem = GetShmem(inst); ! 324: saveRect = shmem->cursorRect; ! 325: /* Clip saveRect vertical within screen bounds */ ! 326: if (saveRect.miny < shmem->screenBounds.miny) ! 327: saveRect.miny = shmem->screenBounds.miny; ! 328: if (saveRect.maxy > shmem->screenBounds.maxy) ! 329: saveRect.maxy = shmem->screenBounds.maxy; ! 330: if (saveRect.minx < shmem->screenBounds.minx) ! 331: saveRect.minx = shmem->screenBounds.minx; ! 332: if (saveRect.maxx > shmem->screenBounds.maxx) ! 333: saveRect.maxx = shmem->screenBounds.maxx; ! 334: shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */ ! 335: ! 336: vramRow = dpy->totalWidth; /* Scanline width in pixels */ ! 337: vramPtr = (unsigned char *)dpy->frameBuffer + ! 338: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) + ! 339: (saveRect.minx - shmem->screenBounds.minx); ! 340: startPtr = (vm_offset_t) vramPtr; ! 341: width = saveRect.maxx - saveRect.minx; ! 342: vramRow -= width; ! 343: ! 344: cursRow = CURSORWIDTH - width; ! 345: savePtr = shmem->cursor.bw8.save; ! 346: cursPtr = shmem->cursor.bw8.image[shmem->frame]; ! 347: maskPtr = shmem->cursor.bw8.mask[shmem->frame]; ! 348: i = (saveRect.miny - shmem->cursorRect.miny) * CURSORWIDTH + ! 349: (saveRect.minx - shmem->cursorRect.minx); ! 350: cursPtr += i; ! 351: maskPtr += i; ! 352: ! 353: if (dpy->colorSpace == IO_OneIsWhiteColorSpace) { ! 354: for (i = saveRect.maxy - saveRect.miny; --i>=0; ) { ! 355: for (j = width; --j>=0; ) { ! 356: int t; ! 357: d = *savePtr++ = *vramPtr; ! 358: s = *cursPtr++; ! 359: t = d * (255 - *maskPtr++); ! 360: d = s + ((t + (t >> 8) + 1) >> 8); ! 361: *vramPtr++ = d; ! 362: } ! 363: cursPtr += cursRow; /* starting point of next cursor line */ ! 364: maskPtr += cursRow; ! 365: vramPtr += vramRow; /* starting point of next screen line */ ! 366: } ! 367: } else { // dpy->colorSpace == IO_RGBColorSpace ! 368: for (i = saveRect.maxy - saveRect.miny; --i>=0; ) { ! 369: for (j = width; --j>=0; savePtr++,maskPtr++,cursPtr++,vramPtr++) { ! 370: *savePtr = *vramPtr; ! 371: if (alpha = *maskPtr) { ! 372: dst = *cursPtr; ! 373: if (alpha = ~alpha) { ! 374: rgb32val = _bm256To38SampleTable[*vramPtr]; ! 375: rgb32val = (_bm256To38SampleTable[dst] & ~0xff) + ! 376: MUL32(rgb32val, alpha); ! 377: dst = map32to256(_bm38To256SampleTable, rgb32val); ! 378: } ! 379: *vramPtr = dst; ! 380: } ! 381: } ! 382: cursPtr += cursRow; /* starting point of next cursor line */ ! 383: maskPtr += cursRow; ! 384: vramPtr += vramRow; /* starting point of next screen line */ ! 385: } ! 386: } ! 387: } ! 388: ! 389: static void StdFBRemoveCursor16(IOFrameBufferDisplay *inst) ! 390: // Description: RemoveCursor erases the cursor by replacing the background ! 391: // image that was saved by the previous call to DisplayCursor. ! 392: // If the frame buffer is cacheable, flush at the end of the ! 393: // drawing operation. ! 394: { ! 395: IODisplayInfo *dpy; ! 396: StdFBShmem_t *shmem; ! 397: short i, j, width; ! 398: vm_offset_t startPtr; ! 399: unsigned int vramRow; ! 400: Bounds saveRect; ! 401: unsigned short *vramPtr; ! 402: unsigned short *savePtr; ! 403: ! 404: dpy = [inst displayInfo]; ! 405: shmem = GetShmem(inst); ! 406: saveRect = shmem->saveRect; ! 407: vramRow = dpy->totalWidth; /* Scanline width in pixels */ ! 408: vramPtr = (unsigned short *)dpy->frameBuffer + ! 409: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) ! 410: + (saveRect.minx - shmem->screenBounds.minx); ! 411: width = saveRect.maxx - saveRect.minx; ! 412: vramRow -= width; ! 413: savePtr = shmem->cursor.rgb.save; ! 414: startPtr = (vm_offset_t) vramPtr; ! 415: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) { ! 416: for (j = width; --j != -1; ) ! 417: *vramPtr++ = *savePtr++; ! 418: vramPtr += vramRow; ! 419: } ! 420: } ! 421: ! 422: static void StdFBRemoveCursor8(IOFrameBufferDisplay *inst) ! 423: // Description: RemoveCursor erases the cursor by replacing the background ! 424: // image that was saved by the previous call to DisplayCursor. ! 425: // If the frame buffer is cacheable, flush at the end of the ! 426: // drawing operation. ! 427: { ! 428: IODisplayInfo *dpy; ! 429: StdFBShmem_t *shmem; ! 430: short i, j, width; ! 431: vm_offset_t startPtr; ! 432: unsigned int vramRow; ! 433: Bounds saveRect; ! 434: unsigned char *vramPtr; ! 435: unsigned char *savePtr; ! 436: ! 437: dpy = [inst displayInfo]; ! 438: shmem = GetShmem(inst); ! 439: saveRect = shmem->saveRect; ! 440: vramRow = dpy->totalWidth; /* Scanline width in pixels */ ! 441: vramPtr = (unsigned char *)dpy->frameBuffer + ! 442: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) ! 443: + (saveRect.minx - shmem->screenBounds.minx); ! 444: width = saveRect.maxx - saveRect.minx; ! 445: vramRow -= width; ! 446: savePtr = shmem->cursor.bw8.save; ! 447: startPtr = (vm_offset_t) vramPtr; ! 448: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) { ! 449: for (j = width; --j != -1; ) ! 450: *vramPtr++ = *savePtr++; ! 451: vramPtr += vramRow; ! 452: } ! 453: } ! 454: ! 455: static void StdFBDisplayCursor32(IOFrameBufferDisplay *inst) ! 456: { ! 457: IODisplayInfo *dpy; ! 458: StdFBShmem_t *shmem; ! 459: unsigned int vramRow; ! 460: Bounds saveRect; ! 461: int i, j, width, cursRow; ! 462: unsigned int *vramPtr; /* screen data pointer */ ! 463: unsigned int *savePtr; /* saved screen data pointer */ ! 464: unsigned int s, d, f; ! 465: volatile unsigned int *cursPtr; ! 466: ! 467: dpy = [inst displayInfo]; ! 468: shmem = GetShmem(inst); ! 469: saveRect = shmem->cursorRect; ! 470: /* Clip saveRect vertical within screen bounds */ ! 471: if (saveRect.miny < shmem->screenBounds.miny) ! 472: saveRect.miny = shmem->screenBounds.miny; ! 473: if (saveRect.maxy > shmem->screenBounds.maxy) ! 474: saveRect.maxy = shmem->screenBounds.maxy; ! 475: if (saveRect.minx < shmem->screenBounds.minx) ! 476: saveRect.minx = shmem->screenBounds.minx; ! 477: if (saveRect.maxx > shmem->screenBounds.maxx) ! 478: saveRect.maxx = shmem->screenBounds.maxx; ! 479: shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */ ! 480: ! 481: vramRow = dpy->totalWidth; /* Scanline width in pixels */ ! 482: vramPtr = (unsigned int *)dpy->frameBuffer + ! 483: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) + ! 484: (saveRect.minx - shmem->screenBounds.minx); ! 485: width = saveRect.maxx - saveRect.minx; ! 486: vramRow -= width; ! 487: ! 488: cursRow = CURSORWIDTH - width; ! 489: savePtr = shmem->cursor.rgb24.save; ! 490: cursPtr = shmem->cursor.rgb24.image[shmem->frame]; ! 491: cursPtr += (saveRect.miny - shmem->cursorRect.miny) * CURSORWIDTH + ! 492: (saveRect.minx - shmem->cursorRect.minx); ! 493: ! 494: if (dpy->pixelEncoding[0] == IO_SampleTypeAlpha || ! 495: dpy->pixelEncoding[0] == IO_SampleTypeSkip) { ! 496: /* Pixel format is Axxx */ ! 497: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) { ! 498: for (j = width; --j != -1; ) { ! 499: d = *savePtr++ = *vramPtr; ! 500: s = *cursPtr++; ! 501: f = s >> 24; ! 502: if (f) { ! 503: if (f == 0xff) // Opaque pixel ! 504: *vramPtr++ = s; ! 505: else { // SOVER the cursor pixel ! 506: s <<= 8; d <<= 8; /* Now pixels are xxxA */ ! 507: f ^= 0xFF; ! 508: d = s+(((((d&0xFF00FF00)>>8)*f+0x00FF00FF)&0xFF00FF00) ! 509: | ((((d & 0x00FF00FF)*f+0x00FF00FF)>>8) & ! 510: 0x00FF00FF)); ! 511: *vramPtr++ = (d>>8) | 0xff000000; ! 512: } ! 513: } else // Transparent cursor pixel ! 514: vramPtr++; ! 515: } ! 516: cursPtr += cursRow; /* starting point of next cursor line */ ! 517: vramPtr += vramRow; /* starting point of next screen line */ ! 518: } ! 519: } else { ! 520: /* Pixel format is xxxA */ ! 521: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) { ! 522: for (j = width; --j != -1; ) { ! 523: d = *savePtr++ = *vramPtr; ! 524: s = *cursPtr++; ! 525: f = s & (unsigned int)0xFF; ! 526: if (f) { ! 527: if (f == 0xff) // Opaque pixel ! 528: *vramPtr++ = s; ! 529: else { // SOVER the cursor pixel ! 530: f ^= 0xFF; ! 531: d = s+(((((d&0xFF00FF00)>>8)*f+0x00FF00FF)&0xFF00FF00) ! 532: | ((((d & 0x00FF00FF)*f+0x00FF00FF)>>8) & ! 533: 0x00FF00FF)); ! 534: *vramPtr++ = d; ! 535: } ! 536: } else // Transparent cursor pixel ! 537: vramPtr++; ! 538: } ! 539: cursPtr += cursRow; /* starting point of next cursor line */ ! 540: vramPtr += vramRow; /* starting point of next screen line */ ! 541: } ! 542: } ! 543: } ! 544: ! 545: static void StdFBRemoveCursor32(IOFrameBufferDisplay *inst) ! 546: { ! 547: IODisplayInfo *dpy; ! 548: StdFBShmem_t *shmem; ! 549: int i, j, width; ! 550: unsigned int vramRow; ! 551: Bounds saveRect; ! 552: unsigned int *vramPtr; ! 553: unsigned int *savePtr; ! 554: ! 555: dpy = [inst displayInfo]; ! 556: shmem = GetShmem(inst); ! 557: saveRect = shmem->saveRect; ! 558: vramRow = dpy->totalWidth; /* Scanline width in pixels */ ! 559: vramPtr = (unsigned int *)dpy->frameBuffer + ! 560: (vramRow * (saveRect.miny - shmem->screenBounds.miny)) ! 561: + (saveRect.minx - shmem->screenBounds.minx); ! 562: width = saveRect.maxx - saveRect.minx; ! 563: vramRow -= width; ! 564: savePtr = (unsigned int *)shmem->cursor.rgb24.save; ! 565: for (i = saveRect.maxy - saveRect.miny; --i != -1; ) { ! 566: for (j = width; --j != -1; ) ! 567: *vramPtr++ = *savePtr++; ! 568: vramPtr += vramRow; ! 569: } ! 570: } ! 571: ! 572: static inline void StdFBDisplayCursor(IOFrameBufferDisplay *inst) ! 573: { ! 574: switch ([inst displayInfo]->bitsPerPixel) { ! 575: default: ! 576: case IO_12BitsPerPixel: ! 577: case IO_15BitsPerPixel: ! 578: StdFBDisplayCursor16(inst); ! 579: break; ! 580: case IO_8BitsPerPixel: ! 581: StdFBDisplayCursor8(inst); ! 582: break; ! 583: case IO_24BitsPerPixel: ! 584: StdFBDisplayCursor32(inst); ! 585: break; ! 586: } ! 587: } ! 588: ! 589: static inline void StdFBRemoveCursor(IOFrameBufferDisplay *inst) ! 590: { ! 591: switch ([inst displayInfo]->bitsPerPixel) { ! 592: default: ! 593: case IO_12BitsPerPixel: ! 594: case IO_15BitsPerPixel: ! 595: StdFBRemoveCursor16(inst); ! 596: break; ! 597: case IO_8BitsPerPixel: ! 598: StdFBRemoveCursor8(inst); ! 599: break; ! 600: case IO_24BitsPerPixel: ! 601: StdFBRemoveCursor32(inst); ! 602: break; ! 603: } ! 604: } ! 605: ! 606: ! 607: #define RemoveCursor(inst) StdFBRemoveCursor(inst) ! 608: static inline void DisplayCursor(IOFrameBufferDisplay *inst) ! 609: { ! 610: Point hs; ! 611: StdFBShmem_t *shmem; ! 612: ! 613: shmem = GetShmem(inst); ! 614: hs = shmem->hotSpot[shmem->frame]; ! 615: shmem->cursorRect.maxx = ! 616: (shmem->cursorRect.minx = (shmem->cursorLoc).x - hs.x) + 16; ! 617: shmem->cursorRect.maxy = ! 618: (shmem->cursorRect.miny = (shmem->cursorLoc).y - hs.y) + 16; ! 619: StdFBDisplayCursor(inst); ! 620: shmem->oldCursorRect = shmem->cursorRect; ! 621: } ! 622: ! 623: static inline void SysHideCursor(IOFrameBufferDisplay *inst) ! 624: { ! 625: if (!GetShmem(inst)->cursorShow++) ! 626: RemoveCursor(inst); ! 627: } ! 628: ! 629: static inline void SysShowCursor(IOFrameBufferDisplay *inst) ! 630: { ! 631: if (GetShmem(inst)->cursorShow) ! 632: if (!--(GetShmem(inst)->cursorShow)) ! 633: DisplayCursor(inst); ! 634: } ! 635: ! 636: static inline void CheckShield(IOFrameBufferDisplay *inst) ! 637: { ! 638: Point hs; ! 639: int intersect; ! 640: Bounds tempRect; ! 641: StdFBShmem_t *shmem; ! 642: ! 643: shmem = GetShmem(inst); ! 644: /* Calculate temp cursorRect */ ! 645: hs = shmem->hotSpot[shmem->frame]; ! 646: tempRect.maxx = (tempRect.minx = (shmem->cursorLoc).x - hs.x) + 16; ! 647: tempRect.maxy = (tempRect.miny = (shmem->cursorLoc).y - hs.y) + 16; ! 648: ! 649: intersect = TOUCHBOUNDS(tempRect, shmem->shieldRect); ! 650: if (intersect != shmem->shielded) ! 651: (shmem->shielded = intersect) ? ! 652: SysHideCursor(inst) : SysShowCursor(inst); ! 653: } ! 654: // ! 655: // END: Generic utility routines ! 656: // ! 657: ! 658: ! 659: // ! 660: // BEGIN: Implementation of the evScreen protocol ! 661: // ! 662: - hideCursor: (int)token ! 663: { ! 664: SETSEMA(GetShmem(self)); ! 665: SysHideCursor(self); ! 666: CLEARSEMA(GetShmem(self)); ! 667: return self; ! 668: } ! 669: ! 670: - moveCursor:(Point*)cursorLoc frame:(int)frame token:(int)t ! 671: { ! 672: StdFBShmem_t *shmem; ! 673: ! 674: shmem = GetShmem(self); ! 675: SETSEMA(shmem); ! 676: shmem->frame = frame; ! 677: shmem->cursorLoc = *cursorLoc; ! 678: if (!shmem->cursorShow++) ! 679: RemoveCursor(self); ! 680: if (shmem->cursorObscured) { ! 681: shmem->cursorObscured = 0; ! 682: if (shmem->cursorShow) ! 683: --shmem->cursorShow; ! 684: } ! 685: if (shmem->shieldFlag) CheckShield(self); ! 686: if (shmem->cursorShow) ! 687: if (!--shmem->cursorShow) ! 688: DisplayCursor(self); ! 689: CLEARSEMA(shmem); ! 690: return self; ! 691: } ! 692: ! 693: - showCursor:(Point*)cursorLoc frame:(int)frame token:(int)t ! 694: { ! 695: StdFBShmem_t *shmem; ! 696: ! 697: shmem = GetShmem(self); ! 698: SETSEMA(GetShmem(self)); ! 699: shmem->frame = frame; ! 700: shmem->cursorLoc = *cursorLoc; ! 701: if (shmem->shieldFlag) CheckShield(self); ! 702: SysShowCursor(self); ! 703: CLEARSEMA(shmem); ! 704: return self; ! 705: } ! 706: ! 707: - setBrightness:(int)level token:(int)t ! 708: { ! 709: if ( level < EV_SCREEN_MIN_BRIGHTNESS ! 710: || level > EV_SCREEN_MAX_BRIGHTNESS ) ! 711: { ! 712: IOLog("%s: Invalid arg to setBrightness:%d\n", ! 713: [self name], level ); ! 714: } ! 715: return self; ! 716: } ! 717: // ! 718: // END: Implementation of the evScreen protocol ! 719: // ! 720: // ! 721: // BEGIN: EXPORTED Methods ! 722: // ! 723: + (BOOL)probe:deviceDescription ! 724: { ! 725: IOFrameBufferDisplay *inst; ! 726: ! 727: // Create an instance and initialize some basic instance variables. ! 728: inst = [[self alloc] initFromDeviceDescription:deviceDescription]; ! 729: if (inst == nil) ! 730: return NO; ! 731: ! 732: [inst setDeviceKind:"Linear Framebuffer"]; ! 733: ! 734: [inst registerDevice]; ! 735: ! 736: return YES; ! 737: } ! 738: ! 739: - initFromDeviceDescription:deviceDescription ! 740: { ! 741: extern int sprintf(char *s, const char *format, ...); ! 742: static int nextUnit = 0; ! 743: char nameBuf[20]; ! 744: ! 745: if ([super initFromDeviceDescription:deviceDescription] == nil) ! 746: return [super free]; ! 747: ! 748: _currentDisplayMode = _pendingDisplayMode = -1; ! 749: _displayModeCount = -1; _displayModes = NULL; ! 750: ! 751: sprintf(nameBuf, "Display%d", nextUnit); ! 752: [self setUnit: nextUnit++]; ! 753: [self setName:nameBuf]; ! 754: return self; ! 755: } ! 756: ! 757: - (IOConsoleInfo *)allocateConsoleInfo; ! 758: // Description: Allocates a console support info structure based on this ! 759: // display. This structure, and the functions in it, are used ! 760: // to display alert and console windows. ! 761: { ! 762: return FBAllocateConsole([self displayInfo]); ! 763: } ! 764: ! 765: static const char * ! 766: find_parameter(const char *parameter, const char *string) ! 767: { ! 768: int c; ! 769: size_t length; ! 770: ! 771: length = strlen(parameter); ! 772: while (*string != 0) { ! 773: if (strncmp(string, parameter, length) == 0) { ! 774: string += length; ! 775: while ((c = *string) != '\0' && (c == ' ' || c == '\t')) ! 776: string++; ! 777: return (c != 0) ? string : 0; ! 778: } ! 779: string++; ! 780: } ! 781: return 0; ! 782: } ! 783: ! 784: ! 785: // Description: Get parameters for the display object. These include support ! 786: // for getting the frame buffer parameters, registering it ! 787: // with the event system, returning the registration token. ! 788: ! 789: - (IOReturn)getIntValues:(unsigned *)parameterArray ! 790: forParameter:(IOParameterName)parameterName ! 791: count:(unsigned int *)count ! 792: { ! 793: unsigned int fb_dimensions[STDFB_FB_DIMENSIONS_SIZE]; ! 794: IOReturn r; ! 795: int i; ! 796: unsigned *returnedCount = count; ! 797: unsigned maxCount = *count; ! 798: ! 799: if (strcmp(parameterName, STDFB_FB_MAP) == 0) { ! 800: parameterArray[0] = 0; ! 801: [self revertToVGAMode]; // start from a well-defined state ! 802: [self enterLinearMode]; ! 803: [kmId registerDisplay:self]; ! 804: *returnedCount = 1; ! 805: return IO_R_SUCCESS; ! 806: ! 807: } else if (strcmp(parameterName, STDFB_FB_DIMENSIONS) == 0) { ! 808: IODisplayInfo *display = [self displayInfo]; ! 809: ! 810: fb_dimensions[STDFB_FB_WIDTH] = display->width; ! 811: fb_dimensions[STDFB_FB_HEIGHT] = display->height; ! 812: fb_dimensions[STDFB_FB_ROWBYTES] = display->rowBytes; ! 813: fb_dimensions[STDFB_FB_FLAGS] = display->flags; ! 814: switch (display->bitsPerPixel) { ! 815: case IO_2BitsPerPixel: ! 816: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 2; break; ! 817: case IO_8BitsPerPixel: ! 818: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 8; break; ! 819: case IO_12BitsPerPixel: ! 820: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 12; break; ! 821: case IO_15BitsPerPixel: ! 822: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 15; break; ! 823: case IO_24BitsPerPixel: ! 824: fb_dimensions[STDFB_FB_BITS_PER_PIXEL] = 32; break; ! 825: default: ! 826: /* Should return an error. */ ! 827: break; ! 828: } ! 829: ! 830: *returnedCount = 0; ! 831: for( i=0; i<STDFB_FB_DIMENSIONS_SIZE; i++) { ! 832: if (*returnedCount == maxCount) ! 833: break; ! 834: parameterArray[i] = fb_dimensions[i]; ! 835: (*returnedCount)++; ! 836: } ! 837: return IO_R_SUCCESS; ! 838: ! 839: } else if (strcmp(parameterName, STDFB_FB_REGISTER) == 0) { ! 840: r = [self _registerWithED]; ! 841: *returnedCount = 0; ! 842: if (maxCount > 0) { ! 843: *returnedCount = 1; ! 844: parameterArray[0] = [self token]; ! 845: } ! 846: return r; ! 847: ! 848: } else if (strcmp(parameterName, IO_GET_DISPLAY_INFO) == 0) { ! 849: const IODisplayInfo *displayInfo; ! 850: if ((*count != 5) && (*count != 7)) ! 851: return IO_R_INVALID_ARG; ! 852: displayInfo = [self displayInfo]; ! 853: parameterArray[0] = displayInfo->width; ! 854: parameterArray[1] = displayInfo->height; ! 855: parameterArray[2] = displayInfo->refreshRate; ! 856: parameterArray[3] = (unsigned)displayInfo->bitsPerPixel; ! 857: parameterArray[4] = (unsigned)displayInfo->colorSpace; ! 858: if (*count == 7) { ! 859: parameterArray[5] = displayInfo->totalWidth; ! 860: parameterArray[6] = displayInfo->rowBytes; ! 861: } ! 862: return IO_R_SUCCESS; ! 863: ! 864: } else if (strcmp(parameterName, IO_GET_DISPLAY_MODE_NUM) == 0) { ! 865: if (*count != 1) ! 866: return IO_R_INVALID_ARG; ! 867: parameterArray[0] = [self displayModeCount]; ! 868: return IO_R_SUCCESS; ! 869: } else if (strncmp(parameterName, IO_GET_DISPLAY_MODE_INFO, ! 870: sizeof(IO_GET_DISPLAY_MODE_INFO)-1) == 0) { ! 871: const IODisplayInfo *displayInfo, *displayModes; ! 872: const char *s; ! 873: int mode; ! 874: ! 875: if (*count != 14) { ! 876: return IO_R_INVALID_ARG; ! 877: } ! 878: s = find_parameter(IO_GET_DISPLAY_MODE_INFO, parameterName); ! 879: if (s == 0) { ! 880: return IO_R_INVALID_ARG; ! 881: } ! 882: mode = strtol(s, 0, 10); ! 883: if (mode < 0 || mode >= [self displayModeCount]) ! 884: return IO_R_INVALID_ARG; ! 885: ! 886: displayModes = [self displayModes]; ! 887: displayInfo = &displayModes[mode]; ! 888: ! 889: parameterArray[0] = displayInfo->width; ! 890: parameterArray[1] = displayInfo->height; ! 891: parameterArray[2] = displayInfo->refreshRate; ! 892: parameterArray[3] = (unsigned)displayInfo->bitsPerPixel; ! 893: parameterArray[4] = (unsigned)displayInfo->colorSpace; ! 894: parameterArray[5] = displayInfo->totalWidth; ! 895: parameterArray[6] = displayInfo->rowBytes; ! 896: ! 897: parameterArray[7] = displayInfo->memorySize; ! 898: parameterArray[8] = displayInfo->scanRate; ! 899: parameterArray[9] = 0; ! 900: parameterArray[10] = displayInfo->dotClockRate; ! 901: parameterArray[11] = displayInfo->screenWidth; ! 902: parameterArray[12] = displayInfo->screenHeight; ! 903: parameterArray[13] = displayInfo->modeUnavailableFlag; ! 904: ! 905: return IO_R_SUCCESS; ! 906: } else if (strcmp(parameterName, IO_GET_DISPLAY_MEMORY) == 0) { ! 907: if (*count != 1) ! 908: return IO_R_INVALID_ARG; ! 909: parameterArray[0] = [self displayMemorySize]; ! 910: return IO_R_SUCCESS; ! 911: } else if (strcmp(parameterName, IO_GET_RAMDAC_SPEED) == 0) { ! 912: if (*count != 1) ! 913: return IO_R_INVALID_ARG; ! 914: parameterArray[0] = [self ramdacSpeed]; ! 915: return IO_R_SUCCESS; ! 916: } else if (strcmp(parameterName, IO_GET_CURRENT_DISPLAY_MODE) == 0) { ! 917: if (*count != 1) ! 918: return IO_R_INVALID_ARG; ! 919: if (_currentDisplayMode >= 0) { ! 920: parameterArray[0] = _currentDisplayMode; ! 921: return IO_R_SUCCESS; ! 922: } else { ! 923: return IO_R_UNDEFINED_MODE; ! 924: } ! 925: } else if (strcmp(parameterName, IO_GET_PENDING_DISPLAY_MODE) == 0) { ! 926: if (*count != 1) ! 927: return IO_R_INVALID_ARG; ! 928: if (_pendingDisplayMode >= 0) { ! 929: parameterArray[0] = _pendingDisplayMode; ! 930: return IO_R_SUCCESS; ! 931: } else { ! 932: return IO_R_UNDEFINED_MODE; ! 933: } ! 934: ! 935: } else if (strncmp(parameterName, IO_SET_PENDING_DISPLAY_MODE, ! 936: sizeof(IO_SET_PENDING_DISPLAY_MODE) - 1 ) == 0) { ! 937: const char *s; ! 938: int mode; ! 939: ! 940: if (*count != 0) { ! 941: return IO_R_INVALID_ARG; ! 942: } ! 943: s = find_parameter(IO_SET_PENDING_DISPLAY_MODE, parameterName); ! 944: if (s == 0) { ! 945: return IO_R_INVALID_ARG; ! 946: } ! 947: mode = strtol(s, 0, 10); ! 948: ! 949: if ([self setPendingDisplayMode:mode] == YES) { ! 950: return IO_R_SUCCESS; ! 951: } else { ! 952: return IO_R_FAILED_TO_SET_MODE; ! 953: } ! 954: ! 955: } else { ! 956: return [super getIntValues:parameterArray ! 957: forParameter:parameterName ! 958: count:count]; ! 959: } ! 960: } ! 961: ! 962: ! 963: /* Set parameters for the display object. This can be used to unregister the ! 964: * frame buffer as well as to set the transfer function. ! 965: */ ! 966: - (IOReturn)setIntValues:(unsigned *)parameterArray ! 967: forParameter:(IOParameterName)parameterName ! 968: count:(unsigned int)count ! 969: { ! 970: int i; ! 971: ! 972: if (strcmp(parameterName, STDFB_FB_UNMAP) == 0) { ! 973: [self revertToVGAMode]; ! 974: //[self unMapFrameBuffer]; ! 975: return IO_R_SUCCESS; ! 976: ! 977: } else if (strcmp(parameterName, STDFB_FB_UNREGISTER) == 0) { ! 978: if (count != 1) ! 979: return IO_R_INVALID_ARG; ! 980: [[EventDriver instance] unregisterScreen:parameterArray[0]]; ! 981: return IO_R_SUCCESS; ! 982: ! 983: } else if (strcmp(parameterName, IO_SET_TRANSFER_TABLE) == 0) { ! 984: switch ([self displayInfo]->bitsPerPixel) { ! 985: case IO_2BitsPerPixel: ! 986: if (count != IO_2BPP_TRANSFER_TABLE_SIZE) ! 987: return IO_R_INVALID_ARG; ! 988: break; ! 989: case IO_8BitsPerPixel: ! 990: if (count != IO_8BPP_TRANSFER_TABLE_SIZE) ! 991: return IO_R_INVALID_ARG; ! 992: break; ! 993: case IO_12BitsPerPixel: ! 994: if (count != IO_12BPP_TRANSFER_TABLE_SIZE) ! 995: return IO_R_INVALID_ARG; ! 996: break; ! 997: case IO_15BitsPerPixel: ! 998: if (count != IO_15BPP_TRANSFER_TABLE_SIZE) ! 999: return IO_R_INVALID_ARG; ! 1000: break; ! 1001: case IO_24BitsPerPixel: ! 1002: if (count != IO_24BPP_TRANSFER_TABLE_SIZE) ! 1003: return IO_R_INVALID_ARG; ! 1004: break; ! 1005: default: ! 1006: return IO_R_INVALID_ARG; ! 1007: } ! 1008: [self setTransferTable:parameterArray count:count]; ! 1009: return IO_R_SUCCESS; ! 1010: ! 1011: } else if (strcmp(parameterName, STDFB_BM256_TO_BM38_MAP) == 0) { ! 1012: if (count != STDFB_BM256_TO_BM38_MAP_SIZE) ! 1013: return IO_R_INVALID_ARG; ! 1014: if (_bm256To38SampleTable == NULL) ! 1015: _bm256To38SampleTable = (unsigned int *) ! 1016: IOMalloc(STDFB_BM256_TO_BM38_MAP_SIZE * sizeof(int)); ! 1017: for (i = 0; i < count; i++) ! 1018: _bm256To38SampleTable[i] = parameterArray[i]; ! 1019: return IO_R_SUCCESS; ! 1020: ! 1021: } else if (strcmp(parameterName, STDFB_BM38_TO_BM256_MAP) == 0) { ! 1022: ! 1023: // For NeXT logical palette to real palette conversion, an additional ! 1024: // 256 bytes can be added to the table ! 1025: #define STDFB_BM38_TO_256_WITH_LOGICAL_SIZE (STDFB_BM38_TO_BM256_MAP_SIZE + (256/sizeof(int))) ! 1026: ! 1027: if ((count != STDFB_BM38_TO_BM256_MAP_SIZE) && (count != STDFB_BM38_TO_256_WITH_LOGICAL_SIZE)) ! 1028: return IO_R_INVALID_ARG; ! 1029: if (_bm38To256SampleTable == NULL) { ! 1030: _bm38To256SampleTable = (unsigned char *) ! 1031: IOMalloc(STDFB_BM38_TO_256_WITH_LOGICAL_SIZE * sizeof(int)); ! 1032: } ! 1033: if( count != STDFB_BM38_TO_256_WITH_LOGICAL_SIZE) ! 1034: for (i = 0; i < 256; i++) ! 1035: _bm38To256SampleTable[ 1024 + i ] = i; ! 1036: for (i = 0; i < count; i++) ! 1037: *(((unsigned int *)_bm38To256SampleTable) + i) = parameterArray[i]; ! 1038: return IO_R_SUCCESS; ! 1039: ! 1040: } else if (strcmp(parameterName, IO_SET_PENDING_DISPLAY_MODE) == 0) { ! 1041: if (count != 1) ! 1042: return IO_R_INVALID_ARG; ! 1043: if ([self setPendingDisplayMode:parameterArray[0]] == YES) { ! 1044: return IO_R_SUCCESS; ! 1045: } else { ! 1046: return IO_R_FAILED_TO_SET_MODE; ! 1047: } ! 1048: } else { ! 1049: return [super setIntValues:parameterArray forParameter:parameterName ! 1050: count:count]; ! 1051: } ! 1052: } ! 1053: ! 1054: /* ! 1055: * This is the first message sent by the windowserver. If there is a pending ! 1056: * display mode then we commit to it (i.e. update our IODisplayInfo ! 1057: * structure). ! 1058: */ ! 1059: #define IO_POSTSCRIPT_DRIVER "PostScript Driver" ! 1060: ! 1061: /* Get parameters for the display object. ! 1062: */ ! 1063: - (IOReturn)getCharValues:(unsigned char *)parameterArray ! 1064: forParameter:(IOParameterName)parameterName ! 1065: count:(unsigned *)count ! 1066: { ! 1067: if (strcmp(parameterName, STDFB_FB_PIXEL_ENCODING) == 0) { ! 1068: if (*count != STDFB_FB_PIXEL_ENCODING_SIZE) ! 1069: return IO_R_INVALID_ARG; ! 1070: ! 1071: /* Copy the format string out of the display structure */ ! 1072: strncpy(parameterArray, [self displayInfo]->pixelEncoding, ! 1073: STDFB_FB_PIXEL_ENCODING_SIZE); ! 1074: return IO_R_SUCCESS; ! 1075: } else if (strcmp(parameterName, IO_POSTSCRIPT_DRIVER) == 0) { ! 1076: /* ! 1077: * FIXME: This is a temporary hack till WS gets fixed. At that time ! 1078: * WS will use IO_COMMIT_TO_PENDING_DISPLAY_MODE and this code can be ! 1079: * deleted. -- rkd. ! 1080: */ ! 1081: if (_pendingDisplayMode >= 0) { ! 1082: (void) [self _commitToPendingMode]; ! 1083: _pendingDisplayMode = -1; /* mode switch is complete */ ! 1084: } ! 1085: return [super getCharValues:parameterArray ! 1086: forParameter:parameterName ! 1087: count:count]; ! 1088: } else { ! 1089: return [super getCharValues:parameterArray ! 1090: forParameter:parameterName ! 1091: count:count]; ! 1092: } ! 1093: } ! 1094: ! 1095: // Description: Set parameters for the display object. This can be used ! 1096: // to set the mapping tables used for conversion between ! 1097: // 4 BPS and 5 BPS data in 5-5-5 frame buffer support, ! 1098: // and bm256 <--> bm38 conversion tables as well. ! 1099: // ! 1100: - (IOReturn)setCharValues:(unsigned char *)parameterArray ! 1101: forParameter:(IOParameterName)parameterName ! 1102: count:(unsigned int)count ! 1103: { ! 1104: int i, mode; ! 1105: ! 1106: if (strcmp(parameterName, STDFB_4BPS_TO_5BPS_MAP) == 0) { ! 1107: if (count != STDFB_4BPS_TO_5BPS_MAP_SIZE) ! 1108: return IO_R_INVALID_ARG; ! 1109: if (_bm34To35SampleTable == NULL) ! 1110: _bm34To35SampleTable = IOMalloc(STDFB_4BPS_TO_5BPS_MAP_SIZE); ! 1111: for (i = 0; i < count; i++) ! 1112: _bm34To35SampleTable[i] = parameterArray[i]; ! 1113: return IO_R_SUCCESS; ! 1114: ! 1115: } else if (strcmp(parameterName, STDFB_5BPS_TO_4BPS_MAP) == 0) { ! 1116: if (count != STDFB_5BPS_TO_4BPS_MAP_SIZE) ! 1117: return IO_R_INVALID_ARG; ! 1118: if (_bm35To34SampleTable == NULL) ! 1119: _bm35To34SampleTable = IOMalloc(STDFB_5BPS_TO_4BPS_MAP_SIZE); ! 1120: for (i = 0; i < count; i++) ! 1121: _bm35To34SampleTable[i] = parameterArray[i]; ! 1122: return IO_R_SUCCESS; ! 1123: } else if (strcmp(parameterName, IO_COMMIT_TO_PENDING_DISPLAY_MODE) == 0) { ! 1124: if (_pendingDisplayMode >= 0) { ! 1125: (void) [self _commitToPendingMode]; ! 1126: _pendingDisplayMode = -1; /* mode switch is complete */ ! 1127: return IO_R_SUCCESS; ! 1128: } else { ! 1129: return IO_R_UNSUPPORTED; ! 1130: } ! 1131: } else { ! 1132: return [super setCharValues:parameterArray ! 1133: forParameter:parameterName ! 1134: count:count]; ! 1135: } ! 1136: } ! 1137: ! 1138: - (void)enterLinearMode; ! 1139: // Description: Put the display into linear framebuffer mode. This typically ! 1140: // happens when the window server starts running. This method ! 1141: // is implemented by subclasses in a device specific way. The ! 1142: // value returned is a pointer to the framebuffer in user space. ! 1143: { ! 1144: } ! 1145: ! 1146: - (void)revertToVGAMode; ! 1147: // Description: Get the device out of whatever advanced linear mode it was ! 1148: // using and back into a state where it can be used as a standard ! 1149: // VGA device. This method is implemented by subclasses in a ! 1150: // device specific way. ! 1151: { ! 1152: } ! 1153: ! 1154: - (BOOL)setPendingDisplayMode:(int)displayMode ! 1155: { ! 1156: IODisplayInfo *displayInfo; ! 1157: ! 1158: displayInfo = [self displayInfo]; // current mode ! 1159: ! 1160: if (displayMode < 0 || displayMode >= [self displayModeCount]) { ! 1161: IOLog("%s: Invalid display mode: %d\n", [self name], displayMode); ! 1162: return NO; ! 1163: } ! 1164: if (displayInfo->modeUnavailableFlag != 0) { ! 1165: IOLog("%s: Display mode %d not available (error 0x%0x)\n", ! 1166: [self name], displayMode, displayInfo->modeUnavailableFlag); ! 1167: return NO; ! 1168: } ! 1169: _pendingDisplayMode = displayMode; ! 1170: return YES; ! 1171: } ! 1172: ! 1173: - (int)pendingDisplayMode ! 1174: { ! 1175: return _pendingDisplayMode; ! 1176: } ! 1177: ! 1178: /* ! 1179: * The subclass must implement these two methods if it want display mode ! 1180: * changes. ! 1181: */ ! 1182: - (unsigned int)displayModeCount ! 1183: { ! 1184: return _displayModeCount; ! 1185: } ! 1186: ! 1187: - (IODisplayInfo *)displayModes ! 1188: { ! 1189: return _displayModes; ! 1190: } ! 1191: ! 1192: /* ! 1193: * Subclass should override and supply appropriate values. ! 1194: */ ! 1195: - (unsigned int)displayMemorySize ! 1196: { ! 1197: return 0; ! 1198: } ! 1199: ! 1200: - (unsigned int)ramdacSpeed ! 1201: { ! 1202: return 0; ! 1203: } ! 1204: ! 1205: - (vm_address_t)mapFrameBufferAtPhysicalAddress:(unsigned int)addr ! 1206: length:(int)length; ! 1207: // Description: Look up the physical memory location for this device instance ! 1208: // and map it into VM for use by the device driver. If problems ! 1209: // occur, the method returns (vm_address_t)0. If addr is not 0, ! 1210: // then it is used as the physical memory address and ! 1211: // length is used as the length. ! 1212: { ! 1213: vm_address_t vmLocation; ! 1214: IOReturn result = IO_R_SUCCESS; ! 1215: IOCache cacheType; ! 1216: ! 1217: switch ([self displayInfo]->flags & IO_DISPLAY_CACHE_MASK) { ! 1218: default: ! 1219: case IO_DISPLAY_CACHE_WRITETHROUGH: ! 1220: cacheType = IO_WriteThrough; ! 1221: break; ! 1222: case IO_DISPLAY_CACHE_COPYBACK: ! 1223: cacheType = IO_CopyBack; ! 1224: break; ! 1225: case IO_DISPLAY_CACHE_OFF: ! 1226: cacheType = IO_CacheOff; ! 1227: break; ! 1228: } ! 1229: ! 1230: if (addr != 0) // Override configuration XXX BOGUS!!! ! 1231: { ! 1232: // This is totally bogus. I cannot believe that it is ! 1233: // public API. NB: This mapping cannot be freed using ! 1234: // unmapMemoryRange:from: in IOEISADirectDevice. ! 1235: if (_KernBusMemoryCreateMapping(addr, ! 1236: length, ! 1237: &vmLocation, ! 1238: current_task_EXTERNAL(), ! 1239: YES, ! 1240: cacheType) != KERN_SUCCESS) ! 1241: result = IO_R_NO_MEMORY; ! 1242: } ! 1243: else ! 1244: { ! 1245: result = [self mapMemoryRange:0 ! 1246: to:&vmLocation ! 1247: findSpace:YES ! 1248: cache:cacheType]; ! 1249: } ! 1250: ! 1251: if (result != IO_R_SUCCESS) ! 1252: { ! 1253: IOLog( ! 1254: "IOFrameBufferDisplay/mapFrameBuffer: Can't map memory (%s)\n", ! 1255: [self stringFromReturn:result]); ! 1256: return (vm_address_t)0; ! 1257: } ! 1258: ! 1259: return vmLocation; ! 1260: } ! 1261: ! 1262: #if 0 ! 1263: - (vm_address_t)mapFrameBufferAtPhysicalAddress:(unsigned int)addr ! 1264: length:(int)length; ! 1265: // Description: Look up the physical memory location for this device instance ! 1266: // and map it into VM for use by the device driver. If problems ! 1267: // occur, the method returns (vm_address_t)0. If addr is not 0, ! 1268: // then it is used as the physical memory address and ! 1269: // length is used as the length. ! 1270: { ! 1271: vm_address_t vmLocation; ! 1272: IOReturn result = IO_R_SUCCESS; ! 1273: IOCache cacheType; ! 1274: IORange *range; ! 1275: ! 1276: /* The default is no cache */ ! 1277: switch ([self displayInfo]->flags & IO_DISPLAY_CACHE_MASK) { ! 1278: default: ! 1279: case IO_DISPLAY_CACHE_WRITETHROUGH: ! 1280: cacheType = IO_WriteThrough; ! 1281: break; ! 1282: case IO_DISPLAY_CACHE_COPYBACK: ! 1283: cacheType = IO_CopyBack; ! 1284: break; ! 1285: case IO_DISPLAY_CACHE_OFF: ! 1286: cacheType = IO_CacheOff; ! 1287: break; ! 1288: } ! 1289: ! 1290: range = [[self deviceDescription] memoryRangeList]; ! 1291: ! 1292: if (addr == 0) ! 1293: addr = range[0].start; ! 1294: if (length == 0) ! 1295: length = range[0].size; ! 1296: ! 1297: /* ! 1298: * The framebuffer must be contained in memory range 0. ! 1299: */ ! 1300: if ((addr < range[0].start) || ! 1301: (addr+length > range[0].start + range[0].size)) { ! 1302: IOLog("%s: framebuffer is not contained in first memory range\n", ! 1303: [self name]); ! 1304: return IO_R_NO_MEMORY; ! 1305: } ! 1306: ! 1307: result = [self mapMemoryRange:0 ! 1308: to:&vmLocation ! 1309: findSpace:YES ! 1310: cache:cacheType]; ! 1311: IOLog("%s: Mapped framed buffer at 0x%x\n", [self name], ! 1312: vmLocation); ! 1313: ! 1314: if (result != IO_R_SUCCESS) { ! 1315: IOLog( ! 1316: "IOFrameBufferDisplay/mapFrameBuffer: Can't map memory (%s)\n", ! 1317: [self stringFromReturn:result]); ! 1318: return (vm_address_t)0; ! 1319: } ! 1320: ! 1321: return vmLocation + (addr - range[0].start); ! 1322: } ! 1323: ! 1324: - (void)unMapFrameBuffer:(unsigned int)addr length:(int)length ! 1325: { ! 1326: void *vmLocation; ! 1327: IORange *range; ! 1328: ! 1329: range = [[self deviceDescription] memoryRangeList]; ! 1330: ! 1331: if (addr == 0) ! 1332: addr = range[0].start; ! 1333: if (length == 0) ! 1334: length = range[0].size; ! 1335: ! 1336: /* ! 1337: * The framebuffer must be contained in memory range 0. ! 1338: */ ! 1339: if ((addr < range[0].start) || ! 1340: (addr+length > range[0].start + range[0].size)) { ! 1341: IOLog("%s: framebuffer is not contained in first memory range\n", ! 1342: [self name]); ! 1343: return IO_R_NO_MEMORY; ! 1344: } ! 1345: ! 1346: vmLocation = [self displayInfo]->frameBuffer - (addr - range[0].start); ! 1347: ! 1348: if (vmLocation) { ! 1349: [self unmapMemoryRange:0 from:(vm_address_t)vmLocation]; ! 1350: } ! 1351: } ! 1352: #endif 0 ! 1353: ! 1354: ! 1355: - (int)selectMode:(const IODisplayInfo *)modeList count:(int)count ! 1356: valid:(const BOOL *)isValid modeString:(const char *)modeString ! 1357: { ! 1358: const char *displayMode; ! 1359: IOConfigTable *configTable; ! 1360: int k, width, height; ! 1361: int screenWidth, screenHeight, memorySize, ramdacSpeed; ! 1362: int scanRate; ! 1363: unsigned int modeUnavailableFlag; ! 1364: IOBitsPerPixel bitsPerPixel; ! 1365: IOColorSpace colorSpace; ! 1366: int refreshRate; ! 1367: const char *s; ! 1368: ! 1369: _displayModeCount = count; ! 1370: _displayModes = modeList; ! 1371: ! 1372: /* Get the string describing the display mode. */ ! 1373: ! 1374: if (modeString == NULL) { ! 1375: ! 1376: configTable = [[self deviceDescription] configTable]; ! 1377: if (configTable == nil) ! 1378: return -1; ! 1379: ! 1380: displayMode = [configTable valueForStringKey:"Display Mode"]; ! 1381: if (displayMode == 0) { ! 1382: /* Historical: for 3.1 drivers only. */ ! 1383: displayMode = [configTable valueForStringKey:"DisplayMode"]; ! 1384: if (displayMode == 0) ! 1385: return -1; ! 1386: } ! 1387: } else { ! 1388: displayMode = modeString; ! 1389: } ! 1390: ! 1391: /* Parse the string. It should be of the form ! 1392: * Width:# Height:# ColorSpace:(BW:#|RGB:###/#) Refresh:# Hz ! 1393: * where `Width' and `Height' specify the width and height of the ! 1394: * framebuffer, `ColorSpace' specifies the color space for the ! 1395: * framebuffer, and `Refresh' specifies the refresh rate in Hz. ! 1396: * The color space parameter should be either BW followed by the ! 1397: * bits/pixel, or RGB followed by the bits/component for each ! 1398: * component followed by the bits/pixel. ! 1399: * ! 1400: * For example, here is the display mode specification for the ! 1401: * RGB mode of the S3: ! 1402: * Width: 800 Height: 600 ColorSpace: RGB:555/16 Refresh: 60 Hz ! 1403: */ ! 1404: ! 1405: height = width = 0; ! 1406: s = find_parameter("Width:", displayMode); ! 1407: if (s != 0) { ! 1408: width = strtol(s, 0, 10); ! 1409: } ! 1410: ! 1411: s = find_parameter("Height:", displayMode); ! 1412: if (s != 0) { ! 1413: height = strtol(s, 0, 10); ! 1414: } ! 1415: ! 1416: s = find_parameter("Refresh:", displayMode); ! 1417: if (s == 0) ! 1418: return -1; ! 1419: refreshRate = strtol(s, 0, 10); ! 1420: ! 1421: s = find_parameter("ColorSpace:", displayMode); ! 1422: if (s == 0) ! 1423: return -1; ! 1424: if (strncmp(s, "BW:2", 4) == 0) { ! 1425: bitsPerPixel = IO_2BitsPerPixel; ! 1426: colorSpace = IO_OneIsBlackColorSpace; ! 1427: } else if (strncmp(s, "BW:8", 4) == 0) { ! 1428: bitsPerPixel = IO_8BitsPerPixel; ! 1429: colorSpace = IO_OneIsWhiteColorSpace; ! 1430: } else if (strncmp(s, "RGB:256/8", 9) == 0) { ! 1431: bitsPerPixel = IO_8BitsPerPixel; ! 1432: colorSpace = IO_RGBColorSpace; ! 1433: } else if (strncmp(s, "RGB:444/16", 10) == 0) { ! 1434: bitsPerPixel = IO_12BitsPerPixel; ! 1435: colorSpace = IO_RGBColorSpace; ! 1436: } else if (strncmp(s, "RGB:555/16", 10) == 0) { ! 1437: bitsPerPixel = IO_15BitsPerPixel; ! 1438: colorSpace = IO_RGBColorSpace; ! 1439: } else if (strncmp(s, "RGB:888/32", 10) == 0) { ! 1440: bitsPerPixel = IO_24BitsPerPixel; ! 1441: colorSpace = IO_RGBColorSpace; ! 1442: } else { ! 1443: return -1; ! 1444: } ! 1445: ! 1446: /* ! 1447: * Now look for 4.0 style optional parameters. The display mode ! 1448: * specification looks like "Resolution:1280x1024 Screen:1600x1200 ! 1449: * Refresh:60Hz ColorSpace:RGB:444/16 Memory:4MB RAMDAC:175Hz Sync:100Hz"; ! 1450: */ ! 1451: ! 1452: s = find_parameter("Resolution:", displayMode); ! 1453: if (s != 0) { ! 1454: char *end; ! 1455: width = strtol(s, &end, 10); ! 1456: height = strtol(end+1, 0, 10); ! 1457: } ! 1458: ! 1459: if ((height == 0) || (width == 0)) ! 1460: return -1; ! 1461: ! 1462: s = find_parameter("Screen:", displayMode); ! 1463: if (s != 0) { ! 1464: char *end; ! 1465: screenWidth = strtol(s, &end, 10); ! 1466: screenHeight = strtol(end+1, 0, 10); ! 1467: } else { ! 1468: screenWidth = width; ! 1469: screenHeight = height; ! 1470: } ! 1471: ! 1472: /* These parameters are not used by the superclass. */ ! 1473: s = find_parameter("Memory:", displayMode); ! 1474: if (s != 0) { ! 1475: memorySize = strtol(s, 0, 10); ! 1476: } ! 1477: ! 1478: s = find_parameter("RAMDAC:", displayMode); ! 1479: if (s != 0) { ! 1480: ramdacSpeed = strtol(s, 0, 10); ! 1481: } ! 1482: ! 1483: s = find_parameter("Sync:", displayMode); ! 1484: if (s != 0) { ! 1485: scanRate = strtol(s, 0, 10); ! 1486: } ! 1487: ! 1488: modeUnavailableFlag = 0; ! 1489: s = find_parameter("Available:", displayMode); ! 1490: if (s != 0) { ! 1491: modeUnavailableFlag = strtol(s, 0, 10); ! 1492: } ! 1493: ! 1494: /* Now try to match these parameters with the list of modes. */ ! 1495: for (k = 0; k < count; k++) { ! 1496: ! 1497: if (isValid != 0 && !isValid[k]) ! 1498: continue; ! 1499: if (modeUnavailableFlag != 0) ! 1500: continue; ! 1501: if (modeList[k].width == width ! 1502: && modeList[k].height == height ! 1503: && modeList[k].colorSpace == colorSpace ! 1504: && modeList[k].bitsPerPixel == bitsPerPixel ! 1505: && modeList[k].refreshRate == refreshRate) { ! 1506: switch (bitsPerPixel) { ! 1507: case IO_2BitsPerPixel: s = "BW:2"; break; ! 1508: case IO_8BitsPerPixel: ! 1509: if (colorSpace == IO_RGBColorSpace) s = "RGB:256/8"; ! 1510: else s = "BW:8"; ! 1511: break; ! 1512: case IO_12BitsPerPixel: s = "RGB:444/16"; break; ! 1513: case IO_15BitsPerPixel: s = "RGB:555/16"; break; ! 1514: case IO_24BitsPerPixel: s = "RGB:888/32"; break; ! 1515: default: s = "Unknown color space"; break; ! 1516: } ! 1517: IOLog("Display: Mode selected: %d x %d @ %d Hz (%s)\n", ! 1518: width, height, refreshRate, s); ! 1519: _currentDisplayMode = k; ! 1520: return k; ! 1521: } ! 1522: } ! 1523: IOLog("Display: Requested mode is not available.\n"); ! 1524: return -1; ! 1525: } ! 1526: ! 1527: - (int)selectMode: (const IODisplayInfo *)modeList count:(int)count ! 1528: { ! 1529: return [self selectMode:modeList count:count valid:0 modeString:NULL]; ! 1530: } ! 1531: ! 1532: - (int)selectMode:(const IODisplayInfo *)modeList count:(int)count ! 1533: valid:(const BOOL *)isValid ! 1534: { ! 1535: return [self selectMode:modeList count:count valid:isValid modeString:NULL]; ! 1536: } ! 1537: ! 1538: - setTransferTable:(const unsigned int *)table count:(int)count ! 1539: { ! 1540: return self; ! 1541: } ! 1542: ! 1543: @end ! 1544: ! 1545: ! 1546: // ! 1547: // BEGIN: PRIVATE Methods ! 1548: // ! 1549: @implementation IOFrameBufferDisplay(Private) ! 1550: ! 1551: - (BOOL)_commitToPendingMode ! 1552: { ! 1553: IODisplayInfo *displayInfo, *displayModes; ! 1554: int mode = _pendingDisplayMode; ! 1555: ! 1556: displayInfo = [self displayInfo]; // current mode ! 1557: ! 1558: displayModes = [self displayModes]; // all possible modes ! 1559: if (displayModes == NULL) ! 1560: return NO; ! 1561: ! 1562: bzero(displayInfo->pixelEncoding, IO_MAX_PIXEL_BITS); ! 1563: strncpy(displayInfo->pixelEncoding, displayModes[mode].pixelEncoding, ! 1564: strlen(displayModes[mode].pixelEncoding)); ! 1565: displayInfo->width = displayModes[mode].width; ! 1566: displayInfo->height = displayModes[mode].height; ! 1567: displayInfo->totalWidth = displayModes[mode].totalWidth; ! 1568: displayInfo->rowBytes = displayModes[mode].rowBytes; ! 1569: displayInfo->refreshRate = displayModes[mode].refreshRate; ! 1570: displayInfo->bitsPerPixel = displayModes[mode].bitsPerPixel; ! 1571: displayInfo->colorSpace = displayModes[mode].colorSpace; ! 1572: displayInfo->parameters = displayModes[mode].parameters; ! 1573: ! 1574: displayInfo->screenWidth = displayModes[mode].screenWidth; ! 1575: displayInfo->screenHeight = displayModes[mode].screenHeight; ! 1576: displayInfo->scanRate = displayModes[mode].scanRate; ! 1577: displayInfo->memorySize = displayModes[mode].memorySize; ! 1578: displayInfo->dotClockRate = displayModes[mode].dotClockRate; ! 1579: displayInfo->modeUnavailableFlag = displayModes[mode].modeUnavailableFlag; ! 1580: ! 1581: /* ! 1582: * If the driver defined the flag use it else chhose a default behavior. ! 1583: */ ! 1584: if (displayModes[mode].flags != 0) { ! 1585: displayInfo->flags = displayModes[mode].flags; ! 1586: } else { ! 1587: if (displayInfo->bitsPerPixel == IO_8BitsPerPixel) { ! 1588: displayInfo->flags = IO_DISPLAY_HAS_TRANSFER_TABLE; ! 1589: } else { ! 1590: displayInfo->flags = IO_DISPLAY_NEEDS_SOFTWARE_GAMMA_CORRECTION; ! 1591: } ! 1592: } ! 1593: _currentDisplayMode = mode; ! 1594: ! 1595: return YES; ! 1596: } ! 1597: ! 1598: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen ! 1599: { ! 1600: strcpy( classes, IOClassFramebuffer); ! 1601: return( self); ! 1602: } ! 1603: ! 1604: @end ! 1605:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.