Annotation of driverkit/libDriver/i386/IOVPCodeDisplay.m, revision 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 by NeXT Computer, Inc.
        !            25:  * All rights reserved.
        !            26:  *
        !            27:  * IOVPCodeDisplay.m -- vpcode video display driver.
        !            28:  *
        !            29:  * 22 July 1993                Derek B Clegg
        !            30:  *     Created.
        !            31:  */
        !            32: 
        !            33: #import <stdio.h>
        !            34: #import <stdlib.h>
        !            35: #import <string.h>
        !            36: #import <driverkit/i386/ioPorts.h>
        !            37: #import <driverkit/i386/IOEISADeviceDescription.h>
        !            38: #import <driverkit/i386/IOVPCodeDisplay.h>
        !            39: 
        !            40: @interface IOVPCodeDisplay (Private)
        !            41: - jumpTo:(int)entryPoint withInitialSRegs:(VPInstruction *)initialSRegs;
        !            42: - setGammaTable;
        !            43: - _setDefaultGammaTable:(VPInstruction *)transferTable;
        !            44: - getDisplayInfo;
        !            45: @end
        !            46: 
        !            47: @implementation IOVPCodeDisplay
        !            48: 
        !            49: - getPixelEncoding
        !            50: {
        !            51:     int n, k;
        !            52:     unsigned char *p;
        !            53:     IODisplayInfo *displayInfo;
        !            54:     VPInstruction reg[8];
        !            55: 
        !            56:     if (_debug)
        !            57:        IOLog("%s: Getting pixel encoding.\n", [self name]);
        !            58: 
        !            59:     if (![self runVPCode:VP_GET_PIXEL_ENCODING withRegs:reg]) {
        !            60:        IOLog("%s: Can't obtain pixel encoding.\n", [self name]);
        !            61:        return nil;
        !            62:     }
        !            63: 
        !            64:     displayInfo = [self displayInfo];
        !            65:     memset(displayInfo->pixelEncoding, 0, sizeof(displayInfo->pixelEncoding));
        !            66: 
        !            67:     switch (displayInfo->colorSpace) {
        !            68:     case IO_OneIsBlackColorSpace:
        !            69:     case IO_OneIsWhiteColorSpace:
        !            70:        switch (displayInfo->bitsPerPixel) {
        !            71:        case IO_2BitsPerPixel:
        !            72:            for (k = 0; k < 2; k++)
        !            73:                displayInfo->pixelEncoding[k] = reg[0];
        !            74:            break;
        !            75:        case IO_8BitsPerPixel:
        !            76:            for (k = 0; k < 8; k++)
        !            77:                displayInfo->pixelEncoding[k] = reg[0];
        !            78:            break;
        !            79:        default:
        !            80:            IOLog("%s: invalid `bitsPerPixel' (%d) for color space %d.\n", 
        !            81:                  [self name], displayInfo->bitsPerPixel,
        !            82:                  displayInfo->colorSpace);
        !            83:            return nil;
        !            84:        }
        !            85:        break;
        !            86: 
        !            87:     case IO_RGBColorSpace:
        !            88:        switch (displayInfo->bitsPerPixel) {
        !            89:        case IO_12BitsPerPixel:
        !            90:            if (reg[0] != 'R' || reg[1] != 'G' || reg[2] != 'B'
        !            91:                || reg[3] != '-') {
        !            92:                IOLog("%s: Sorry, only `RRRRGGGGBBBB----' supported for "
        !            93:                      "`IO_12BitsPerPixel'.\n", [self name]);
        !            94:                return nil;
        !            95:            }
        !            96:            strcpy(displayInfo->pixelEncoding, "RRRRGGGGBBBB----");
        !            97:            break;
        !            98:        case IO_15BitsPerPixel:
        !            99:            if (reg[0] != '-' || reg[1] != 'R' || reg[2] != 'G'
        !           100:                || reg[3] != 'B') {
        !           101:                IOLog("%s: Sorry, only `-RRRRRGGGGGBBBBB' supported for "
        !           102:                      "`IO_15BitsPerPixel'.\n", [self name]);
        !           103:                return nil;
        !           104:            }
        !           105:            strcpy(displayInfo->pixelEncoding, "-RRRRRGGGGGBBBBB");
        !           106:            break;
        !           107: 
        !           108:        case IO_24BitsPerPixel:
        !           109:            p = displayInfo->pixelEncoding;
        !           110:            for (n = 0; n < 4; n++) {
        !           111:                for (k = 0; k < 8; k++) {
        !           112:                    *p++ = reg[n];
        !           113:                }
        !           114:            }
        !           115:            break;
        !           116:        default:
        !           117:            IOLog("%s: invalid `bitsPerPixel' (%d) for RGB color space.\n", 
        !           118:                  [self name], displayInfo->bitsPerPixel);
        !           119:            break;
        !           120:        }
        !           121:        break;
        !           122: 
        !           123:     default:
        !           124:        IOLog("%s: Sorry, color space %d is not supported.\n", 
        !           125:              [self name], displayInfo->colorSpace);
        !           126:        return nil;
        !           127:     }
        !           128: 
        !           129:     if (_debug)
        !           130:        IOLog("%s: pixelEncoding = `%s'.\n", [self name], 
        !           131:              displayInfo->pixelEncoding);
        !           132: 
        !           133:     return self;
        !           134: }
        !           135: 
        !           136: - getDisplayInfo
        !           137: {
        !           138:     IODisplayInfo *displayInfo;
        !           139:     VPInstruction reg[8];
        !           140: 
        !           141:     /* Verify that the selected mode is valid. */
        !           142: 
        !           143:     if (_debug)
        !           144:        IOLog("%s: verifying selected mode.\n", [self name]);
        !           145: 
        !           146:     if (![self runVPCode:VP_VERIFY_MODE withRegs:reg]) {
        !           147:        IOLog("%s: Failed to verify mode.\n", [self name]);
        !           148:        return nil;
        !           149:     }
        !           150:     if (reg[0] != 0) {
        !           151:        IOLog("%s: Selected mode is invalid.\n", [self name]);
        !           152:        if (![self runVPCode:VP_SET_DEFAULT_MODE withRegs:0]) {
        !           153:            IOLog("%s: Failed to set default mode.\n", [self name]);
        !           154:            return nil;
        !           155:        }
        !           156:     }
        !           157: 
        !           158:     if (_debug)
        !           159:        IOLog("%s: Getting display info.\n", [self name]);
        !           160: 
        !           161:     if (![self runVPCode:VP_GET_DISPLAY_INFO withRegs:reg]) {
        !           162:        IOLog("%s: Failed to obtain display info.\n", [self name]);
        !           163:        return nil;
        !           164:     }
        !           165:     displayInfo = [self displayInfo];
        !           166:     displayInfo->width = reg[0];
        !           167:     displayInfo->height = reg[1];
        !           168:     displayInfo->totalWidth = reg[2];
        !           169:     displayInfo->rowBytes = reg[3];
        !           170:     displayInfo->refreshRate = reg[4];
        !           171:     displayInfo->bitsPerPixel = reg[5];
        !           172:     displayInfo->colorSpace = reg[6];
        !           173:     displayInfo->flags = reg[7];
        !           174: 
        !           175:     if ([self getPixelEncoding] == nil)
        !           176:        return nil;
        !           177: 
        !           178:     IOLog("%s: IOVPCodeDisplay: Initialized.\n", [self name]);
        !           179:     return self;
        !           180: }
        !           181: 
        !           182: /* Put the display into linear framebuffer mode. This typically happens
        !           183:  * when the window server starts running.
        !           184:  */
        !           185: - (void)enterLinearMode
        !           186: {
        !           187:     IODisplayInfo *displayInfo;
        !           188:     VPInstruction reg[8];
        !           189: 
        !           190:     /* Set up the chip to use the selected mode. */
        !           191: 
        !           192:     if (_debug)
        !           193:        IOLog("%s: Initializing video mode.\n", [self name]);
        !           194: 
        !           195:     if (![self runVPCode:VP_INITIALIZE_MODE withRegs:0]) {
        !           196:        IOLog("%s: Failed to initialize mode.\n", [self name]);
        !           197:        return;
        !           198:     }
        !           199: 
        !           200:     /* Set the gamma-corrected gray-scale palette if necessary. */
        !           201:     [self setGammaTable];
        !           202: 
        !           203:     /* Enter linear mode. */
        !           204:     if (_debug)
        !           205:        IOLog("%s: Enabling linear framebuffer: 0x%08x\n", [self name], 
        !           206:              _videoRamAddress);
        !           207: 
        !           208:     reg[0] = _videoRamAddress;
        !           209:     reg[1] = _videoRamSize;
        !           210:     if (![self runVPCode:VP_ENABLE_LINEAR_FRAMEBUFFER withRegs:reg])
        !           211:        return;
        !           212: 
        !           213:     /* Clear the screen. */
        !           214:     displayInfo = [self displayInfo];
        !           215:     memset(displayInfo->frameBuffer, 0, 
        !           216:           displayInfo->rowBytes * displayInfo->height);
        !           217: }
        !           218: 
        !           219: /* Get the device out of whatever advanced linear mode it was using and back
        !           220:  * into a state where it can be used as a standard VGA device.
        !           221:  */
        !           222: - (void)revertToVGAMode
        !           223: {
        !           224:     /* Reset the VGA parameters. */
        !           225:     if (_debug)
        !           226:        IOLog("%s: Resetting VGA parameters.\n", [self name]);
        !           227: 
        !           228:     if (![self runVPCode:VP_RESET_VGA withRegs:0])
        !           229:        return;
        !           230: 
        !           231:     /* Let the superclass do whatever work it needs to do. */
        !           232:     [super revertToVGAMode];
        !           233: }
        !           234: 
        !           235: /* Set the brightness to `level'.
        !           236:  */
        !           237: - setBrightness:(int)level token:(int)t
        !           238: {
        !           239:     if (level < EV_SCREEN_MIN_BRIGHTNESS || level > EV_SCREEN_MAX_BRIGHTNESS) {
        !           240:        IOLog("QVision: Invalid brightness level `%d'.\n", level);
        !           241:        return nil;
        !           242:     }
        !           243:     brightnessLevel = level;
        !           244:     [self setGammaTable];
        !           245:     return self;
        !           246: }
        !           247: 
        !           248: /* Set the transfer tables.
        !           249:  */
        !           250: - setTransferTable:(const unsigned int *)table count:(int)count
        !           251: {
        !           252:     int k;
        !           253: 
        !           254:     if (redTransferTable != 0)
        !           255:        IOFree(redTransferTable, 3 * transferTableCount);
        !           256: 
        !           257:     transferTableCount = count;
        !           258: 
        !           259:     redTransferTable = IOMalloc(3 * count);
        !           260:     greenTransferTable = redTransferTable + count;
        !           261:     blueTransferTable = greenTransferTable + count;
        !           262: 
        !           263:     switch ([self displayInfo]->bitsPerPixel) {
        !           264:     case IO_2BitsPerPixel:
        !           265:     case IO_8BitsPerPixel:
        !           266:        for (k = 0; k < count; k++) {
        !           267:            redTransferTable[k] = greenTransferTable[k] =
        !           268:                blueTransferTable[k] = table[k] & 0xFF;
        !           269:        }
        !           270:        break;
        !           271: 
        !           272:     case IO_12BitsPerPixel:
        !           273:     case IO_15BitsPerPixel:
        !           274:     case IO_24BitsPerPixel:
        !           275:        for (k = 0; k < count; k++) {
        !           276:            redTransferTable[k] = (table[k] >> 24) & 0xFF;
        !           277:            greenTransferTable[k] = (table[k] >> 16) & 0xFF;
        !           278:            blueTransferTable[k] = (table[k] >> 8) & 0xFF;
        !           279:        }
        !           280:        break;
        !           281: 
        !           282:     default:
        !           283:        IOFree(redTransferTable, 3 * count);
        !           284:        redTransferTable = 0;
        !           285:        break;
        !           286:     }
        !           287:     [self setGammaTable];
        !           288:     return self;
        !           289: }
        !           290: 
        !           291: /* Default gamma precompensation table for color displays.
        !           292:  * Gamma 2.2 LUT for P22 phosphor displays (Hitachi, NEC, generic VGA) */
        !           293: 
        !           294: static unsigned char gamma2[4] = {
        !           295:     0, 155, 212, 255,
        !           296: };
        !           297: 
        !           298: static unsigned char gamma4[16] = {
        !           299:       0,  74, 102, 123, 140, 155, 168, 180,
        !           300:     192, 202, 212, 221, 230, 239, 247, 255,
        !           301: };
        !           302: 
        !           303: static unsigned char gamma5[32] = {
        !           304:       0,  54,  73,  88, 101, 111, 121, 130,
        !           305:     138, 145, 152, 159, 166, 172, 178, 183,
        !           306:     189, 194, 199, 204, 209, 214, 218, 223,
        !           307:     227, 231, 235, 239, 243, 247, 251, 255,
        !           308: };
        !           309: 
        !           310: static const unsigned char gamma8[256] = {
        !           311:       0,  15,  22,  27,  31,  35,  39,  42,  45,  47,  50,  52,
        !           312:      55,  57,  59,  61,  63,  65,  67,  69,  71,  73,  74,  76,
        !           313:      78,  79,  81,  82,  84,  85,  87,  88,  90,  91,  93,  94,
        !           314:      95,  97,  98,  99, 100, 102, 103, 104, 105, 107, 108, 109,
        !           315:     110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122,
        !           316:     123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
        !           317:     135, 136, 137, 138, 139, 140, 141, 141, 142, 143, 144, 145,
        !           318:     146, 147, 148, 148, 149, 150, 151, 152, 153, 153, 154, 155, 
        !           319:     156, 157, 158, 158, 159, 160, 161, 162, 162, 163, 164, 165,
        !           320:     165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174,
        !           321:     174, 175, 176, 177, 177, 178, 179, 179, 180, 181, 182, 182,
        !           322:     183, 184, 184, 185, 186, 186, 187, 188, 188, 189, 190, 190, 
        !           323:     191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 198, 198,
        !           324:     199, 200, 200, 201, 201, 202, 203, 203, 204, 205, 205, 206, 
        !           325:     206, 207, 208, 208, 209, 210, 210, 211, 211, 212, 213, 213,
        !           326:     214, 214, 215, 216, 216, 217, 217, 218, 218, 219, 220, 220, 
        !           327:     221, 221, 222, 222, 223, 224, 224, 225, 225, 226, 226, 227,
        !           328:     228, 228, 229, 229, 230, 230, 231, 231, 232, 233, 233, 234, 
        !           329:     234, 235, 235, 236, 236, 237, 237, 238, 238, 239, 240, 240,
        !           330:     241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 
        !           331:     247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252,
        !           332:     253, 253, 254, 255, 
        !           333: };
        !           334: 
        !           335: - _setDefaultGammaTable:(VPInstruction *)transferTable
        !           336: {
        !           337:     unsigned int k, g, v;
        !           338:     const IODisplayInfo *displayInfo;
        !           339: 
        !           340:     displayInfo = [self displayInfo];
        !           341: 
        !           342:     switch (displayInfo->bitsPerPixel) {
        !           343:     case IO_2BitsPerPixel:
        !           344:        for (g = 0; g < 4; g++) {
        !           345:            v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma2[g]);
        !           346:            v = (v << 16) | (v << 8) | v;
        !           347:            for (k = 0; k < 64; k++) {
        !           348:                *transferTable++ = v;
        !           349:            }
        !           350:        }
        !           351:        break;
        !           352: 
        !           353:     case IO_12BitsPerPixel:
        !           354:        for (g = 0; g < 16; g++) {
        !           355:            v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma4[g]);
        !           356:            v = (v << 16) | (v << 8) | v;
        !           357:            for (k = 0; k < 16; k++) {
        !           358:                *transferTable++ = v;
        !           359:            }
        !           360:        }
        !           361:        break;
        !           362: 
        !           363:     case IO_15BitsPerPixel:
        !           364:        for (g = 0; g < 32; g++) {
        !           365:            v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma5[g]);
        !           366:            v = (v << 16) | (v << 8) | v;
        !           367:            for (k = 0; k < 8; k++)
        !           368:                *transferTable++ = v;
        !           369:        }
        !           370:        break;
        !           371: 
        !           372:     case IO_8BitsPerPixel:
        !           373:     case IO_24BitsPerPixel:
        !           374:        for (g = 0; g < 256; g++) {
        !           375:            v = EV_SCALE_BRIGHTNESS(brightnessLevel, gamma8[g]);
        !           376:            *transferTable++ = (v << 16) | (v << 8) | v;
        !           377:        }
        !           378:        break;
        !           379: 
        !           380:     default:
        !           381:        return self;
        !           382:     }
        !           383:     if (![self runVPCode:VP_SET_TRANSFER_TABLE withRegs:0])
        !           384:        return nil;
        !           385:     return self;
        !           386: }
        !           387: 
        !           388: - setGammaTable
        !           389: {
        !           390:     unsigned int i, j, r, g, b, v, *transferTable;
        !           391: 
        !           392:     if (_debug)
        !           393:        IOLog("%s: setting transfer table.\n", [self name]);
        !           394: 
        !           395:     if (_vpCode == 0 || _vpCodeCount <= 0 
        !           396:        || VP_TRANSFER_TABLE >= _vpCodeCount) {
        !           397:        IOLog("%s: Can't set transfer table: no vpcode present.\n",
        !           398:              [self name]);
        !           399:        return nil;
        !           400:     }
        !           401:     v = _vpCode[VP_TRANSFER_TABLE];
        !           402:     if (v >= _vpCodeCount) {
        !           403:        IOLog("%s: transfer table address is out of range: 0x%x.\n",
        !           404:              [self name], v);
        !           405:        return nil;
        !           406:     }
        !           407:     if (v == 0)
        !           408:        return self;
        !           409: 
        !           410:     if (_debug)
        !           411:        IOLog("%s: using transfer table at 0x%08x.\n", [self name], v);
        !           412: 
        !           413:     transferTable = &_vpCode[v];
        !           414: 
        !           415:     if (redTransferTable == 0)
        !           416:        return [self _setDefaultGammaTable:transferTable];
        !           417: 
        !           418:     for (i = 0; i < transferTableCount; i++) {
        !           419:        for (j = 0; j < 256/transferTableCount; j++) {
        !           420:            r = EV_SCALE_BRIGHTNESS(brightnessLevel, redTransferTable[i]);
        !           421:            g = EV_SCALE_BRIGHTNESS(brightnessLevel, greenTransferTable[i]);
        !           422:            b = EV_SCALE_BRIGHTNESS(brightnessLevel, blueTransferTable[i]);
        !           423:            *transferTable++ = (r << 16) | (g << 8) | b;
        !           424:        }
        !           425:     }
        !           426: 
        !           427:     if (_debug) {
        !           428:        transferTable = &_vpCode[v];
        !           429:        IOLog("%s: Transfer table:\n", [self name]);
        !           430:        for (i = 0; i < 64; i++) {
        !           431:            IOLog("%s: ", [self name]);
        !           432:            for (j = 0; j < 4; j++) {
        !           433:                IOLog("%08x ", *transferTable++);
        !           434:            }
        !           435:            IOLog("\n");
        !           436:        }
        !           437:     }
        !           438: 
        !           439:     if (![self runVPCode:VP_SET_TRANSFER_TABLE withRegs:0])
        !           440:        return nil;
        !           441:     return self;
        !           442: }
        !           443: 
        !           444: - initFromDeviceDescription:deviceDescription
        !           445: {
        !           446:     const IORange *range;
        !           447:     IODisplayInfo *displayInfo;
        !           448: 
        !           449:     if ([super initFromDeviceDescription:deviceDescription] == nil)
        !           450:        return [super free];
        !           451: 
        !           452:     _debug = NO;
        !           453: 
        !           454:     range = [deviceDescription memoryRangeList];
        !           455:     if (range == 0) {
        !           456:        IOLog("%s: No memory range set.\n", [self name]);
        !           457:        return [super free];
        !           458:     }
        !           459:     _videoRamAddress = range[0].start;
        !           460:     _videoRamSize = range[0].size;
        !           461: 
        !           462:     redTransferTable = greenTransferTable = blueTransferTable = 0;
        !           463:     transferTableCount = 0;
        !           464:     brightnessLevel = EV_SCREEN_MAX_BRIGHTNESS;
        !           465: 
        !           466:     displayInfo = [self displayInfo];
        !           467:     displayInfo->frameBuffer =
        !           468:        (void *)[self mapFrameBufferAtPhysicalAddress:0 length:0];
        !           469:     if (displayInfo->frameBuffer == 0)
        !           470:        return [self free];
        !           471: 
        !           472:     if (_debug) {
        !           473:        IOLog("Video Ram Address = 0x%08x\n", _videoRamAddress);
        !           474:        IOLog("Framebuffer Address = 0x%08x\n",
        !           475:              (unsigned int)displayInfo->frameBuffer);
        !           476:     }
        !           477:     return self;
        !           478: }
        !           479: 
        !           480: - jumpTo:(int)entryPoint withInitialSRegs:(VPInstruction *)initialSRegs
        !           481: {
        !           482:     VPInstruction reg[16];     /* P-machine register set */
        !           483:     VPInstruction immediate;   /* Immediate value for some instructions. */
        !           484:     VPInstruction instruction; /* The current instruction */
        !           485:     unsigned int port;         /* The port for ins and outs. */
        !           486:     BOOL zero;                 /* Zero condition code. */
        !           487:     BOOL positive;             /* Positive condition code. */
        !           488:     BOOL negative;             /* Negative condition code. */
        !           489:     int pc;                    /* The program counter. */
        !           490: 
        !           491:     if (_vpCode == 0 || _vpCodeCount <= 0) {
        !           492:        IOLog("%s: No vpcode to run.\n", [self name]);
        !           493:        return nil;
        !           494:     }
        !           495: 
        !           496:     /* Set up the initial registers. */
        !           497: 
        !           498:     if (initialSRegs == 0) {
        !           499:        memset(&reg[0], 0, 16 * sizeof(reg[0]));
        !           500:     } else {
        !           501:        memset(&reg[0], 0, 8 * sizeof(reg[0]));
        !           502:        memcpy(&reg[8], initialSRegs, 8 * sizeof(reg[0]));
        !           503:     }
        !           504: 
        !           505:     immediate = 0;
        !           506:     zero = positive = negative = NO;
        !           507:     pc = entryPoint;
        !           508: 
        !           509:     while (1) {
        !           510:        if (pc < 0 || pc >= _vpCodeCount) {
        !           511:            IOLog("%s: program counter is out of range: 0x%x.\n",
        !           512:                  [self name], (unsigned)pc);
        !           513:            return nil;
        !           514:        }
        !           515:        instruction = _vpCode[pc++];
        !           516:        if (VP_IMMEDIATE_FOLLOWS_OPCODE(instruction))
        !           517:            immediate = _vpCode[pc++];
        !           518: 
        !           519:        switch (VP_OPCODE(instruction)) {
        !           520:        case VP_DEBUG:
        !           521:            _debug = YES;
        !           522:            break;
        !           523: 
        !           524:        case VP_DELAY:
        !           525:            IODelay(immediate);
        !           526:            break;
        !           527: 
        !           528:        case VP_LOAD_CR:        /* load constant, reg2 */
        !           529:        case VP_LOAD_TR:        /* load label, reg2 */
        !           530:            reg[VP_REG2(instruction)] = immediate;
        !           531:            break;
        !           532: 
        !           533:        case VP_LOAD_AR:        /* load @address, reg2 */
        !           534:            if (immediate >= _vpCodeCount) {
        !           535:                IOLog("%s: load address is out of range: 0x%x.\n",
        !           536:                      [self name], immediate);
        !           537:                return nil;
        !           538:            }
        !           539:            reg[VP_REG2(instruction)] = _vpCode[immediate];
        !           540:            break;
        !           541: 
        !           542:        case VP_LOAD_IR:        /* load @reg1, reg2 */
        !           543:            immediate = reg[VP_REG1(instruction)];
        !           544:            if (immediate >= _vpCodeCount) {
        !           545:                IOLog("%s: load address is out of range: 0x%x.\n",
        !           546:                      [self name], immediate);
        !           547:                return nil;
        !           548:            }
        !           549:            reg[VP_REG2(instruction)] = _vpCode[immediate];
        !           550:            break;
        !           551: 
        !           552:        case VP_VLOAD_AR:       /* vload @address, reg2 */
        !           553:            if (_videoRamAddress == 0 || immediate >= _videoRamSize) {
        !           554:                IOLog("%s: invalid video ram address: 0x%x.\n",
        !           555:                      [self name], _videoRamAddress + immediate);
        !           556:                return nil;
        !           557:            }
        !           558:            reg[VP_REG2(instruction)] =
        !           559:                ((VPInstruction *)_videoRamAddress)[immediate];
        !           560:            break;
        !           561: 
        !           562:        case VP_VLOAD_IR:       /* vload @reg1, reg2 */
        !           563:            immediate = reg[VP_REG1(instruction)];
        !           564:            if (_videoRamAddress == 0 || immediate >= _videoRamSize) {
        !           565:                IOLog("%s: invalid video ram address: 0x%x.\n",
        !           566:                      [self name], _videoRamAddress + immediate);
        !           567:                return nil;
        !           568:            }
        !           569:            reg[VP_REG2(instruction)] =
        !           570:                ((VPInstruction *)_videoRamAddress)[immediate];
        !           571:            break;
        !           572: 
        !           573:        case VP_STORE_AR:       /* store reg1, @address */
        !           574:            if (immediate >= _vpCodeCount) {
        !           575:                IOLog("%s: store address is out of range: 0x%x.\n",
        !           576:                      [self name], immediate);
        !           577:                return nil;
        !           578:            }
        !           579:            _vpCode[immediate] = reg[VP_REG1(instruction)];
        !           580:            break;
        !           581: 
        !           582:        case VP_STORE_IR:       /* store  reg1, @reg2 */
        !           583:            immediate = reg[VP_REG2(instruction)];
        !           584:            if (immediate >= _vpCodeCount) {
        !           585:                IOLog("%s: store address is out of range: 0x%x.\n",
        !           586:                      [self name], immediate);
        !           587:                return nil;
        !           588:            }
        !           589:            _vpCode[immediate] = reg[VP_REG1(instruction)];
        !           590:            break;
        !           591: 
        !           592:        case VP_VSTORE_AR:      /* vstore reg1, @address */
        !           593:            if (_videoRamAddress == 0
        !           594:                || immediate * sizeof(VPInstruction) >= _videoRamSize) {
        !           595:                IOLog("%s: invalid video ram address: 0x%x.\n",
        !           596:                      [self name], _videoRamAddress + immediate);
        !           597:                return nil;
        !           598:            }
        !           599:            ((VPInstruction *)_videoRamAddress)[immediate] =
        !           600:                reg[VP_REG1(instruction)];
        !           601:            break;
        !           602: 
        !           603:        case VP_VSTORE_IR:      /* vstore  reg1, @reg2 */
        !           604:            immediate = reg[VP_REG2(instruction)];
        !           605:            if (_videoRamAddress == 0
        !           606:                || immediate * sizeof(VPInstruction) >= _videoRamSize) {
        !           607:                IOLog("%s: invalid video ram address: 0x%x.\n",
        !           608:                      [self name], _videoRamAddress + immediate);
        !           609:                return nil;
        !           610:            }
        !           611:            ((VPInstruction *)_videoRamAddress)[immediate] =
        !           612:                reg[VP_REG1(instruction)];
        !           613:            break;
        !           614: 
        !           615:        case VP_ADD_CRR:        /* add constant, reg1, reg2 */
        !           616:            reg[VP_REG2(instruction)] = immediate + reg[VP_REG1(instruction)];
        !           617:            break;
        !           618: 
        !           619:        case VP_ADD_RRR:        /* add reg1, reg2, reg3 */
        !           620:            reg[VP_REG3(instruction)] =
        !           621:                reg[VP_REG1(instruction)] + reg[VP_REG2(instruction)];
        !           622:            break;
        !           623: 
        !           624:        case VP_SUB_RCR:        /* sub reg1, constant, reg2 */
        !           625:            reg[VP_REG2(instruction)] = reg[VP_REG1(instruction)] - immediate;
        !           626:            break;
        !           627: 
        !           628:        case VP_SUB_CRR:        /* sub constant, reg1, reg2 */
        !           629:            reg[VP_REG2(instruction)] = immediate - reg[VP_REG1(instruction)];
        !           630:            break;
        !           631: 
        !           632:        case VP_SUB_RRR:        /* sub reg1, reg2, reg3 */
        !           633:            reg[VP_REG3(instruction)] =
        !           634:                reg[VP_REG1(instruction)] - reg[VP_REG2(instruction)];
        !           635:            break;
        !           636: 
        !           637:        case VP_AND_CRR:        /* and constant, reg1, reg2 */
        !           638:            reg[VP_REG2(instruction)] = immediate & reg[VP_REG1(instruction)];
        !           639:            break;
        !           640: 
        !           641:        case VP_AND_RRR:        /* and reg1, reg2, reg3 */
        !           642:            reg[VP_REG3(instruction)] = 
        !           643:                reg[VP_REG1(instruction)] & reg[VP_REG2(instruction)];
        !           644:            break;
        !           645: 
        !           646:        case VP_OR_CRR:         /* or constant, reg1, reg2 */
        !           647:            reg[VP_REG2(instruction)] = immediate | reg[VP_REG1(instruction)];
        !           648:            break;
        !           649: 
        !           650:        case VP_OR_RRR:         /* or reg1, reg2, reg3 */
        !           651:            reg[VP_REG3(instruction)] =
        !           652:                reg[VP_REG1(instruction)] | reg[VP_REG2(instruction)];
        !           653:            break;
        !           654: 
        !           655:        case VP_XOR_CRR:        /* xor constant, reg1, reg2 */
        !           656:            reg[VP_REG2(instruction)] = immediate ^ reg[VP_REG1(instruction)];
        !           657:            break;
        !           658: 
        !           659:        case VP_XOR_RRR:        /* xor reg1, reg2, reg3 */
        !           660:            reg[VP_REG3(instruction)] =
        !           661:                reg[VP_REG1(instruction)] ^ reg[VP_REG2(instruction)];
        !           662:            break;
        !           663: 
        !           664:        case VP_LSL_RCR:        /* lsl reg1, constant, reg3 */
        !           665:            reg[VP_REG3(instruction)] =
        !           666:                reg[VP_REG1(instruction)] << VP_FIELD2(instruction);
        !           667:            break;
        !           668: 
        !           669:        case VP_LSR_RCR:        /* lsr reg1, constant, reg3 */
        !           670:            reg[VP_REG3(instruction)] = 
        !           671:                reg[VP_REG1(instruction)] >> VP_FIELD2(instruction);
        !           672:            break;
        !           673: 
        !           674:        case VP_MOVE_RR:        /* move reg1, reg2 */
        !           675:            reg[VP_REG2(instruction)] = reg[VP_REG1(instruction)];
        !           676:            break;
        !           677: 
        !           678:        case VP_TEST_R:         /* test reg1 */
        !           679:            zero = positive = negative = NO;
        !           680:            immediate = reg[VP_REG1(instruction)];
        !           681:        set_condition_codes:
        !           682:            if (immediate == 0) {
        !           683:                zero = YES;
        !           684:            } else if ((int)immediate > 0) {
        !           685:                positive = YES;
        !           686:            } else {
        !           687:                negative = YES;
        !           688:            }
        !           689:            break;
        !           690: 
        !           691:        case VP_CMP_RC:         /* cmp reg1, constant */
        !           692:            zero = positive = negative = 0;
        !           693:            immediate = reg[VP_REG1(instruction)] - immediate;
        !           694:            goto set_condition_codes;
        !           695:            break;
        !           696: 
        !           697:        case VP_CMP_CR:         /* cmp constant, reg1 */
        !           698:            zero = positive = negative = 0;
        !           699:            immediate = immediate - reg[VP_REG1(instruction)];
        !           700:            goto set_condition_codes;
        !           701:            break;
        !           702: 
        !           703:        case VP_CMP_RR:         /* cmp reg1, reg2 */
        !           704:            zero = positive = negative = 0;
        !           705:            immediate = reg[VP_REG1(instruction)] - reg[VP_REG2(instruction)];
        !           706:            goto set_condition_codes;
        !           707:            break;
        !           708: 
        !           709:        case VP_BR:
        !           710:            pc = VP_BRANCH_DEST(instruction);
        !           711:            break;
        !           712: 
        !           713:        case VP_BPOS:
        !           714:            if (positive)
        !           715:                pc = VP_BRANCH_DEST(instruction);
        !           716:            break;
        !           717: 
        !           718:        case VP_BNEG:
        !           719:            if (negative)
        !           720:                pc = VP_BRANCH_DEST(instruction);
        !           721:            break;
        !           722: 
        !           723:        case VP_BZERO:
        !           724:            if (zero)
        !           725:                pc = VP_BRANCH_DEST(instruction);
        !           726:            break;
        !           727: 
        !           728:        case VP_BNPOS:
        !           729:            if (!positive)
        !           730:                pc = VP_BRANCH_DEST(instruction);
        !           731:            break;
        !           732: 
        !           733:        case VP_BNNEG:
        !           734:            if (!negative)
        !           735:                pc = VP_BRANCH_DEST(instruction);
        !           736:            break;
        !           737: 
        !           738:        case VP_BNZERO:
        !           739:            if (!zero)
        !           740:                pc = VP_BRANCH_DEST(instruction);
        !           741:            break;
        !           742: 
        !           743:        case VP_INB_CR:
        !           744:            port = VP_PORT(instruction);
        !           745:            reg[VP_REG2(instruction)] = 0xFF & inb(port);
        !           746:            break;
        !           747: 
        !           748:        case VP_OUTB_CR:
        !           749:            port = VP_PORT(instruction);
        !           750:            outb(port, 0xFF & reg[VP_REG2(instruction)]);
        !           751:            break;
        !           752: 
        !           753:        case VP_OUTB_CC:
        !           754:            port = VP_PORT(instruction);
        !           755:            outb(port, 0xFF & immediate);
        !           756:            break;
        !           757: 
        !           758:        case VP_INW_CR:
        !           759:            port = VP_PORT(instruction);
        !           760:            reg[VP_REG2(instruction)] = 0xFFFF & inw(port);
        !           761:            break;
        !           762: 
        !           763:        case VP_OUTW_CR:
        !           764:            port = VP_PORT(instruction);
        !           765:            outw(port, 0xFFFF & reg[VP_REG2(instruction)]);
        !           766:            break;
        !           767: 
        !           768:        case VP_OUTW_CC:
        !           769:            port = VP_PORT(instruction);
        !           770:            outw(port, 0xFFFF & immediate);
        !           771:            break;
        !           772: 
        !           773:        case VP_CALL:
        !           774:            [self jumpTo:VP_BRANCH_DEST(instruction) withInitialSRegs:&reg[8]];
        !           775:            break;
        !           776: 
        !           777:        case VP_RETURN:
        !           778:            /* Store the S-registers in the caller's initial S-register set. */
        !           779:            if (initialSRegs != 0)
        !           780:                memcpy(&initialSRegs[0], &reg[8], 8 * sizeof(reg[0]));
        !           781:            return self;
        !           782: 
        !           783:        default:
        !           784:            IOLog("%s: Unrecognized opcode: 0x%08x; pc: 0x%x\n", [self name],
        !           785:                  instruction, pc);
        !           786:            return nil;
        !           787:        }
        !           788:     }
        !           789: }
        !           790: 
        !           791: - runVPCode:(unsigned int)entryPoint withRegs:(VPInstruction *)initialRegs
        !           792: {
        !           793:     VPInstruction reg[8];
        !           794: 
        !           795:     if (_vpCode == 0 || _vpCodeCount <= 0) {
        !           796:        IOLog("%s: No vpcode to run.\n", [self name]);
        !           797:        return nil;
        !           798:     }
        !           799:     if (entryPoint >= _vpCodeCount) {
        !           800:        IOLog("%s: entry point is out of range: 0x%x.\n", [self name],
        !           801:              (unsigned)entryPoint);
        !           802:        return nil;
        !           803:     }
        !           804:     if (_vpCode[entryPoint] == 0)
        !           805:        return self;
        !           806:     if (_debug) {
        !           807:        IOLog("%s: Running vpcode at 0x%x\n", [self name],
        !           808:              (unsigned)_vpCode[entryPoint]);
        !           809:     }
        !           810:     if (initialRegs == 0) {
        !           811:        memset(reg, 0, sizeof(reg));
        !           812:        initialRegs = reg;
        !           813:     }
        !           814:     return [self jumpTo:_vpCode[entryPoint] withInitialSRegs:initialRegs];
        !           815: }
        !           816: 
        !           817: static const char *
        !           818: find_parameter(const char *parameter, const char *string)
        !           819: {
        !           820:     int c;
        !           821:     size_t length;
        !           822: 
        !           823:     length = strlen(parameter);
        !           824:     while (*string != 0) {
        !           825:        if (strncmp(string, parameter, length) == 0) {
        !           826:            string += length;
        !           827:            while ((c = *string) != '\0' && (c == ' ' || c == '\t'))
        !           828:                string++;
        !           829:            return (c != 0) ? string : 0;
        !           830:        }
        !           831:        string++;
        !           832:     }
        !           833:     return 0;
        !           834: }
        !           835: 
        !           836: - getVPCodeFilename:(char *)parameterArray count:(unsigned int *)count
        !           837: {
        !           838:     char buffer[256];
        !           839:     IOConfigTable *configTable;
        !           840:     const char *s, *displayMode, *color, *filename;
        !           841:     int width, height, refreshRate, length;
        !           842: 
        !           843:     /* Get the string describing the display mode. */
        !           844:     configTable = [[self deviceDescription] configTable];
        !           845:     if (configTable == nil)
        !           846:        return nil;
        !           847: 
        !           848:     displayMode = [configTable valueForStringKey:"Display Mode"];
        !           849: 
        !           850:     s = find_parameter("Width:", displayMode);
        !           851:     if (s == 0)
        !           852:        return nil;
        !           853:     width = strtol(s, 0, 10);
        !           854: 
        !           855:     s = find_parameter("Height:", displayMode);
        !           856:     if (s == 0)
        !           857:        return nil;
        !           858:     height = strtol(s, 0, 10);
        !           859: 
        !           860:     s = find_parameter("Refresh:", displayMode);
        !           861:     if (s == 0)
        !           862:        return nil;
        !           863:     refreshRate = strtol(s, 0, 10);
        !           864: 
        !           865:     s = find_parameter("ColorSpace:", displayMode);
        !           866:     if (s == 0)
        !           867:        return nil;
        !           868:     if (strncmp(s, "BW:2", 4) == 0) {
        !           869:        color = "BW:2";
        !           870:     } else if (strncmp(s, "BW:8", 4) == 0) {
        !           871:        color = "BW:8";
        !           872:     } else if (strncmp(s, "RGB:444/16", 10) == 0) {
        !           873:        color = "RGB:444/16";
        !           874:     } else if (strncmp(s, "RGB:555/16", 10) == 0) {
        !           875:        color = "RGB:555/16";
        !           876:     } else if (strncmp(s, "RGB:888/32", 10) == 0) {
        !           877:        color = "RGB:888/32";
        !           878:     } else {
        !           879:        return nil;
        !           880:     }
        !           881:     sprintf(buffer, "[%d x %d x %s @ %d]", width, height, color, refreshRate);
        !           882: 
        !           883:     if (_debug)
        !           884:        IOLog("%s: Searching for key `%s'.\n", [self name], buffer);
        !           885: 
        !           886:     filename = [configTable valueForStringKey:buffer];
        !           887:     if (filename == 0)
        !           888:        return nil;
        !           889:     length = strlen(filename) + 1;
        !           890:     if (*count < length)
        !           891:        return nil;
        !           892: 
        !           893:     if (_debug)
        !           894:        IOLog("%s: Using vpcode from `%s'.\n", [self name], filename);
        !           895:     *count = length;
        !           896:     strcpy(parameterArray, filename);
        !           897:     return self;
        !           898: }
        !           899: 
        !           900: - (IOReturn)getCharValues:(unsigned char *)parameterArray
        !           901:                forParameter:(IOParameterName)parameterName
        !           902:                count:(unsigned int *)count
        !           903: {
        !           904:     if (_debug)
        !           905:        IOLog("%s: received parameter `%s'.\n", [self name], parameterName);
        !           906: 
        !           907:     if (strcmp(parameterName, VP_GET_VPCODE_FILENAME) == 0) {
        !           908:        if (![self getVPCodeFilename:parameterArray count:count])
        !           909:            return IO_R_UNSUPPORTED;
        !           910:        return IO_R_SUCCESS;
        !           911:     } else {
        !           912:        return [super getCharValues:parameterArray 
        !           913:            forParameter:parameterName
        !           914:            count:count];
        !           915:     }
        !           916: }
        !           917: 
        !           918: /* Set parameters for the display object.
        !           919:  */
        !           920: - (IOReturn)setIntValues:(unsigned *)parameterArray
        !           921:        forParameter:(IOParameterName)parameterName
        !           922:        count:(unsigned int)count
        !           923: {
        !           924:     if (strcmp(parameterName, VP_SET_VPCODE_SIZE) == 0) {
        !           925:        if (count != 1)
        !           926:            return IO_R_INVALID_ARG;
        !           927:        if (_vpCode != 0)
        !           928:            IOFree(_vpCode, _vpCodeCount * sizeof(_vpCode[0]));
        !           929:        _vpCodeCount = parameterArray[0];
        !           930:        _vpCodeReceived = 0;
        !           931:        _vpCode = IOMalloc(_vpCodeCount * sizeof(_vpCode[0]));
        !           932:        if (_vpCode == 0)
        !           933:            return IO_R_NO_MEMORY;
        !           934:        IOLog("About to receive %d bytes of VPCode!\n", _vpCodeCount);
        !           935:        return IO_R_SUCCESS;
        !           936: 
        !           937:     } else if (strcmp(parameterName, VP_SET_VPCODE) == 0) {
        !           938:        if (_vpCode == 0)
        !           939:            return IO_R_NO_MEMORY;
        !           940:        if (_vpCodeReceived + count > _vpCodeCount)
        !           941:            return IO_R_INVALID_ARG;
        !           942:        memcpy(&_vpCode[_vpCodeReceived], parameterArray,
        !           943:               count * sizeof(_vpCode[0]));
        !           944:        _vpCodeReceived += count;
        !           945:        IOLog("Received %d bytes of VPCode!\n", count);
        !           946:        return IO_R_SUCCESS;
        !           947: 
        !           948:     } else if (strcmp(parameterName, VP_END_VPCODE) == 0) {
        !           949:        if (![self getDisplayInfo])
        !           950:            return IO_R_UNSUPPORTED;
        !           951:        return IO_R_SUCCESS;
        !           952:     } else {
        !           953:        return [super setIntValues:parameterArray
        !           954:            forParameter:parameterName
        !           955:            count:count];
        !           956:     }
        !           957: }
        !           958: @end

unix.superglobalmegacorp.com

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