Annotation of driverkit/libDriver/Kernel/IOFrameBufferDisplay.m, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.