|
|
1.1 ! root 1: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. ! 2: * ! 3: * CirrusLogicGD542X.m ! 4: * ! 5: */ ! 6: ! 7: ! 8: #import <driverkit/i386/IOEISADeviceDescription.h> ! 9: #import "CirrusLogicGD542X.h" ! 10: #import <kernserv/kern_server_types.h> ! 11: #import <driverkit/i386/displayRegisters.h> ! 12: #import <stdio.h> ! 13: #import <string.h> ! 14: ! 15: #define MIN(a,b) (((a)<(b))?(a):(b)) ! 16: ! 17: ! 18: // ! 19: // typedef used to store arrays of register index and values. ! 20: // -1 as index indicates end of the set... ! 21: // ! 22: typedef struct _SVGAIndexValuePair { ! 23: signed short index; ! 24: unsigned char value; ! 25: } SVGAIndexValuePair; ! 26: ! 27: ! 28: // ! 29: // typedef defining a given graphics mode. A graphics mode ! 30: // consists of all the register/value pairs that, when set, ! 31: // completely define a mode of operation. ! 32: // ! 33: typedef struct _CirrusLogicGD542XMode { ! 34: const char *name; /* human-readable mode name */ ! 35: const SVGAIndexValuePair *generalRegisters; ! 36: const SVGAIndexValuePair *sequencerRegisters; ! 37: const SVGAIndexValuePair *crtControllerRegisters; ! 38: const SVGAIndexValuePair *graphicsControllerRegisters; ! 39: const SVGAIndexValuePair *attributeControllerRegisters; ! 40: } CirrusLogicGD542XMode; ! 41: ! 42: ! 43: /*************************************** ! 44: * CirrusLogicGD542X_1024x768x2x60hz mode ! 45: ***************************************/ ! 46: ! 47: static const SVGAIndexValuePair ! 48: CirrusLogicGD542X_1024x768x2x60hz_generalRegisters[] = { ! 49: {0, 0x3F}, ! 50: {-1, 0} ! 51: }; ! 52: ! 53: static const SVGAIndexValuePair ! 54: CirrusLogicGD542X_1024x768x2x60hz_sequencerRegisters[] = { ! 55: {0, 0x03}, {1, 0x01}, {2, 0x0F}, {3, 0x00}, {4, 0x06}, ! 56: {-1, 0} ! 57: }; ! 58: ! 59: static const SVGAIndexValuePair ! 60: CirrusLogicGD542X_1024x768x2x60hz_crtControllerRegisters[] = { ! 61: {0x11,0x00}, // Turn off lock allowing changing 0..7 ! 62: {0x00,0xA1}, {0x01,0x7F}, {0x02,0x80}, {0x03,0x04}, {0x04,0x88}, ! 63: {0x05,0x9E}, {0x06,0x26}, {0x07,0xFD}, {0x08,0x00}, {0x09,0x60}, ! 64: {0x0A,0x00}, {0x0B,0x00}, {0x0C,0x00}, {0x0D,0x00}, {0x0E,0x00}, ! 65: {0x0F,0x00}, {0x10,0x08}, {0x11,0x8A}, {0x12,0xFF}, {0x13,0x40}, ! 66: {0x14,0x00}, {0x15,0x04}, {0x16,0x22}, {0x17,0xC3}, {0x18,0xFF}, ! 67: {0x1b,0x02}, ! 68: {-1, 0} ! 69: }; ! 70: ! 71: static const SVGAIndexValuePair ! 72: CirrusLogicGD542X_1024x768x2x60hz_graphicsControllerRegisters[] = { ! 73: {0x00,0x00}, {0x01,0x00}, {0x02,0x00}, {0x03,0x00}, {0x04,0x00}, ! 74: {0x05,0x00}, {0x06,0x05}, {0x07,0x0F}, {0x08,0xFF}, ! 75: {-1, 0} ! 76: }; ! 77: ! 78: static const SVGAIndexValuePair ! 79: CirrusLogicGD542X_1024x768x2x60hz_attributeControllerRegisters[] = { ! 80: {0x00,0x00}, {0x01,0x01}, {0x02,0x02}, {0x03,0x03}, {0x04,0x04}, ! 81: {0x05,0x05}, {0x06,0x14}, {0x07,0x07}, {0x08,0x38}, {0x09,0x39}, ! 82: {0x0A,0x3A}, {0x0B,0x3B}, {0x0C,0x3C}, {0x0D,0x3D}, {0x0E,0x3E}, ! 83: {0x0F,0x3F}, {0x10,0x01}, {0x11,0x00}, {0x12,0x0F}, {0x13,0x00}, ! 84: {0x14,0x00}, ! 85: {-1, 0} ! 86: }; ! 87: ! 88: ! 89: static const CirrusLogicGD542XMode ! 90: CirrusLogicGD542X_1024x768x2x60hz = { ! 91: "1024x768x2x60hz", ! 92: CirrusLogicGD542X_1024x768x2x60hz_generalRegisters, ! 93: CirrusLogicGD542X_1024x768x2x60hz_sequencerRegisters, ! 94: CirrusLogicGD542X_1024x768x2x60hz_crtControllerRegisters, ! 95: CirrusLogicGD542X_1024x768x2x60hz_graphicsControllerRegisters, ! 96: CirrusLogicGD542X_1024x768x2x60hz_attributeControllerRegisters ! 97: }; ! 98: ! 99: ! 100: /************************************** ! 101: * Framebuffer characteristics. ! 102: **************************************/ ! 103: ! 104: #define FRAMEBUFFER_ADDRESS ((void *) 0xa0000) ! 105: ! 106: static const IODisplayInfo modeTable[] = { ! 107: { ! 108: // ! 109: // CirrusLogicGD542X 1024 x 768 x 2 x 60hz ! 110: // ! 111: 1024, 768, 1024, ! 112: ! 113: // ! 114: // rowbytes = ! 115: // #bytes/scanline = ! 116: // ((pixels/line) * (2 bits/pixel) * (byte/8 bits)) = ! 117: // (pixel width / 4) ! 118: // ! 119: 256, 60, 0, IO_2BitsPerPixel, IO_OneIsBlackColorSpace, ! 120: "WW", 0, (void *)&CirrusLogicGD542X_1024x768x2x60hz ! 121: } ! 122: /* Add more modes here. */ ! 123: }; ! 124: #define modeTableCount (sizeof(modeTable) / sizeof(IODisplayInfo)) ! 125: ! 126: ! 127: @implementation CirrusLogicGD542X ! 128: ! 129: ! 130: // ! 131: // BEGIN: Implementation of private routines for SVGA ! 132: // ! 133: ! 134: ! 135: static void SetBrightness(unsigned int level) ! 136: // Description: Sets the screen's brightness. This implementation ! 137: // uses a fixed gamma value. It sets the palette ! 138: // values according to the brightness level. ! 139: { ! 140: unsigned char val; ! 141: ! 142: val = EV_SCALE_BRIGHTNESS(level, WHITE_PALETTE_VALUE); ! 143: outb(WRIT_COLR_PEL_AWMR, (unsigned char)WHITE_INDEX); ! 144: outb(WRIT_COLR_PEL_DATA, val); ! 145: outb(WRIT_COLR_PEL_DATA, val); ! 146: outb(WRIT_COLR_PEL_DATA, val); ! 147: ! 148: val = EV_SCALE_BRIGHTNESS(level, LIGHT_GRAY_PALETTE_VALUE); ! 149: outb(WRIT_COLR_PEL_AWMR, (unsigned char)LIGHT_GRAY_INDEX); ! 150: outb(WRIT_COLR_PEL_DATA, val); ! 151: outb(WRIT_COLR_PEL_DATA, val); ! 152: outb(WRIT_COLR_PEL_DATA, val); ! 153: ! 154: val = EV_SCALE_BRIGHTNESS(level, DARK_GRAY_PALETTE_VALUE); ! 155: outb(WRIT_COLR_PEL_AWMR, (unsigned char)DARK_GRAY_INDEX); ! 156: outb(WRIT_COLR_PEL_DATA, val); ! 157: outb(WRIT_COLR_PEL_DATA, val); ! 158: outb(WRIT_COLR_PEL_DATA, val); ! 159: ! 160: val = EV_SCALE_BRIGHTNESS(level, BLACK_PALETTE_VALUE); ! 161: outb(WRIT_COLR_PEL_AWMR, (unsigned char)BLACK_INDEX); ! 162: outb(WRIT_COLR_PEL_DATA, val); ! 163: outb(WRIT_COLR_PEL_DATA, val); ! 164: outb(WRIT_COLR_PEL_DATA, val); ! 165: } ! 166: ! 167: ! 168: static void setColorMapToLinearMonochrome() ! 169: // Description: Sets the color map to linear monochrome by zeroing ! 170: // out the entire table, then setting the first four ! 171: // palette values correctly. ! 172: { ! 173: int i; ! 174: ! 175: for (i = 0; i < 256; i++) { ! 176: outb(WRIT_COLR_PEL_AWMR, i); ! 177: outb(WRIT_COLR_PEL_DATA, 0x00); ! 178: outb(WRIT_COLR_PEL_DATA, 0x00); ! 179: outb(WRIT_COLR_PEL_DATA, 0x00); ! 180: } ! 181: outb(WRIT_COLR_PEL_AWMR, WHITE_INDEX); ! 182: outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE); ! 183: outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE); ! 184: outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE); ! 185: ! 186: outb(WRIT_COLR_PEL_AWMR, LIGHT_GRAY_INDEX); ! 187: outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE); ! 188: outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE); ! 189: outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE); ! 190: ! 191: outb(WRIT_COLR_PEL_AWMR, DARK_GRAY_INDEX); ! 192: outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE); ! 193: outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE); ! 194: outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE); ! 195: ! 196: outb(WRIT_COLR_PEL_AWMR, BLACK_INDEX); ! 197: outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE); ! 198: outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE); ! 199: outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE); ! 200: } ! 201: ! 202: ! 203: - (void) _selectMode ! 204: // Description: During initialization, this selects the configured mode ! 205: // and sets the display info accordingly. ! 206: { ! 207: selectedMode = [self selectMode:modeTable count:modeTableCount valid:NULL]; ! 208: ! 209: if (selectedMode < 0) { ! 210: IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]); ! 211: selectedMode = 0; ! 212: } ! 213: ! 214: *[self displayInfo] = modeTable[selectedMode]; ! 215: } ! 216: ! 217: ! 218: - (void)_SVGASetGeneralRegistersForMode: ! 219: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode ! 220: // Description: Set all the general registers for the given mode. ! 221: { ! 222: const SVGAIndexValuePair *regInfo; ! 223: ! 224: regInfo = cirrusLogicGD542XMode->generalRegisters; ! 225: while (regInfo->index != -1) { ! 226: outb(WRIT_EIDR_GEN_MISC_OP, regInfo->value); ! 227: regInfo++; ! 228: } ! 229: } ! 230: ! 231: ! 232: - (void)_SVGASetSequencerRegistersForMode: ! 233: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode ! 234: // Description: Set all the sequencer registers for the given mode. ! 235: { ! 236: const SVGAIndexValuePair *regInfo; ! 237: ! 238: regInfo = cirrusLogicGD542XMode->sequencerRegisters; ! 239: while (regInfo->index != -1) { ! 240: IOWriteRegister(EIDR_SEQ_ADDR, (char)(regInfo->index), regInfo->value); ! 241: regInfo++; ! 242: } ! 243: } ! 244: ! 245: ! 246: - (void)_SVGASetCrtControllerRegistersForMode: ! 247: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode ! 248: // Description: Set all the crt controller registers for the given mode. ! 249: { ! 250: const SVGAIndexValuePair *regInfo; ! 251: ! 252: regInfo = cirrusLogicGD542XMode->crtControllerRegisters; ! 253: while (regInfo->index != -1) { ! 254: IOWriteRegister(COLR_CRT_ADDR, (char)(regInfo->index), regInfo->value); ! 255: regInfo++; ! 256: } ! 257: } ! 258: ! 259: ! 260: - (void)_SVGASetGraphicsControllerRegistersForMode: ! 261: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode ! 262: // Description: Set all the graphics controller registers for the given mode. ! 263: { ! 264: const SVGAIndexValuePair *regInfo; ! 265: ! 266: regInfo = cirrusLogicGD542XMode->graphicsControllerRegisters; ! 267: while (regInfo->index != -1) { ! 268: IOWriteRegister(EIDR_GCR_ADDR, (char)(regInfo->index), regInfo->value); ! 269: regInfo++; ! 270: } ! 271: } ! 272: ! 273: ! 274: - (void)_SVGASetAttributeControllerRegistersForMode: ! 275: (const CirrusLogicGD542XMode *)cirrusLogicGD542XMode ! 276: // Description: Set all the attribute controller registers for the given mode. ! 277: { ! 278: const SVGAIndexValuePair *regInfo; ! 279: ! 280: regInfo = cirrusLogicGD542XMode->attributeControllerRegisters; ! 281: while (regInfo->index != -1) { ! 282: char tmpi; ! 283: inb(READ_COLR_GEN_IN_ST_1); ! 284: tmpi = inb(READ_TOGL_ACR_ADDR); ! 285: tmpi &= ~ACR_MSK; ! 286: tmpi |= (regInfo->index & ACR_MSK); ! 287: outb(WRIT_TOGL_ACR_ADDR, tmpi); ! 288: outb(WRIT_TOGL_ACR_DATA, regInfo->value); ! 289: regInfo++; ! 290: } ! 291: } ! 292: ! 293: ! 294: // ! 295: // END: Implementation of private routines for SVGA ! 296: // ! 297: ! 298: ! 299: // ! 300: // BEGIN: EXPORTED methods ! 301: // ! 302: ! 303: ! 304: - (void)setReadSegment: (unsigned char)segmentNum ! 305: // Description: Select which 64K segment we intend to read from. ! 306: { ! 307: outb(0x03ce,0x09); ! 308: outb(0x03cf,(segmentNum << 4)); ! 309: } ! 310: ! 311: ! 312: - (void)setWriteSegment: (unsigned char)segmentNum ! 313: // Description: Select which 64K segment we intend to write to. ! 314: { ! 315: outb(0x03ce,0x09); ! 316: outb(0x03cf,(segmentNum << 4)); ! 317: } ! 318: ! 319: ! 320: - (void)setReadPlane: (unsigned char)planeNum ! 321: // Description: Select which of 4 bit planes to read from in planar ! 322: // modes - only one plane can be active at a time. ! 323: { ! 324: char tmp; ! 325: ! 326: /* Select plane we are reading from */ ! 327: tmp = IOReadRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS); ! 328: tmp &= ~GCR_AT_RMS; ! 329: tmp |= (planeNum & GCR_AT_RMS); ! 330: IOWriteRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS, tmp); ! 331: } ! 332: ! 333: ! 334: - (void)setWritePlane: (unsigned char)planeNum ! 335: // Description: Select one of 4 bit planes to write to in planar modes. ! 336: // Although more than one plane can be active at a time, ! 337: // this routine only allows access to 1 plane at a time. ! 338: { ! 339: char tmp, plane = 0x01; ! 340: ! 341: // ! 342: // Convert plane num to bit enable. ! 343: // ! 344: plane = plane << (planeNum & 0x03); ! 345: ! 346: // ! 347: // Select plane we are writing to ! 348: // ! 349: tmp = IOReadRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK); ! 350: tmp &= ~(SEQ_AT_EM3 | SEQ_AT_EM2 | SEQ_AT_EM1 | SEQ_AT_EM0); ! 351: tmp |= plane; ! 352: IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK, tmp); ! 353: } ! 354: ! 355: ! 356: - (void)savePlaneAndSegmentSettings ! 357: // Description: Saves the current plane and segment settings. ! 358: // This is not a stack push, so we can only save/ ! 359: // restore one group of settings at a time. ! 360: { ! 361: writePlaneMask = IOReadRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK); ! 362: readPlaneMask = IOReadRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS); ! 363: outb(0x3ce,0x09); ! 364: readSegment = inb(0x3cf); ! 365: writeSegment=readSegment=(readSegment >> 4); ! 366: } ! 367: ! 368: ! 369: - (void)restorePlaneAndSegmentSettings ! 370: // Description: Restores the current plane and segment settings. ! 371: // This is not a stack pop, so we can only save/ ! 372: // restore one group of settings at a time. ! 373: { ! 374: IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK, writePlaneMask); ! 375: IOWriteRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS, readPlaneMask); ! 376: outb(0x3ce, 0x09); ! 377: outb(0x3cf, (readSegment << 4)); ! 378: } ! 379: ! 380: ! 381: - (void)enterSVGAMode ! 382: // Description: Put the display into SVGA mode selectedMode. This ! 383: // typically happens when the window server starts running. ! 384: // We set up all the registers necessary for the given ! 385: // mode and then clear the screen. ! 386: { ! 387: IODisplayInfo *displayInfo; ! 388: int totalScreenBytes, bytesLeftToClear, writeSegmentToClear; ! 389: ! 390: [self _SVGASetGeneralRegistersForMode: ! 391: modeTable[selectedMode].parameters]; ! 392: [self _SVGASetSequencerRegistersForMode: ! 393: modeTable[selectedMode].parameters]; ! 394: [self _SVGASetCrtControllerRegistersForMode: ! 395: modeTable[selectedMode].parameters]; ! 396: [self _SVGASetGraphicsControllerRegistersForMode: ! 397: modeTable[selectedMode].parameters]; ! 398: [self _SVGASetAttributeControllerRegistersForMode: ! 399: modeTable[selectedMode].parameters]; ! 400: ! 401: // ! 402: // re-enable timing sequencer ! 403: // ! 404: IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_CRS, 0x00); ! 405: setColorMapToLinearMonochrome(); ! 406: ! 407: // ! 408: // Clear the screen. ! 409: // ! 410: displayInfo = [self displayInfo]; ! 411: totalScreenBytes = displayInfo->rowBytes * displayInfo->height; ! 412: for ( bytesLeftToClear = totalScreenBytes, writeSegmentToClear = 0; ! 413: bytesLeftToClear > 0; ! 414: bytesLeftToClear -= 0x20000, writeSegmentToClear++) { ! 415: [self setWriteSegment:writeSegmentToClear]; ! 416: memset(displayInfo->frameBuffer, 0, MIN(0x20000, bytesLeftToClear)); ! 417: } ! 418: ! 419: [self setWriteSegment:0]; ! 420: } ! 421: ! 422: ! 423: - (void)revertToVGAMode ! 424: // Description: Put the display into VGA mode. This typically happens ! 425: // when SoftPC enters full-screen mode. We set up all the ! 426: // registers necessary for the given mode. ! 427: { ! 428: outb(WRIT_EIDR_GEN_MISC_OP, 0xE3); ! 429: } ! 430: ! 431: ! 432: - initFromDeviceDescription:deviceDescription ! 433: // Description: IODevice method. Initialize the current instance as ! 434: // per the deviceDescription. Most importantly, this ! 435: // includes selecting the mode and mapping the frame buffer. ! 436: { ! 437: IODisplayInfo *displayInfo; ! 438: const IORange *range; ! 439: const CirrusLogicGD542XMode *cirrusLogicGD542XMode; ! 440: ! 441: if ([super initFromDeviceDescription:deviceDescription] == nil) ! 442: return [super free]; ! 443: ! 444: [self _selectMode]; ! 445: ! 446: range = [deviceDescription memoryRangeList]; ! 447: if (range == 0) { ! 448: IOLog("%s: No memory range set.\n", [self name]); ! 449: return [super free]; ! 450: } ! 451: videoRamAddress = range[0].start; ! 452: ! 453: displayInfo = [self displayInfo]; ! 454: cirrusLogicGD542XMode = displayInfo->parameters; ! 455: ! 456: displayInfo->frameBuffer = ! 457: (void *)[self mapFrameBufferAtPhysicalAddress:videoRamAddress ! 458: length:0x20000]; //SCOTT--fix this ! 459: ! 460: if (displayInfo->frameBuffer == 0) ! 461: return [super free]; ! 462: ! 463: IOLog("%s: Initialized `%s' @ %d Hz.\n", [self name], ! 464: cirrusLogicGD542XMode->name, displayInfo->refreshRate); ! 465: ! 466: return self; ! 467: } ! 468: ! 469: ! 470: - setBrightness:(int)level token:(int)t ! 471: // Description: This is from the evScreen protocol. We override our superclass ! 472: // on this since it doesn't know how to set our brightness. ! 473: { ! 474: if ( level < EV_SCREEN_MIN_BRIGHTNESS ! 475: || level > EV_SCREEN_MAX_BRIGHTNESS ) ! 476: { ! 477: IOLog("%s: Invalid arg to setBrightness:%d\n", ! 478: [self name], level ); ! 479: ! 480: if (level < EV_SCREEN_MIN_BRIGHTNESS) { ! 481: level = EV_SCREEN_MIN_BRIGHTNESS; ! 482: } else { ! 483: level = EV_SCREEN_MAX_BRIGHTNESS; ! 484: } ! 485: } ! 486: SetBrightness(level); ! 487: ! 488: return self; ! 489: } ! 490: ! 491: ! 492: // ! 493: // END: EXPORTED methods ! 494: // ! 495: ! 496: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.