home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OpenStep 4.2J (Developer)
/
os42jdev.iso
/
NextDeveloper
/
Examples
/
DriverKit
/
QVision
/
QVision_reloc.tproj
/
QVisionSetMode.m
< prev
next >
Wrap
Text File
|
1996-03-26
|
16KB
|
639 lines
/* Copyright (c) 1993-1996 by NeXT Software, Inc. as an unpublished work.
* All rights reserved.
*
* QVisionSetMode.m -- Mode support for the QVision.
*
* Author: Derek B Clegg 21 May 1993
* Based on work by Joe Pasqua.
* 16 Aug 1994 James C. Lee
* Add 3.3 bus support & 8-bit color support.
* 09 Oct 1995 Rakesh Dubey
* Added support for QV64P10.
*/
#import <string.h>
#import <driverkit/generalFuncs.h>
#import <driverkit/i386/ioPorts.h>
#import <driverkit/i386/directDevice.h>
#import <driverkit/i386/IOPCIDeviceDescription.h>
#import <driverkit/i386/IOPCIDirectDevice.h>
#import <string.h>
#import <stdio.h>
#import "QVision.h"
/* The `SetMode' category of `QVision'. */
@implementation QVision (SetMode)
- (ConfigBusType) determineConfigBusType
{
const char *busTypeName;
IOConfigTable *configTable;
configTable = [[self deviceDescription] configTable];
busTypeName = [configTable valueForStringKey:"Bus Type"];
if (strcmp(busTypeName, "PCI") == 0) {
busType = BusPCI;
} else if (strcmp(busTypeName, "EISA") == 0) {
busType = BusEISA;
} else {
/* default to ISA or VL */
busType = BusISAorVL;
}
return busType;
}
/* assume dac type is determined already. This method is called by
* determineConfiguration only */
- (QVAdapterType) determineVLCardType
{
QVAdapterType adapterType;
adapterType = UnknownAdapter;
switch (dac) {
case Bt484:
adapterType = OrionAdapter;
break;
case Bt485:
case Bt485A:
case ATT20C505:
adapterType = Orion12Adapter;
break;
default:
break;
}
return adapterType;
}
/* TODO: clean up error handling, i.e. return something meaningful rather
* than returning [super free]; */
- (QVAdapterType) determinePCICardType
{
unsigned int physicalAddress;
int numRanges;
IOPCIConfigSpace configSpace;
unsigned char devNum, funcNum, busNum;
unsigned long vendorDeviceID;
unsigned short vendorID, deviceID;
char idString[11];
id deviceDescription;
QVAdapterType adapterType;
IOConfigTable *configTable;
IORange *oldRange, newRange[3];
adapterType = UnknownAdapter;
if (![self isPCIPresent]) {
IOLog("%s: No PCI bus found.\n",[self name]);
return UnknownAdapter;
}
deviceDescription = [self deviceDescription];
[deviceDescription getPCIdevice:&devNum function:&funcNum bus:&busNum];
IOLog("%s: PCI Dev: %d Func: %d Bus: %d\n", [self name], devNum,
funcNum, busNum);
[self getPCIConfigData:&vendorDeviceID atRegister:0x00];
vendorID = (unsigned short)vendorDeviceID;
deviceID = (unsigned short)(vendorDeviceID >> 16);
IOLog_dbg(("%s: vendorID=%04x deviceID=%04x\n",[self name], vendorID,
deviceID));
/* go through "Auto Detect IDs" and make sure we are okay */
configTable = [[self deviceDescription] configTable];
sprintf(idString, "%08lx", vendorDeviceID);
if (strstr([configTable valueForStringKey:"Auto Detect IDs"], idString)
== NULL) {
IOLog("%s: VenderDeviceID %08lx not found in instance table.\n",
[self name], vendorDeviceID);
return UnknownAdapter;
} else {
/*
* add more card types here if there are PCI cards other than 1280P
* actually, if there are more than one PCI cards, we should
* determine which PCI card here
*/
adapterType = QVision1280P;
}
/* need to do set framebuffer address for PCI */
[self getPCIConfigSpace:&configSpace];
physicalAddress = configSpace.BaseAddress[0];
physicalAddress &= 0xfffffff0; /* mask out lower 4 bits */
if (physicalAddress) {
IOLog_dbg(("%s: try to set physical address to 0x%08x\n",
[self name], physicalAddress));
/* PCI does report where the frame buffer address is */
oldRange = [deviceDescription memoryRangeList];
numRanges = [deviceDescription numMemoryRanges];
if (numRanges == 3) {
int ret;
int i;
/* replace the address */
for (i = 0; i < numRanges; i++) {
newRange[i] = oldRange[i];
}
newRange[0].start = physicalAddress;
ret = [deviceDescription setMemoryRangeList:newRange num:3];
if (ret) {
/* can't set to new memory range */
IOLog("%s: Can't set memory range, using default.\n",
[self name]);
for (i = 0; i < numRanges; i++) {
newRange[i] = oldRange[i];
}
physicalAddress = newRange[0].start;
ret = [deviceDescription setMemoryRangeList:newRange
num:3];
if (ret) {
/* can't set to old range-->major problem! */
IOLog("%s: Can't set to default range either!\n",
[self name]);
return UnknownAdapter;
}
}
} else {
IOLog("%s: Incorrect number of address ranges: %d.\n",
[self name], numRanges);
return UnknownAdapter;
}
} else {
IOLog_dbg(("%s: PCI doesn't tell us the physical address.\n",
[self name]));
physicalAddress = [deviceDescription memoryRangeList]->start;
configSpace.BaseAddress[0] = physicalAddress;
[self setPCIConfigSpace:&configSpace];
}
return adapterType;
}
/* helper method to -determineEISACardType */
- (QVAdapterType)adapterTypeFromEISAID:(unsigned int)cardID
{
QVAdapterType adapterType;
adapterType = UnknownAdapter;
IOLog_dbg(("%s: adapterTypeFromEISAID cardID=0x%08x\n",[self name],
cardID));
switch (cardID) {
case QVISION_EISA_ID:
adapterType = QVisionAdapter;
break;
case ORION_EISA_ID:
adapterType = OrionAdapter;
break;
case ORION12_EISA_ID:
adapterType = Orion12Adapter;
break;
case QVISION_ISA_ID:
case ORION_ISA_ID:
case ORION12_ISA_ID:
IOLog("%s: Sorry, ISA cards are not supported (id=0x%08x).\n",
[self name], cardID);
break;
default:
/* We found some other EISA card. Just ignore it. */
break;
}
return adapterType;
}
/* helper method to -determineEISACardType */
- (QVAdapterType)autoScanEISAForCardType
{
int slot;
QVAdapterType adapterType;
unsigned int cardID;
IOLog_dbg(("%s: doing auto-scan on EISA bus.\n",[self name]));
adapterType = UnknownAdapter;
for (slot = 1; slot < 16; slot++) {
if ([self getEISAId:&cardID forSlot:slot]) {
adapterType = [self adapterTypeFromEISAID:cardID];
}
if (adapterType != UnknownAdapter) {
IOLog_dbg(("%s: found card in slot %d.\n",[self name], slot));
return adapterType;
}
}
return UnknownAdapter;
}
/* can't use atoi() nor sscanf() */
- (int) getFirstNumber:(char *)s
{
char *cptr;
int n;
cptr = s;
n = -1;
while (*cptr && ((*cptr < '0') || (*cptr > '9')))
cptr++;
while (*cptr && ((*cptr >= '0') && (*cptr <= '9'))) {
if (n == -1)
n = 0;
n = n * 10 + (*cptr - '0');
cptr++;
}
return n;
}
/* TODO: clean up error handling, i.e. return something meaningful rather
* than returning [super free]; */
- (QVAdapterType) determineEISACardType
{
QVAdapterType adapterType;
int mySlot;
id deviceDescription;
const char *slotValue;
IOConfigTable *configTable;
unsigned int cardID;
adapterType = UnknownAdapter;
if (![self isEISAPresent]) {
IOLog("%s: Not an EISA system.\n",[self name]);
return UnknownAdapter;
}
deviceDescription = [self deviceDescription];
configTable = [[self deviceDescription] configTable];
/* see what slot we're supposed be in */
slotValue = [configTable valueForStringKey:"Location"];
if (strstr(slotValue, "Slot")) {
mySlot = [self getFirstNumber:(char *)slotValue];
IOLog_dbg(("%s: we should be in slot %d\n",[self name], mySlot));
} else {
/* instance table doesn't tell us what slot we're in */
return [self autoScanEISAForCardType];
}
/* TODO: need to check for auto detect id's */
if (mySlot > 0) {
if ([self getEISAId:&cardID forSlot:mySlot]) {
adapterType = [self adapterTypeFromEISAID:cardID];
} else {
/* can't find card in the specified slot, do auto-scan */
adapterType = [self autoScanEISAForCardType];
}
} else {
/* slot not specified, do auto-scan */
adapterType = [self autoScanEISAForCardType];
}
return adapterType;
}
- (void)reportConfiguration
{
const char *adapterString, *dacString;
unsigned int biosCapability, memoryPresent;
const char *capString, *memString;
switch (adapter) {
case QVisionAdapter:
adapterString = "QVision";
break;
case OrionAdapter:
adapterString = "Orion";
break;
case Orion12Adapter:
adapterString = "Orion12";
break;
case QVision1280P:
adapterString = "QVision1280P";
break;
default:
adapterString = "Unknown";
break;
}
switch (dac) {
case Bt484:
dacString = "Brooktree 484";
break;
case Bt485:
dacString = "Brooktree 485";
break;
case Bt485A:
dacString = "Brooktree 485A";
break;
case ATT20C505:
dacString = "AT&T 20C505";
break;
default:
dacString = "Unknown";
break;
}
/* Unlock */
outb(VGA_GRFX_INDEX, 0x0F);
outb(VGA_GRFX_DATA, 0x05);
outb(VGA_GRFX_INDEX, 0x56);
biosCapability = inb(VGA_GRFX_DATA);
outb(VGA_GRFX_INDEX, 0x57);
biosCapability |= (inb(VGA_GRFX_DATA) << 8);
/* TITAN == Bt484, TITAN-1280 == Bt484, GIANT == Bt485 (64-bit) */
switch (biosCapability) {
case 0x2F3A:
case 0x2FBA:
capString = "QV64P10/GIANT";
break;
case 0x2F36:
case 0x2FB6:
capString = "QV64P10/TITAN-1280";
break;
case 0x2F32:
case 0x2FB2:
capString = "QV64P10/TITAN";
break;
case 0x0936:
capString = "QV35P04/TITAN-1280";
break;
case 0x0932:
capString = "QV35P04/TITAN";
break;
default:
capString = "Unknown";
break;
}
/* Now find amount of installed memory */
outb(VGA_GRFX_INDEX, 0x54);
memoryPresent = inb(VGA_GRFX_DATA);
installedVRAMBytes = (memoryPresent * 1024 * 1024)/4;
switch (memoryPresent) {
case 0x02:
memString = "0.5MB";
break;
case 0x04:
memString = "1MB";
break;
case 0x08:
memString = "2MB";
break;
case 0x10:
memString = "4MB";
break;
default:
memString = "Unknown";
break;
}
IOLog("%s: %s: %s/%s/%s\n", [self name], adapterString, capString, dacString, memString);
/* Relock */
outb(VGA_GRFX_INDEX, 0x0F);
outb(VGA_GRFX_DATA, 0x0);
}
- determineConfiguration
{
adapter = UnknownAdapter;
[self determineConfigBusType];
[self determineDACType];
switch (busType) {
case BusISAorVL:
adapter = [self determineVLCardType];
break;
case BusPCI:
adapter = [self determinePCICardType];
break;
case BusEISA:
adapter = [self determineEISACardType];
break;
}
[self reportConfiguration];
if (adapter == UnknownAdapter || dac == UnknownDAC)
return nil;
return self;
}
/*
* Initialize all fields in the QVision mode table.
*/
- (void)initModeList
{
int i, n;
QVisionMode *qvMode;
unsigned int memoryNeeded;
for (i = 0; i < QVisionModeTableCount; i++) {
QVisionModeTable[i].flags = IO_DISPLAY_HAS_TRANSFER_TABLE;
QVisionModeTable[i].modeUnavailableFlag = IO_DISPLAY_MODE_VALID;
}
for (i = 0; i < QVisionModeTableCount; i++) {
memoryNeeded = QVisionModeTable[i].rowBytes *
QVisionModeTable[i].height;
if (installedVRAMBytes < memoryNeeded)
QVisionModeTable[i].modeUnavailableFlag |=
IO_DISPLAY_MODE_NEEDS_MORE_MEMORY;
}
for (i = 0; i < QVisionModeTableCount; i++) {
memoryNeeded = QVisionModeTable[i].rowBytes *
QVisionModeTable[i].height;
for (n = 1024; n < memoryNeeded; n *= 2)
;
QVisionModeTable[i].memorySize = n;
}
for (i = 0; i < QVisionModeTableCount; i++) {
qvMode = QVisionModeTable[i].parameters;
if (qvMode->adapter > adapter)
QVisionModeTable[i].modeUnavailableFlag |=
IO_DISPLAY_MODE_WRONG_VERSION;
}
/*
* Add code here that fills in other fields as well.
*/
}
- selectMode
{
int mode;
mode = [self selectMode:QVisionModeTable count:QVisionModeTableCount
valid:0];
if (mode < 0) {
mode = DEFAULT_QVISION_MODE;
}
*[self displayInfo] = QVisionModeTable[mode];
return self;
}
- initializeMode
{
unsigned int i;
const QVisionMode *mode;
const IODisplayInfo *displayInfo;
displayInfo = [self displayInfo];
mode = displayInfo->parameters;
/* Turn off video while setting all of the registers. */
inb(VGA_INPUT_STATUS_1);
outb(VGA_ATTR_INDEX, 0x00);
/* Set the sequencer registers. */
for (i = 0; i < VGA_SEQ_COUNT; i++) {
outb(VGA_SEQ_INDEX, i);
outb(VGA_SEQ_DATA, mode->vgaData.seqx[i]);
}
outb(VGA_SEQ_INDEX, 0x00);
outb(VGA_SEQ_DATA, 0x03); /* Restart the sequencer. */
/* Unlock extended graphics registers. */
outw(VGA_GRFX_INDEX, 0x050f);
/* Unlock more extended registers. */
outb(VGA_GRFX_INDEX, 0x10);
outb(VGA_GRFX_DATA, 0x08);
/* Set Advanced VGA mode (set bit 0 of Ctrl Reg 0). */
outb(VGA_GRFX_INDEX, 0x40);
outb(VGA_GRFX_DATA, 0x01);
/* Fix sequencer pixel mask for 8 bits. */
outb(VGA_SEQ_INDEX, SEQ_PIXEL_WR_MSK);
outb(VGA_SEQ_DATA, 0xff);
outb(CTRL_REG_1, mode->ctrlReg1);
if (mode->adapter >= OrionAdapter) {
/* Set access level & enable high address map. */
outb(QVGA_CTL_2, 0x14);
/* Select 2 Meg mode. */
outb(QVGA_CTL_3, 0x05);
}
/* Set miscellaneous output register. */
outb(VGA_MISC_OUTPUT, mode->vgaData.miscOutput);
[self programDAC];
/* Load CRTC registers. */
outb(VGA_CRTC_INDEX, 0x11); /* Unlock CRTC regs 0-7. */
outb(VGA_CRTC_DATA, 0x00);
for (i = 0; i < VGA_CRTC_COUNT; i++) {
outb(VGA_CRTC_INDEX, i);
outb(VGA_CRTC_DATA, mode->vgaData.crtc[i]);
}
/* Load overflow registers. */
outb(VGA_GRFX_INDEX, 0x42);
outb(VGA_GRFX_DATA, mode->overflow1);
outb(VGA_GRFX_INDEX, 0x51);
outb(VGA_GRFX_DATA, mode->overflow2);
/* Load attribute registers. */
inb(VGA_INPUT_STATUS_1); /* Reset latch. */
for (i = 0; i < VGA_ATTR_COUNT; i++) {
outb(VGA_ATTR_INDEX, i);
outb(VGA_ATTR_DATA, mode->vgaData.attr[i]);
}
/* Load graphics registers. */
for (i = 0; i < VGA_GRFX_COUNT; i++) {
outb(VGA_GRFX_INDEX, i);
outb(VGA_GRFX_DATA, mode->vgaData.grfx[i]);
}
[self setGammaTable];
/* Re-enable video display. */
inb(VGA_INPUT_STATUS_1);
outb(VGA_ATTR_INDEX, 0x20);
return self;
}
- enableLinearFrameBuffer
{
const IODisplayInfo *displayInfo;
unsigned char tmp;
/*
* Override the high address map disable, thus allowing access to the
* high address map of the current board, even when the board is
* disabled.
*/
outb(VGA_GRFX_INDEX, HI_ADDR_MAP + 1);
tmp = inb(VGA_GRFX_DATA);
outb(VGA_GRFX_DATA, tmp | 0x80);
/* Map VRAM. Tell the adapter where to decode the framebuffer. */
/* Set low 8 bits */
outb(VGA_GRFX_INDEX, HI_ADDR_MAP);
outb(VGA_GRFX_DATA, (videoRamAddress >> 20) & 0xFF);
/* Set upper 4 bits */
outb(VGA_GRFX_INDEX, HI_ADDR_MAP + 1);
outb(VGA_GRFX_DATA, (videoRamAddress >> 28) & 0x0F);
/* Leave them with a nice clear screen. */
displayInfo = [self displayInfo];
memset(displayInfo->frameBuffer, 0,
displayInfo->rowBytes * displayInfo->height);
return self;
}
- resetVGA
{
const IODisplayInfo *displayInfo;
const QVisionMode *mode;
displayInfo = [self displayInfo];
mode = displayInfo->parameters;
/* Clear the QVision extended mode bit. This is bit 0 of CTRL_REG_1. */
outb(CTRL_REG_1, inb(CTRL_REG_1) & 0xFE);
if (mode != 0 && mode->adapter >= OrionAdapter) {
/* Select 1 meg mode. */
outb(QVGA_CTL_3, 0x00);
/* Reset access level & disable high address map. */
outb(QVGA_CTL_2, 0x00);
}
/* Clear the extended 256 color bit. This is bit 0 of 3CF.40. */
outb(VGA_GRFX_INDEX, 0x40);
outb(VGA_GRFX_DATA, (inb(VGA_GRFX_DATA) & 0xFE));
/* Clear the page registers - 3CF.45 and 3CF.46. */
outb(VGA_GRFX_INDEX, PAGE_REG_0);
outb(VGA_GRFX_DATA, 0x00);
outb(VGA_GRFX_INDEX, PAGE_REG_1);
outb(VGA_GRFX_DATA, 0x00);
[self resetDAC];
/* Clear the overflow registers. */
outb(VGA_GRFX_INDEX, 0x42);
outb(VGA_GRFX_DATA, 0x00);
outb(VGA_GRFX_INDEX, 0x51);
outb(VGA_GRFX_DATA, 0x00);
VGASetMode(0x03);
return self;
}
@end