home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OpenStep 4.2J (Developer)
/
os42jdev.iso
/
NextDeveloper
/
Examples
/
DriverKit
/
CirrusLogicGD542X
/
CirrusLogicGD542X_reloc.tproj
/
CirrusLogicGD542X.m
< prev
next >
Wrap
Text File
|
1993-08-06
|
14KB
|
497 lines
/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
*
* CirrusLogicGD542X.m
*
*/
#import <driverkit/i386/IOEISADeviceDescription.h>
#import "CirrusLogicGD542X.h"
#import <kernserv/kern_server_types.h>
#import <driverkit/i386/displayRegisters.h>
#import <stdio.h>
#import <string.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
//
// typedef used to store arrays of register index and values.
// -1 as index indicates end of the set...
//
typedef struct _SVGAIndexValuePair {
signed short index;
unsigned char value;
} SVGAIndexValuePair;
//
// typedef defining a given graphics mode. A graphics mode
// consists of all the register/value pairs that, when set,
// completely define a mode of operation.
//
typedef struct _CirrusLogicGD542XMode {
const char *name; /* human-readable mode name */
const SVGAIndexValuePair *generalRegisters;
const SVGAIndexValuePair *sequencerRegisters;
const SVGAIndexValuePair *crtControllerRegisters;
const SVGAIndexValuePair *graphicsControllerRegisters;
const SVGAIndexValuePair *attributeControllerRegisters;
} CirrusLogicGD542XMode;
/***************************************
* CirrusLogicGD542X_1024x768x2x60hz mode
***************************************/
static const SVGAIndexValuePair
CirrusLogicGD542X_1024x768x2x60hz_generalRegisters[] = {
{0, 0x3F},
{-1, 0}
};
static const SVGAIndexValuePair
CirrusLogicGD542X_1024x768x2x60hz_sequencerRegisters[] = {
{0, 0x03}, {1, 0x01}, {2, 0x0F}, {3, 0x00}, {4, 0x06},
{-1, 0}
};
static const SVGAIndexValuePair
CirrusLogicGD542X_1024x768x2x60hz_crtControllerRegisters[] = {
{0x11,0x00}, // Turn off lock allowing changing 0..7
{0x00,0xA1}, {0x01,0x7F}, {0x02,0x80}, {0x03,0x04}, {0x04,0x88},
{0x05,0x9E}, {0x06,0x26}, {0x07,0xFD}, {0x08,0x00}, {0x09,0x60},
{0x0A,0x00}, {0x0B,0x00}, {0x0C,0x00}, {0x0D,0x00}, {0x0E,0x00},
{0x0F,0x00}, {0x10,0x08}, {0x11,0x8A}, {0x12,0xFF}, {0x13,0x40},
{0x14,0x00}, {0x15,0x04}, {0x16,0x22}, {0x17,0xC3}, {0x18,0xFF},
{0x1b,0x02},
{-1, 0}
};
static const SVGAIndexValuePair
CirrusLogicGD542X_1024x768x2x60hz_graphicsControllerRegisters[] = {
{0x00,0x00}, {0x01,0x00}, {0x02,0x00}, {0x03,0x00}, {0x04,0x00},
{0x05,0x00}, {0x06,0x05}, {0x07,0x0F}, {0x08,0xFF},
{-1, 0}
};
static const SVGAIndexValuePair
CirrusLogicGD542X_1024x768x2x60hz_attributeControllerRegisters[] = {
{0x00,0x00}, {0x01,0x01}, {0x02,0x02}, {0x03,0x03}, {0x04,0x04},
{0x05,0x05}, {0x06,0x14}, {0x07,0x07}, {0x08,0x38}, {0x09,0x39},
{0x0A,0x3A}, {0x0B,0x3B}, {0x0C,0x3C}, {0x0D,0x3D}, {0x0E,0x3E},
{0x0F,0x3F}, {0x10,0x01}, {0x11,0x00}, {0x12,0x0F}, {0x13,0x00},
{0x14,0x00},
{-1, 0}
};
static const CirrusLogicGD542XMode
CirrusLogicGD542X_1024x768x2x60hz = {
"1024x768x2x60hz",
CirrusLogicGD542X_1024x768x2x60hz_generalRegisters,
CirrusLogicGD542X_1024x768x2x60hz_sequencerRegisters,
CirrusLogicGD542X_1024x768x2x60hz_crtControllerRegisters,
CirrusLogicGD542X_1024x768x2x60hz_graphicsControllerRegisters,
CirrusLogicGD542X_1024x768x2x60hz_attributeControllerRegisters
};
/**************************************
* Framebuffer characteristics.
**************************************/
#define FRAMEBUFFER_ADDRESS ((void *) 0xa0000)
static const IODisplayInfo modeTable[] = {
{
//
// CirrusLogicGD542X 1024 x 768 x 2 x 60hz
//
1024, 768, 1024,
//
// rowbytes =
// #bytes/scanline =
// ((pixels/line) * (2 bits/pixel) * (byte/8 bits)) =
// (pixel width / 4)
//
256, 60, 0, IO_2BitsPerPixel, IO_OneIsBlackColorSpace,
"WW", 0, (void *)&CirrusLogicGD542X_1024x768x2x60hz
}
/* Add more modes here. */
};
#define modeTableCount (sizeof(modeTable) / sizeof(IODisplayInfo))
@implementation CirrusLogicGD542X
//
// BEGIN: Implementation of private routines for SVGA
//
static void SetBrightness(unsigned int level)
// Description: Sets the screen's brightness. This implementation
// uses a fixed gamma value. It sets the palette
// values according to the brightness level.
{
unsigned char val;
val = EV_SCALE_BRIGHTNESS(level, WHITE_PALETTE_VALUE);
outb(WRIT_COLR_PEL_AWMR, (unsigned char)WHITE_INDEX);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
val = EV_SCALE_BRIGHTNESS(level, LIGHT_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_AWMR, (unsigned char)LIGHT_GRAY_INDEX);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
val = EV_SCALE_BRIGHTNESS(level, DARK_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_AWMR, (unsigned char)DARK_GRAY_INDEX);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
val = EV_SCALE_BRIGHTNESS(level, BLACK_PALETTE_VALUE);
outb(WRIT_COLR_PEL_AWMR, (unsigned char)BLACK_INDEX);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
outb(WRIT_COLR_PEL_DATA, val);
}
static void setColorMapToLinearMonochrome()
// Description: Sets the color map to linear monochrome by zeroing
// out the entire table, then setting the first four
// palette values correctly.
{
int i;
for (i = 0; i < 256; i++) {
outb(WRIT_COLR_PEL_AWMR, i);
outb(WRIT_COLR_PEL_DATA, 0x00);
outb(WRIT_COLR_PEL_DATA, 0x00);
outb(WRIT_COLR_PEL_DATA, 0x00);
}
outb(WRIT_COLR_PEL_AWMR, WHITE_INDEX);
outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, WHITE_PALETTE_VALUE);
outb(WRIT_COLR_PEL_AWMR, LIGHT_GRAY_INDEX);
outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, LIGHT_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_AWMR, DARK_GRAY_INDEX);
outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, DARK_GRAY_PALETTE_VALUE);
outb(WRIT_COLR_PEL_AWMR, BLACK_INDEX);
outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE);
outb(WRIT_COLR_PEL_DATA, BLACK_PALETTE_VALUE);
}
- (void) _selectMode
// Description: During initialization, this selects the configured mode
// and sets the display info accordingly.
{
selectedMode = [self selectMode:modeTable count:modeTableCount valid:NULL];
if (selectedMode < 0) {
IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
selectedMode = 0;
}
*[self displayInfo] = modeTable[selectedMode];
}
- (void)_SVGASetGeneralRegistersForMode:
(const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
// Description: Set all the general registers for the given mode.
{
const SVGAIndexValuePair *regInfo;
regInfo = cirrusLogicGD542XMode->generalRegisters;
while (regInfo->index != -1) {
outb(WRIT_EIDR_GEN_MISC_OP, regInfo->value);
regInfo++;
}
}
- (void)_SVGASetSequencerRegistersForMode:
(const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
// Description: Set all the sequencer registers for the given mode.
{
const SVGAIndexValuePair *regInfo;
regInfo = cirrusLogicGD542XMode->sequencerRegisters;
while (regInfo->index != -1) {
IOWriteRegister(EIDR_SEQ_ADDR, (char)(regInfo->index), regInfo->value);
regInfo++;
}
}
- (void)_SVGASetCrtControllerRegistersForMode:
(const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
// Description: Set all the crt controller registers for the given mode.
{
const SVGAIndexValuePair *regInfo;
regInfo = cirrusLogicGD542XMode->crtControllerRegisters;
while (regInfo->index != -1) {
IOWriteRegister(COLR_CRT_ADDR, (char)(regInfo->index), regInfo->value);
regInfo++;
}
}
- (void)_SVGASetGraphicsControllerRegistersForMode:
(const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
// Description: Set all the graphics controller registers for the given mode.
{
const SVGAIndexValuePair *regInfo;
regInfo = cirrusLogicGD542XMode->graphicsControllerRegisters;
while (regInfo->index != -1) {
IOWriteRegister(EIDR_GCR_ADDR, (char)(regInfo->index), regInfo->value);
regInfo++;
}
}
- (void)_SVGASetAttributeControllerRegistersForMode:
(const CirrusLogicGD542XMode *)cirrusLogicGD542XMode
// Description: Set all the attribute controller registers for the given mode.
{
const SVGAIndexValuePair *regInfo;
regInfo = cirrusLogicGD542XMode->attributeControllerRegisters;
while (regInfo->index != -1) {
char tmpi;
inb(READ_COLR_GEN_IN_ST_1);
tmpi = inb(READ_TOGL_ACR_ADDR);
tmpi &= ~ACR_MSK;
tmpi |= (regInfo->index & ACR_MSK);
outb(WRIT_TOGL_ACR_ADDR, tmpi);
outb(WRIT_TOGL_ACR_DATA, regInfo->value);
regInfo++;
}
}
//
// END: Implementation of private routines for SVGA
//
//
// BEGIN: EXPORTED methods
//
- (void)setReadSegment: (unsigned char)segmentNum
// Description: Select which 64K segment we intend to read from.
{
outb(0x03ce,0x09);
outb(0x03cf,(segmentNum << 4));
}
- (void)setWriteSegment: (unsigned char)segmentNum
// Description: Select which 64K segment we intend to write to.
{
outb(0x03ce,0x09);
outb(0x03cf,(segmentNum << 4));
}
- (void)setReadPlane: (unsigned char)planeNum
// Description: Select which of 4 bit planes to read from in planar
// modes - only one plane can be active at a time.
{
char tmp;
/* Select plane we are reading from */
tmp = IOReadRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS);
tmp &= ~GCR_AT_RMS;
tmp |= (planeNum & GCR_AT_RMS);
IOWriteRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS, tmp);
}
- (void)setWritePlane: (unsigned char)planeNum
// Description: Select one of 4 bit planes to write to in planar modes.
// Although more than one plane can be active at a time,
// this routine only allows access to 1 plane at a time.
{
char tmp, plane = 0x01;
//
// Convert plane num to bit enable.
//
plane = plane << (planeNum & 0x03);
//
// Select plane we are writing to
//
tmp = IOReadRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK);
tmp &= ~(SEQ_AT_EM3 | SEQ_AT_EM2 | SEQ_AT_EM1 | SEQ_AT_EM0);
tmp |= plane;
IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK, tmp);
}
- (void)savePlaneAndSegmentSettings
// Description: Saves the current plane and segment settings.
// This is not a stack push, so we can only save/
// restore one group of settings at a time.
{
writePlaneMask = IOReadRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK);
readPlaneMask = IOReadRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS);
outb(0x3ce,0x09);
readSegment = inb(0x3cf);
writeSegment=readSegment=(readSegment >> 4);
}
- (void)restorePlaneAndSegmentSettings
// Description: Restores the current plane and segment settings.
// This is not a stack pop, so we can only save/
// restore one group of settings at a time.
{
IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_MPK, writePlaneMask);
IOWriteRegister(EIDR_GCR_ADDR, GCR_AT_READ_MAPS, readPlaneMask);
outb(0x3ce, 0x09);
outb(0x3cf, (readSegment << 4));
}
- (void)enterSVGAMode
// Description: Put the display into SVGA mode selectedMode. This
// typically happens when the window server starts running.
// We set up all the registers necessary for the given
// mode and then clear the screen.
{
IODisplayInfo *displayInfo;
int totalScreenBytes, bytesLeftToClear, writeSegmentToClear;
[self _SVGASetGeneralRegistersForMode:
modeTable[selectedMode].parameters];
[self _SVGASetSequencerRegistersForMode:
modeTable[selectedMode].parameters];
[self _SVGASetCrtControllerRegistersForMode:
modeTable[selectedMode].parameters];
[self _SVGASetGraphicsControllerRegistersForMode:
modeTable[selectedMode].parameters];
[self _SVGASetAttributeControllerRegistersForMode:
modeTable[selectedMode].parameters];
//
// re-enable timing sequencer
//
IOWriteRegister(EIDR_SEQ_ADDR, SEQ_AT_CRS, 0x00);
setColorMapToLinearMonochrome();
//
// Clear the screen.
//
displayInfo = [self displayInfo];
totalScreenBytes = displayInfo->rowBytes * displayInfo->height;
for ( bytesLeftToClear = totalScreenBytes, writeSegmentToClear = 0;
bytesLeftToClear > 0;
bytesLeftToClear -= 0x20000, writeSegmentToClear++) {
[self setWriteSegment:writeSegmentToClear];
memset(displayInfo->frameBuffer, 0, MIN(0x20000, bytesLeftToClear));
}
[self setWriteSegment:0];
}
- (void)revertToVGAMode
// Description: Put the display into VGA mode. This typically happens
// when SoftPC enters full-screen mode. We set up all the
// registers necessary for the given mode.
{
outb(WRIT_EIDR_GEN_MISC_OP, 0xE3);
}
- initFromDeviceDescription:deviceDescription
// Description: IODevice method. Initialize the current instance as
// per the deviceDescription. Most importantly, this
// includes selecting the mode and mapping the frame buffer.
{
IODisplayInfo *displayInfo;
const IORange *range;
const CirrusLogicGD542XMode *cirrusLogicGD542XMode;
if ([super initFromDeviceDescription:deviceDescription] == nil)
return [super free];
[self _selectMode];
range = [deviceDescription memoryRangeList];
if (range == 0) {
IOLog("%s: No memory range set.\n", [self name]);
return [super free];
}
videoRamAddress = range[0].start;
displayInfo = [self displayInfo];
cirrusLogicGD542XMode = displayInfo->parameters;
displayInfo->frameBuffer =
(void *)[self mapFrameBufferAtPhysicalAddress:videoRamAddress
length:0x20000]; //SCOTT--fix this
if (displayInfo->frameBuffer == 0)
return [super free];
IOLog("%s: Initialized `%s' @ %d Hz.\n", [self name],
cirrusLogicGD542XMode->name, displayInfo->refreshRate);
return self;
}
- setBrightness:(int)level token:(int)t
// Description: This is from the evScreen protocol. We override our superclass
// on this since it doesn't know how to set our brightness.
{
if ( level < EV_SCREEN_MIN_BRIGHTNESS
|| level > EV_SCREEN_MAX_BRIGHTNESS )
{
IOLog("%s: Invalid arg to setBrightness:%d\n",
[self name], level );
if (level < EV_SCREEN_MIN_BRIGHTNESS) {
level = EV_SCREEN_MIN_BRIGHTNESS;
} else {
level = EV_SCREEN_MAX_BRIGHTNESS;
}
}
SetBrightness(level);
return self;
}
//
// END: EXPORTED methods
//
@end