|
|
1.1 ! root 1: /* Copyright (c) 1993 by NeXT Computer, Inc. ! 2: * All rights reserved. ! 3: * ! 4: * S3SetMode.m -- Mode support for the S3. ! 5: * ! 6: * Author: Derek B Clegg 21 May 1993 ! 7: * Based on work by Peter Graffagnino, 31 January 1993. ! 8: */ ! 9: #import <string.h> ! 10: #import <driverkit/generalFuncs.h> ! 11: #import <driverkit/i386/ioPorts.h> ! 12: #import "S3.h" ! 13: ! 14: /* The `S3SetMode' category of `S3'. */ ! 15: ! 16: @implementation S3 (SetMode) ! 17: ! 18: - (void)reportConfiguration ! 19: { ! 20: const char *adapterString, *busString, *memString, *dacString; ! 21: ! 22: switch (adapter) { ! 23: case S3_805: adapterString = "86C805"; break; ! 24: case S3_928: adapterString = "86C928"; break; ! 25: default: adapterString = "(unknown adapter)"; break; ! 26: } ! 27: ! 28: switch (busConfiguration) { ! 29: case S3_EISA_BUS: busString = "EISA"; break; ! 30: case S3_LOCAL_BUS: busString = "Local"; break; ! 31: case S3_ISA_BUS: busString = "ISA"; break; ! 32: default: busString = "Unknown"; break; ! 33: } ! 34: ! 35: switch (availableMemory) { ! 36: case FOUR_MEGABYTES: memString = "4 Mb VRAM"; break; ! 37: case THREE_MEGABYTES: memString = "3 Mb VRAM"; break; ! 38: case TWO_MEGABYTES: memString = "2 Mb VRAM"; break; ! 39: case ONE_MEGABYTE: memString = "1 Mb VRAM"; break; ! 40: case ONE_MEGABYTE/2: memString = "500 Kb VRAM"; break; ! 41: default: memString = "(unknown memory size)"; break; ! 42: } ! 43: ! 44: switch (dac) { ! 45: case Bt484: dacString = "Brooktree 484"; break; ! 46: case Bt485: dacString = "Brooktree 485"; break; ! 47: case Bt485A: dacString = "Brooktree 485A"; break; ! 48: case ATT20C491: dacString = "AT&T 20C491 or compatible"; break; ! 49: default: dacString = "Unknown"; break; ! 50: } ! 51: ! 52: IOLog("%s: S3 %s; %s bus; %s; %s DAC.\n", [self name], adapterString, ! 53: busString, memString, dacString); ! 54: } ! 55: ! 56: - determineConfiguration ! 57: { ! 58: int value, lockRegisterValue; ! 59: ! 60: /* If we turn out not to be an S3, we preserve the old value ! 61: * of the lock register. */ ! 62: ! 63: lockRegisterValue = rread(VGA_CRTC_INDEX, S3_REG_LOCK1); ! 64: rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, S3_LOCK1_KEY); ! 65: ! 66: /* Get the adapter type. */ ! 67: ! 68: value = rread(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX); ! 69: ! 70: switch (value & S3_CHIP_ID_MASK) { ! 71: case S3_CHIP_ID_805: ! 72: adapter = S3_805; ! 73: modeTable = S3_805_ModeTable; ! 74: modeTableCount = S3_805_ModeTableCount; ! 75: break; ! 76: case S3_CHIP_ID_928: ! 77: adapter = S3_928; ! 78: modeTable = S3_928_ModeTable; ! 79: modeTableCount = S3_928_ModeTableCount; ! 80: break; ! 81: default: ! 82: IOLog("%s: Unrecognized adapter.\n", [self name]); ! 83: /* If we're not an S3, reset things to the way we found them.... */ ! 84: rwrite(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX, value); ! 85: rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, lockRegisterValue); ! 86: adapter = UnknownAdapter; ! 87: modeTable = 0; ! 88: modeTableCount = 0; ! 89: return nil; ! 90: break; ! 91: } ! 92: ! 93: /* Get the bus and memory configuration. */ ! 94: ! 95: value = rread(VGA_CRTC_INDEX, S3_CONFG_REG1_INDEX); ! 96: ! 97: busConfiguration = value & S3_BUS_SELECT_MASK; ! 98: ! 99: switch (value & S3_MEM_SIZE_MASK) { ! 100: case S3_HALF_MEG: availableMemory = ONE_MEGABYTE/2; break; ! 101: case S3_1_MEG: availableMemory = ONE_MEGABYTE; break; ! 102: case S3_2_MEG: availableMemory = TWO_MEGABYTES; break; ! 103: case S3_3_MEG: availableMemory = THREE_MEGABYTES; break; ! 104: case S3_4_MEG: availableMemory = FOUR_MEGABYTES; break; ! 105: default: ! 106: IOLog("%s: Unrecognized memory configuration.\n", [self name]); ! 107: availableMemory = 0; ! 108: return nil; ! 109: } ! 110: ! 111: [self determineDACType]; ! 112: [self reportConfiguration]; ! 113: ! 114: S3_lockRegisters(); ! 115: return self; ! 116: } ! 117: ! 118: /* Select a display mode based on the adapter type, the bus configuration, ! 119: * and the memory configuration. Return the selected mode, or -1 if no mode ! 120: * is valid. ! 121: */ ! 122: - selectMode ! 123: { ! 124: int k, mode; ! 125: const S3Mode *modeData; ! 126: BOOL valid[modeTableCount]; ! 127: ! 128: for (k = 0; k < modeTableCount; k++) { ! 129: modeData = modeTable[k].parameters; ! 130: valid[k] = (modeData->memSize <= availableMemory ! 131: && modeData->adapter == adapter); ! 132: } ! 133: ! 134: mode = [self selectMode:modeTable count:modeTableCount valid:valid]; ! 135: if (mode < 0) { ! 136: IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]); ! 137: if (adapter == S3_805) ! 138: mode = S3_805_defaultMode; ! 139: else ! 140: mode = S3_928_defaultMode; ! 141: } ! 142: *[self displayInfo] = modeTable[mode]; ! 143: return self; ! 144: } ! 145: ! 146: - initializeMode ! 147: { ! 148: int k, count; ! 149: const S3Mode *mode; ! 150: const IODisplayInfo *displayInfo; ! 151: unsigned char crtc[VGA_CRTC_COUNT]; ! 152: unsigned char miscOutput[1]; ! 153: unsigned char xcrtc[2*S3_EXTENDED_REGISTER_MAX]; ! 154: unsigned char modeControl[S3_MODE_COUNT]; ! 155: unsigned char advFunctionControl[1]; ! 156: ! 157: displayInfo = [self displayInfo]; ! 158: mode = displayInfo->parameters; ! 159: ! 160: /* Turn off the screen. */ ! 161: ! 162: outb(VGA_SEQ_DATA, mode->vgaData.seqx[1] | 0x20); ! 163: ! 164: /* Sequencer. */ ! 165: ! 166: for (k = 0; k < VGA_SEQ_COUNT; k++) { ! 167: if (k == 1) ! 168: continue; ! 169: outb(VGA_SEQ_INDEX, k); ! 170: outb(VGA_SEQ_DATA, mode->vgaData.seqx[k]); ! 171: } ! 172: ! 173: S3_unlockRegisters(); ! 174: ! 175: /* Unlock the CRTC registers. */ ! 176: rrmw(VGA_CRTC_INDEX, 0x11, ~0x80, 0x00); ! 177: rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00); ! 178: ! 179: /* Set up the CRTC parameters. */ ! 180: ! 181: count = [self parametersForMode:mode->name ! 182: forStringKey:"CRTC Registers" ! 183: parameters:crtc ! 184: count:sizeof(crtc)]; ! 185: if (count > 0) { ! 186: IOLog("%s: Using crtc parameters from instance table.\n", [self name]); ! 187: for (k = 0; k < count; k++) ! 188: rwrite(VGA_CRTC_INDEX, k, crtc[k]); ! 189: } else { ! 190: for (k = 0; k < VGA_CRTC_COUNT; k++) ! 191: rwrite(VGA_CRTC_INDEX, k, mode->vgaData.crtc[k]); ! 192: } ! 193: ! 194: /* Initialize the address flip-flop for the attribute controller. */ ! 195: ! 196: inb(VGA_INPUT_STATUS_1); ! 197: /* Set up the attribute controller registers. */ ! 198: for (k = 0; k < VGA_ATTR_COUNT; k++) { ! 199: outb(VGA_ATTR_INDEX, k); ! 200: outb(VGA_ATTR_DATA, mode->vgaData.attr[k]); ! 201: } ! 202: ! 203: /* Start the sequencer. */ ! 204: rwrite(VGA_SEQ_INDEX, 0x00, 0x03); ! 205: ! 206: /* Set up the graphics controller registers. */ ! 207: for (k = 0; k < VGA_GRFX_COUNT; k++) ! 208: rwrite(VGA_GRFX_INDEX, k, mode->vgaData.grfx[k]); ! 209: ! 210: /* Set the miscellaneous output register (0x3C2). */ ! 211: ! 212: count = [self parametersForMode:mode->name ! 213: forStringKey:"MiscOutput Register" ! 214: parameters:miscOutput ! 215: count:sizeof(miscOutput)]; ! 216: if (count > 0) { ! 217: IOLog("%s: Using miscOutput parameter from instance table.\n", ! 218: [self name]); ! 219: outb(VGA_MISC_OUTPUT, miscOutput[0]); ! 220: } else { ! 221: outb(VGA_MISC_OUTPUT, mode->vgaData.miscOutput); ! 222: } ! 223: ! 224: /* Reset the address flip-flop for the attribute controller and ! 225: * enable the palette. */ ! 226: inb(VGA_INPUT_STATUS_1); ! 227: outb(VGA_ATTR_INDEX, 0x20); ! 228: ! 229: /* Set up the extended CRTC registers. */ ! 230: ! 231: count = [self parametersForMode:mode->name ! 232: forStringKey:"XCRTC Registers" ! 233: parameters:xcrtc ! 234: count:sizeof(xcrtc)]; ! 235: if (count > 0) { ! 236: IOLog("%s: Using extended crtc parameters from instance table.\n", ! 237: [self name]); ! 238: for (k = 0; k < count && xcrtc[k] != 0; k += 2) ! 239: rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]); ! 240: } else { ! 241: for (k = 0; k < S3_XCRTC_COUNT && mode->xcrtc[k] != 0; k += 2) ! 242: rwrite(VGA_CRTC_INDEX, mode->xcrtc[k], mode->xcrtc[k+1]); ! 243: } ! 244: ! 245: /* Set the mode control register. */ ! 246: count = [self parametersForMode:mode->name ! 247: forStringKey:"Mode Control Register" ! 248: parameters:modeControl ! 249: count:sizeof(modeControl)]; ! 250: if (count > 0) { ! 251: IOLog("%s: Using mode control parameters from instance table.\n", ! 252: [self name]); ! 253: for (k = 0; k < count; k += 2) { ! 254: if (displayInfo->refreshRate == modeControl[k]/*refreshRate*/) { ! 255: rwrite(VGA_CRTC_INDEX, 0x42, modeControl[k+1]/*modeControl*/); ! 256: break; ! 257: } ! 258: } ! 259: if (k >= count) ! 260: IOLog("%s: Warning: Unable to set the refresh rate.\n", ! 261: [self name]); ! 262: } else { ! 263: for (k = 0; k < S3_MODE_COUNT; k++) { ! 264: if (displayInfo->refreshRate == mode->modeControl[k].refreshRate) { ! 265: rwrite(VGA_CRTC_INDEX, 0x42, mode->modeControl[k].modeControl); ! 266: break; ! 267: } ! 268: } ! 269: if (k == S3_MODE_COUNT) ! 270: IOLog("%s: Warning: Unable to set the refresh rate.\n", ! 271: [self name]); ! 272: } ! 273: ! 274: /* Unlock access to the enhanced commands registers. */ ! 275: rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01); ! 276: ! 277: /* Set the advanced function control register (0x4AE8). */ ! 278: ! 279: count = [self parametersForMode:mode->name ! 280: forStringKey:"Advanced Function Control Register" ! 281: parameters:advFunctionControl ! 282: count:sizeof(advFunctionControl)]; ! 283: if (count > 0) { ! 284: outw(S3_ADVFUNC_CNTL, advFunctionControl[0]); ! 285: } else { ! 286: outw(S3_ADVFUNC_CNTL, mode->advFuncCntl); ! 287: } ! 288: ! 289: /* Lock the register set. */ ! 290: rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x00); ! 291: ! 292: /* Program the DAC. */ ! 293: [self programDAC]; ! 294: ! 295: /* Lock the registers. */ ! 296: S3_lockRegisters(); ! 297: ! 298: /* Enable the screen */ ! 299: rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x00); ! 300: return self; ! 301: } ! 302: ! 303: - enableLinearFrameBuffer ! 304: { ! 305: int lawSize; ! 306: S3Mode *mode; ! 307: IODisplayInfo *displayInfo; ! 308: ! 309: displayInfo = [self displayInfo]; ! 310: mode = displayInfo->parameters; ! 311: ! 312: S3_unlockRegisters(); ! 313: ! 314: /* Tell the chip where the frame buffer is mapped in. */ ! 315: ! 316: rwrite(VGA_CRTC_INDEX, S3_LAW_POS_LO, (videoRamAddress >> 16) & 0xFF); ! 317: rwrite(VGA_CRTC_INDEX, S3_LAW_POS_HI, (videoRamAddress >> 24) & 0xFF); ! 318: ! 319: /* Set the linear address window size. */ ! 320: ! 321: switch (mode->memSize) { ! 322: case ONE_MEGABYTE: ! 323: lawSize = S3_LAW_SIZE_1M; ! 324: break; ! 325: case TWO_MEGABYTES: ! 326: lawSize = S3_LAW_SIZE_2M; ! 327: break; ! 328: case THREE_MEGABYTES: ! 329: case FOUR_MEGABYTES: ! 330: lawSize = S3_LAW_SIZE_4M; ! 331: break; ! 332: default: ! 333: IOLog("%s: Invalid linear address window size for mode `%s'.\n", ! 334: [self name], mode->name); ! 335: return nil; ! 336: } ! 337: ! 338: /* Set the linear address window size. */ ! 339: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_SIZE_MASK, lawSize); ! 340: ! 341: if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) { ! 342: /* Wait for the graphics accelerator to stop. */ ! 343: while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK) ! 344: ; ! 345: /* Disable 8514 register access. */ ! 346: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK, ! 347: S3_8514_DISABLE_ACCESS); ! 348: } ! 349: ! 350: /* Turn off mmio. */ ! 351: rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_1, ~S3_MMIO_ACCESS_MASK, ! 352: S3_DISABLE_MMIO_ACCESS); ! 353: ! 354: if (writePostingEnabled) { ! 355: /* Enable fast write buffer (write posting into FIFO). */ ! 356: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK, ! 357: S3_WRITE_POST_ENABLE); ! 358: } else { ! 359: /* Disable fast write buffer. */ ! 360: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK, ! 361: S3_WRITE_POST_DISABLE); ! 362: } ! 363: ! 364: if (readAheadCacheEnabled) { ! 365: /* Enable read-ahead cache. */ ! 366: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK, ! 367: S3_ENABLE_PREFETCH); ! 368: /* Max out the read-ahead cache. */ ! 369: rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_2, ~S3_PREFETCH_CTRL_MASK, ! 370: S3_PREFETCH_MAX); ! 371: } else { ! 372: /* Disable read-ahead cache. */ ! 373: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK, ! 374: S3_DISABLE_PREFETCH); ! 375: } ! 376: ! 377: /* Turn on the linear address window. */ ! 378: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_ENABLE_LAW); ! 379: ! 380: S3_lockRegisters(); ! 381: ! 382: /* Clear the screen. */ ! 383: memset(displayInfo->frameBuffer, 0, mode->memSize); ! 384: return self; ! 385: } ! 386: ! 387: - resetVGA ! 388: { ! 389: int k; ! 390: static const unsigned char xcrtc[S3_XCRTC_COUNT] = { ! 391: 0x31, 0x85, 0x32, 0x10, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, ! 392: 0x3A, 0x85, 0x3B, 0x5A, 0x3C, 0x10, 0x40, 0x58, 0x43, 0x00, ! 393: 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x54, 0x38, 0x56, 0x00, ! 394: 0x57, 0x00, 0x5C, 0x31, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, ! 395: 0x60, 0x07, 0x61, 0x80, 0x62, 0xA1, 0x63, 0xA1, ! 396: }; ! 397: ! 398: /* Disable the linear framebuffer. */ ! 399: S3_unlockRegisters(); ! 400: ! 401: if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) { ! 402: /* Wait for the graphics accelerator to stop. */ ! 403: while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK) ! 404: ; ! 405: /* Disable 8514 register access. */ ! 406: rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK, ! 407: S3_8514_DISABLE_ACCESS); ! 408: } ! 409: ! 410: /* Turn off the linear address window. */ ! 411: rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_DISABLE_LAW); ! 412: ! 413: /* Turn off the display. */ ! 414: rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x20); ! 415: ! 416: /* Unlock the CRTC registers. */ ! 417: rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00); ! 418: ! 419: /* Unlock access to the enhanced commands registers. */ ! 420: rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01); ! 421: ! 422: /* Set VGA mode. */ ! 423: outw(S3_ADVFUNC_CNTL, 0x02); ! 424: ! 425: /* Set the DAC for VGA mode. */ ! 426: [self resetDAC]; ! 427: ! 428: /* Set up the extended CRTC registers. */ ! 429: for (k = 0; k < S3_XCRTC_COUNT && xcrtc[k] != 0; k += 2) ! 430: rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]); ! 431: ! 432: VGASetMode(0x03); ! 433: ! 434: S3_lockRegisters(); ! 435: ! 436: return self; ! 437: } ! 438: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.