home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1993 by NeXT Computer, Inc.
- * All rights reserved.
- *
- * S3SetMode.m -- Mode support for the S3.
- *
- * Author: Derek B Clegg 21 May 1993
- * Based on work by Peter Graffagnino, 31 January 1993.
- */
- #import <string.h>
- #import <driverkit/generalFuncs.h>
- #import <driverkit/i386/ioPorts.h>
- #import "S3.h"
-
- /* The `S3SetMode' category of `S3'. */
-
- @implementation S3 (SetMode)
-
- - (void)reportConfiguration
- {
- const char *adapterString, *busString, *memString, *dacString;
-
- switch (adapter) {
- case S3_805: adapterString = "86C805"; break;
- case S3_928: adapterString = "86C928"; break;
- default: adapterString = "(unknown adapter)"; break;
- }
-
- switch (busConfiguration) {
- case S3_EISA_BUS: busString = "EISA"; break;
- case S3_LOCAL_BUS: busString = "Local"; break;
- case S3_ISA_BUS: busString = "ISA"; break;
- default: busString = "Unknown"; break;
- }
-
- switch (availableMemory) {
- case FOUR_MEGABYTES: memString = "4 Mb VRAM"; break;
- case THREE_MEGABYTES: memString = "3 Mb VRAM"; break;
- case TWO_MEGABYTES: memString = "2 Mb VRAM"; break;
- case ONE_MEGABYTE: memString = "1 Mb VRAM"; break;
- case ONE_MEGABYTE/2: memString = "500 Kb VRAM"; break;
- default: memString = "(unknown memory size)"; break;
- }
-
- switch (dac) {
- case Bt484: dacString = "Brooktree 484"; break;
- case Bt485: dacString = "Brooktree 485"; break;
- case Bt485A: dacString = "Brooktree 485A"; break;
- case ATT20C491: dacString = "AT&T 20C491 or compatible"; break;
- default: dacString = "Unknown"; break;
- }
-
- IOLog("%s: S3 %s; %s bus; %s; %s DAC.\n", [self name], adapterString,
- busString, memString, dacString);
- }
-
- - determineConfiguration
- {
- int value, lockRegisterValue;
-
- /* If we turn out not to be an S3, we preserve the old value
- * of the lock register. */
-
- lockRegisterValue = rread(VGA_CRTC_INDEX, S3_REG_LOCK1);
- rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, S3_LOCK1_KEY);
-
- /* Get the adapter type. */
-
- value = rread(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX);
-
- switch (value & S3_CHIP_ID_MASK) {
- case S3_CHIP_ID_805:
- adapter = S3_805;
- modeTable = S3_805_ModeTable;
- modeTableCount = S3_805_ModeTableCount;
- break;
- case S3_CHIP_ID_928:
- adapter = S3_928;
- modeTable = S3_928_ModeTable;
- modeTableCount = S3_928_ModeTableCount;
- break;
- default:
- IOLog("%s: Unrecognized adapter.\n", [self name]);
- /* If we're not an S3, reset things to the way we found them.... */
- rwrite(VGA_CRTC_INDEX, S3_CHIP_ID_INDEX, value);
- rwrite(VGA_CRTC_INDEX, S3_REG_LOCK1, lockRegisterValue);
- adapter = UnknownAdapter;
- modeTable = 0;
- modeTableCount = 0;
- return nil;
- break;
- }
-
- /* Get the bus and memory configuration. */
-
- value = rread(VGA_CRTC_INDEX, S3_CONFG_REG1_INDEX);
-
- busConfiguration = value & S3_BUS_SELECT_MASK;
-
- switch (value & S3_MEM_SIZE_MASK) {
- case S3_HALF_MEG: availableMemory = ONE_MEGABYTE/2; break;
- case S3_1_MEG: availableMemory = ONE_MEGABYTE; break;
- case S3_2_MEG: availableMemory = TWO_MEGABYTES; break;
- case S3_3_MEG: availableMemory = THREE_MEGABYTES; break;
- case S3_4_MEG: availableMemory = FOUR_MEGABYTES; break;
- default:
- IOLog("%s: Unrecognized memory configuration.\n", [self name]);
- availableMemory = 0;
- return nil;
- }
-
- [self determineDACType];
- [self reportConfiguration];
-
- S3_lockRegisters();
- return self;
- }
-
- /* Select a display mode based on the adapter type, the bus configuration,
- * and the memory configuration. Return the selected mode, or -1 if no mode
- * is valid.
- */
- - selectMode
- {
- int k, mode;
- const S3Mode *modeData;
- BOOL valid[modeTableCount];
-
- for (k = 0; k < modeTableCount; k++) {
- modeData = modeTable[k].parameters;
- valid[k] = (modeData->memSize <= availableMemory
- && modeData->adapter == adapter);
- }
-
- mode = [self selectMode:modeTable count:modeTableCount valid:valid];
- if (mode < 0) {
- IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
- if (adapter == S3_805)
- mode = S3_805_defaultMode;
- else
- mode = S3_928_defaultMode;
- }
- *[self displayInfo] = modeTable[mode];
- return self;
- }
-
- - initializeMode
- {
- int k, count;
- const S3Mode *mode;
- const IODisplayInfo *displayInfo;
- unsigned char crtc[VGA_CRTC_COUNT];
- unsigned char miscOutput[1];
- unsigned char xcrtc[2*S3_EXTENDED_REGISTER_MAX];
- unsigned char modeControl[S3_MODE_COUNT];
- unsigned char advFunctionControl[1];
-
- displayInfo = [self displayInfo];
- mode = displayInfo->parameters;
-
- /* Turn off the screen. */
-
- outb(VGA_SEQ_DATA, mode->vgaData.seqx[1] | 0x20);
-
- /* Sequencer. */
-
- for (k = 0; k < VGA_SEQ_COUNT; k++) {
- if (k == 1)
- continue;
- outb(VGA_SEQ_INDEX, k);
- outb(VGA_SEQ_DATA, mode->vgaData.seqx[k]);
- }
-
- S3_unlockRegisters();
-
- /* Unlock the CRTC registers. */
- rrmw(VGA_CRTC_INDEX, 0x11, ~0x80, 0x00);
- rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00);
-
- /* Set up the CRTC parameters. */
-
- count = [self parametersForMode:mode->name
- forStringKey:"CRTC Registers"
- parameters:crtc
- count:sizeof(crtc)];
- if (count > 0) {
- IOLog("%s: Using crtc parameters from instance table.\n", [self name]);
- for (k = 0; k < count; k++)
- rwrite(VGA_CRTC_INDEX, k, crtc[k]);
- } else {
- for (k = 0; k < VGA_CRTC_COUNT; k++)
- rwrite(VGA_CRTC_INDEX, k, mode->vgaData.crtc[k]);
- }
-
- /* Initialize the address flip-flop for the attribute controller. */
-
- inb(VGA_INPUT_STATUS_1);
- /* Set up the attribute controller registers. */
- for (k = 0; k < VGA_ATTR_COUNT; k++) {
- outb(VGA_ATTR_INDEX, k);
- outb(VGA_ATTR_DATA, mode->vgaData.attr[k]);
- }
-
- /* Start the sequencer. */
- rwrite(VGA_SEQ_INDEX, 0x00, 0x03);
-
- /* Set up the graphics controller registers. */
- for (k = 0; k < VGA_GRFX_COUNT; k++)
- rwrite(VGA_GRFX_INDEX, k, mode->vgaData.grfx[k]);
-
- /* Set the miscellaneous output register (0x3C2). */
-
- count = [self parametersForMode:mode->name
- forStringKey:"MiscOutput Register"
- parameters:miscOutput
- count:sizeof(miscOutput)];
- if (count > 0) {
- IOLog("%s: Using miscOutput parameter from instance table.\n",
- [self name]);
- outb(VGA_MISC_OUTPUT, miscOutput[0]);
- } else {
- outb(VGA_MISC_OUTPUT, mode->vgaData.miscOutput);
- }
-
- /* Reset the address flip-flop for the attribute controller and
- * enable the palette. */
- inb(VGA_INPUT_STATUS_1);
- outb(VGA_ATTR_INDEX, 0x20);
-
- /* Set up the extended CRTC registers. */
-
- count = [self parametersForMode:mode->name
- forStringKey:"XCRTC Registers"
- parameters:xcrtc
- count:sizeof(xcrtc)];
- if (count > 0) {
- IOLog("%s: Using extended crtc parameters from instance table.\n",
- [self name]);
- for (k = 0; k < count && xcrtc[k] != 0; k += 2)
- rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]);
- } else {
- for (k = 0; k < S3_XCRTC_COUNT && mode->xcrtc[k] != 0; k += 2)
- rwrite(VGA_CRTC_INDEX, mode->xcrtc[k], mode->xcrtc[k+1]);
- }
-
- /* Set the mode control register. */
- count = [self parametersForMode:mode->name
- forStringKey:"Mode Control Register"
- parameters:modeControl
- count:sizeof(modeControl)];
- if (count > 0) {
- IOLog("%s: Using mode control parameters from instance table.\n",
- [self name]);
- for (k = 0; k < count; k += 2) {
- if (displayInfo->refreshRate == modeControl[k]/*refreshRate*/) {
- rwrite(VGA_CRTC_INDEX, 0x42, modeControl[k+1]/*modeControl*/);
- break;
- }
- }
- if (k >= count)
- IOLog("%s: Warning: Unable to set the refresh rate.\n",
- [self name]);
- } else {
- for (k = 0; k < S3_MODE_COUNT; k++) {
- if (displayInfo->refreshRate == mode->modeControl[k].refreshRate) {
- rwrite(VGA_CRTC_INDEX, 0x42, mode->modeControl[k].modeControl);
- break;
- }
- }
- if (k == S3_MODE_COUNT)
- IOLog("%s: Warning: Unable to set the refresh rate.\n",
- [self name]);
- }
-
- /* Unlock access to the enhanced commands registers. */
- rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01);
-
- /* Set the advanced function control register (0x4AE8). */
-
- count = [self parametersForMode:mode->name
- forStringKey:"Advanced Function Control Register"
- parameters:advFunctionControl
- count:sizeof(advFunctionControl)];
- if (count > 0) {
- outw(S3_ADVFUNC_CNTL, advFunctionControl[0]);
- } else {
- outw(S3_ADVFUNC_CNTL, mode->advFuncCntl);
- }
-
- /* Lock the register set. */
- rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x00);
-
- /* Program the DAC. */
- [self programDAC];
-
- /* Lock the registers. */
- S3_lockRegisters();
-
- /* Enable the screen */
- rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x00);
- return self;
- }
-
- - enableLinearFrameBuffer
- {
- int lawSize;
- S3Mode *mode;
- IODisplayInfo *displayInfo;
-
- displayInfo = [self displayInfo];
- mode = displayInfo->parameters;
-
- S3_unlockRegisters();
-
- /* Tell the chip where the frame buffer is mapped in. */
-
- rwrite(VGA_CRTC_INDEX, S3_LAW_POS_LO, (videoRamAddress >> 16) & 0xFF);
- rwrite(VGA_CRTC_INDEX, S3_LAW_POS_HI, (videoRamAddress >> 24) & 0xFF);
-
- /* Set the linear address window size. */
-
- switch (mode->memSize) {
- case ONE_MEGABYTE:
- lawSize = S3_LAW_SIZE_1M;
- break;
- case TWO_MEGABYTES:
- lawSize = S3_LAW_SIZE_2M;
- break;
- case THREE_MEGABYTES:
- case FOUR_MEGABYTES:
- lawSize = S3_LAW_SIZE_4M;
- break;
- default:
- IOLog("%s: Invalid linear address window size for mode `%s'.\n",
- [self name], mode->name);
- return nil;
- }
-
- /* Set the linear address window size. */
- rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_SIZE_MASK, lawSize);
-
- if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) {
- /* Wait for the graphics accelerator to stop. */
- while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK)
- ;
- /* Disable 8514 register access. */
- rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK,
- S3_8514_DISABLE_ACCESS);
- }
-
- /* Turn off mmio. */
- rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_1, ~S3_MMIO_ACCESS_MASK,
- S3_DISABLE_MMIO_ACCESS);
-
- if (writePostingEnabled) {
- /* Enable fast write buffer (write posting into FIFO). */
- rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK,
- S3_WRITE_POST_ENABLE);
- } else {
- /* Disable fast write buffer. */
- rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_WRITE_POST_MASK,
- S3_WRITE_POST_DISABLE);
- }
-
- if (readAheadCacheEnabled) {
- /* Enable read-ahead cache. */
- rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK,
- S3_ENABLE_PREFETCH);
- /* Max out the read-ahead cache. */
- rrmw(VGA_CRTC_INDEX, S3_EX_MCTL_2, ~S3_PREFETCH_CTRL_MASK,
- S3_PREFETCH_MAX);
- } else {
- /* Disable read-ahead cache. */
- rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_PREFETCH_MASK,
- S3_DISABLE_PREFETCH);
- }
-
- /* Turn on the linear address window. */
- rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_ENABLE_LAW);
-
- S3_lockRegisters();
-
- /* Clear the screen. */
- memset(displayInfo->frameBuffer, 0, mode->memSize);
- return self;
- }
-
- - resetVGA
- {
- int k;
- static const unsigned char xcrtc[S3_XCRTC_COUNT] = {
- 0x31, 0x85, 0x32, 0x10, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
- 0x3A, 0x85, 0x3B, 0x5A, 0x3C, 0x10, 0x40, 0x58, 0x43, 0x00,
- 0x50, 0x00, 0x51, 0x00, 0x53, 0x00, 0x54, 0x38, 0x56, 0x00,
- 0x57, 0x00, 0x5C, 0x31, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00,
- 0x60, 0x07, 0x61, 0x80, 0x62, 0xA1, 0x63, 0xA1,
- };
-
- /* Disable the linear framebuffer. */
- S3_unlockRegisters();
-
- if (rread(VGA_CRTC_INDEX, S3_SYS_CNFG) & S3_8514_ACCESS_MASK) {
- /* Wait for the graphics accelerator to stop. */
- while (inw(S3_GP_STAT) & S3_GP_BUSY_MASK)
- ;
- /* Disable 8514 register access. */
- rrmw(VGA_CRTC_INDEX, S3_SYS_CNFG, ~S3_8514_ACCESS_MASK,
- S3_8514_DISABLE_ACCESS);
- }
-
- /* Turn off the linear address window. */
- rrmw(VGA_CRTC_INDEX, S3_LAW_CTL, ~S3_LAW_ENABLE_MASK, S3_DISABLE_LAW);
-
- /* Turn off the display. */
- rrmw(VGA_SEQ_INDEX, 0x01, 0xDF, 0x20);
-
- /* Unlock the CRTC registers. */
- rrmw(VGA_CRTC_INDEX, 0x35, ~0x30, 0x00);
-
- /* Unlock access to the enhanced commands registers. */
- rrmw(VGA_CRTC_INDEX, 0x40, ~0x01, 0x01);
-
- /* Set VGA mode. */
- outw(S3_ADVFUNC_CNTL, 0x02);
-
- /* Set the DAC for VGA mode. */
- [self resetDAC];
-
- /* Set up the extended CRTC registers. */
- for (k = 0; k < S3_XCRTC_COUNT && xcrtc[k] != 0; k += 2)
- rwrite(VGA_CRTC_INDEX, xcrtc[k], xcrtc[k+1]);
-
- VGASetMode(0x03);
-
- S3_lockRegisters();
-
- return self;
- }
- @end
-