|
|
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(®[0], 0, 16 * sizeof(reg[0])); ! 500: } else { ! 501: memset(®[0], 0, 8 * sizeof(reg[0])); ! 502: memcpy(®[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:®[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], ®[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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.