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

unix.superglobalmegacorp.com

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