|
|
Sample Programs from NeXSTEP 3.3
/* Copyright (c) 1993 by NeXT Computer, Inc as an unpublished work.
* All rights reserved.
*
* QVisionSetMode.m -- Mode support for the QVision.
*
* NOTE: view this file with tabs set to 4 spaces
*
* Author: Derek B Clegg 21 May 1993
* Based on work by Joe Pasqua.
* Tue Aug 16 16:53:03 PDT 1994 James C. Lee
* Add 3.3 bus support & 8-bit color support.
* Thu Sep 22 16:39:18 PDT 1994 James C. Lee
* Use the new PCI API that returns IOReturn instead of BOOL.
*/
#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 <stdlib.h>
#import "QVision.h"
/* private interfaces for SetMode category of QVision */
/*@interface QVision (SetMode_Private)
- (ConfigBusType) determineConfigBusType;
- (QVAdapterType) determineVLCardType;
- (QVAdapterType) determinePCICardType;
- (QVAdapterType) determineEISACardType;
@end
*/
/* 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 card found.\n", [self name]);
return UnknownAdapter;
}
deviceDescription = [self deviceDescription];
[deviceDescription getPCIdevice:&devNum function:&funcNum bus:&busNum];
IOLog_dbg(("%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("%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;
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;
}
IOLog("%s: %s adapter; %s DAC.\n", [self name], adapterString, dacString);
}
- 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;
}
- selectMode
{
int k, mode;
const QVisionMode *qvMode;
BOOL validModes[QVisionModeTableCount];
for (k = 0; k < QVisionModeTableCount; k++) {
qvMode = QVisionModeTable[k].parameters;
validModes[k] = (qvMode->adapter <= adapter);
}
mode = [self selectMode:QVisionModeTable count:QVisionModeTableCount
valid:validModes];
if (mode < 0) {
IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
switch (adapter) {
case Orion12Adapter:
mode = DEFAULT_ORION12_MODE;
break;
case OrionAdapter:
mode = DEFAULT_ORION_MODE;
break;
case QVision1280P:
mode = DEFAULT_1280P_MODE;
break;
case QVisionAdapter:
default:
mode = DEFAULT_QVISION_MODE;
break;
}
}
*[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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.