Annotation of driverkit/libDriver/i386/IOVPCodeDisplay.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 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.