|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
modeset.c
Abstract:
This is the modeset code for the et4000 miniport driver.
Environment:
kernel mode only
Notes:
Revision History:
--*/ #include "dderror.h"
#include "devioctl.h"
#include "miniport.h"
#include "ntddvdeo.h"
#include "video.h"
#include "et4000.h"
#include "cmdcnst.h"
VP_STATUS VgaInterpretCmdStream( PHW_DEVICE_EXTENSION HwDeviceExtension, PUSHORT pusCmdStream );
VP_STATUS VgaSetMode( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE Mode, ULONG ModeSize );
VP_STATUS VgaQueryAvailableModes( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE_INFORMATION ModeInformation, ULONG ModeInformationSize, PULONG OutputSize );
VP_STATUS VgaQueryNumberOfAvailableModes( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_NUM_MODES NumModes, ULONG NumModesSize, PULONG OutputSize );
VP_STATUS VgaQueryCurrentMode( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE_INFORMATION ModeInformation, ULONG ModeInformationSize, PULONG OutputSize );
VOID VgaZeroVideoMemory( PHW_DEVICE_EXTENSION HwDeviceExtension );
VOID VgaValidateModes( PHW_DEVICE_EXTENSION HwDeviceExtension );
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE,VgaInterpretCmdStream)
#pragma alloc_text(PAGE,VgaSetMode)
#pragma alloc_text(PAGE,VgaQueryAvailableModes)
#pragma alloc_text(PAGE,VgaQueryNumberOfAvailableModes)
#pragma alloc_text(PAGE,VgaQueryCurrentMode)
#pragma alloc_text(PAGE,VgaZeroVideoMemory)
#pragma alloc_text(PAGE,VgaValidateModes)
#endif
VP_STATUS VgaInterpretCmdStream( PHW_DEVICE_EXTENSION HwDeviceExtension, PUSHORT pusCmdStream )
/*++
Routine Description:
Interprets the appropriate command array to set up VGA registers for the requested mode. Typically used to set the VGA into a particular mode by programming all of the registers
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
pusCmdStream - array of commands to be interpreted.
Return Value:
The status of the operation (can only fail on a bad command); TRUE for success, FALSE for failure.
--*/
{ ULONG ulCmd; ULONG ulPort; UCHAR jValue; USHORT usValue; ULONG culCount; ULONG ulIndex; ULONG ulBase;
if (pusCmdStream == NULL) {
VideoDebugPrint((1, "VgaInterpretCmdStream - Invalid pusCmdStream\n")); return TRUE; }
ulBase = (ULONG)HwDeviceExtension->IOAddress;
//
// Now set the adapter to the desired mode.
//
while ((ulCmd = *pusCmdStream++) != EOD) {
//
// Determine major command type
//
switch (ulCmd & 0xF0) {
//
// Basic input/output command
//
case INOUT:
//
// Determine type of inout instruction
//
if (!(ulCmd & IO)) {
//
// Out instruction. Single or multiple outs?
//
if (!(ulCmd & MULTI)) {
//
// Single out. Byte or word out?
//
if (!(ulCmd & BW)) {
//
// Single byte out
//
ulPort = *pusCmdStream++; jValue = (UCHAR) *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)(ulBase+ulPort), jValue);
} else {
//
// Single word out
//
ulPort = *pusCmdStream++; usValue = *pusCmdStream++; VideoPortWritePortUshort((PUSHORT)(ulBase+ulPort), usValue);
}
} else {
//
// Output a string of values
// Byte or word outs?
//
if (!(ulCmd & BW)) {
//
// String byte outs. Do in a loop; can't use
// VideoPortWritePortBufferUchar because the data
// is in USHORT form
//
ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++;
while (culCount--) { jValue = (UCHAR) *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)ulPort, jValue);
}
} else {
//
// String word outs
//
ulPort = *pusCmdStream++; culCount = *pusCmdStream++; VideoPortWritePortBufferUshort((PUSHORT) (ulBase + ulPort), pusCmdStream, culCount); pusCmdStream += culCount;
} }
} else {
// In instruction
//
// Currently, string in instructions aren't supported; all
// in instructions are handled as single-byte ins
//
// Byte or word in?
//
if (!(ulCmd & BW)) { //
// Single byte in
//
ulPort = *pusCmdStream++; jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort);
} else {
//
// Single word in
//
ulPort = *pusCmdStream++; usValue = VideoPortReadPortUshort((PUSHORT) (ulBase+ulPort));
}
}
break;
//
// Higher-level input/output commands
//
case METAOUT:
//
// Determine type of metaout command, based on minor
// command field
//
switch (ulCmd & 0x0F) {
//
// Indexed outs
//
case INDXOUT:
ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; ulIndex = *pusCmdStream++;
while (culCount--) {
usValue = (USHORT) (ulIndex + (((ULONG)(*pusCmdStream++)) << 8)); VideoPortWritePortUshort((PUSHORT)ulPort, usValue);
ulIndex++;
}
break;
//
// Masked out (read, AND, XOR, write)
//
case MASKOUT:
ulPort = *pusCmdStream++; jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort); jValue &= *pusCmdStream++; jValue ^= *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)ulBase + ulPort, jValue); break;
//
// Attribute Controller out
//
case ATCOUT:
ulPort = ulBase + *pusCmdStream++; culCount = *pusCmdStream++; ulIndex = *pusCmdStream++;
while (culCount--) {
// Write Attribute Controller index
VideoPortWritePortUchar((PUCHAR)ulPort, (UCHAR)ulIndex);
// Write Attribute Controller data
jValue = (UCHAR) *pusCmdStream++; VideoPortWritePortUchar((PUCHAR)ulPort, jValue);
ulIndex++;
}
break;
//
// None of the above; error
//
default:
return FALSE;
}
break;
//
// NOP
//
case NCMD:
break;
//
// Unknown command; error
//
default:
return FALSE;
}
}
return TRUE;
} // end VgaInterpretCmdStream()
VP_STATUS VgaSetMode( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE Mode, ULONG ModeSize )
/*++
Routine Description:
This routine sets the vga into the requested mode.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Mode - Pointer to the structure containing the information about the font to be set.
ModeSize - Length of the input buffer supplied by the user.
Return Value:
ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough for the input data.
ERROR_INVALID_PARAMETER if the mode number is invalid.
NO_ERROR if the operation completed successfully.
--*/
{
PVIDEOMODE pRequestedMode; VP_STATUS status; USHORT usDataSet, usTemp, usDataClr; PUSHORT pBios = NULL; VIDEO_X86_BIOS_ARGUMENTS biosArguments;
VideoDebugPrint((1, "VgaSetMode - entry\n"));
//
// Check if the size of the data in the input buffer is large enough.
//
if (ModeSize < sizeof(VIDEO_MODE)) {
VideoDebugPrint((1, "VgaSetMode - ERROR_INSUFFICIENT_BUFFER\n")); return ERROR_INSUFFICIENT_BUFFER;
}
//
// Extract the map linear bits.
//
HwDeviceExtension->bInLinearMode = FALSE;
if (Mode->RequestedMode & VIDEO_MODE_MAP_MEM_LINEAR) { if (!HwDeviceExtension->bLinearModeSupported) { return ERROR_INVALID_PARAMETER; } else { HwDeviceExtension->bInLinearMode = TRUE; Mode->RequestedMode &= ~VIDEO_MODE_MAP_MEM_LINEAR; } }
//
// Extract the clear memory bit.
//
if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY) {
Mode->RequestedMode &= ~VIDEO_MODE_NO_ZERO_MEMORY;
} else {
VgaZeroVideoMemory(HwDeviceExtension);
}
//
// Check to see if we are requesting a valid mode
//
if ( (Mode->RequestedMode >= NumVideoModes) || (!ModesVGA[Mode->RequestedMode].ValidMode) ) {
VideoDebugPrint((1, "VgaSetMode - ERROR_INVALID_PARAMETER\n")); return ERROR_INVALID_PARAMETER;
}
pRequestedMode = &ModesVGA[Mode->RequestedMode];
//
// If the chip is a W32 and it's not a planar color so we're using the
// accelerated W32 driver. We don't want stretched scans for that driver,
// so... No stretched scans!
//
if ((HwDeviceExtension->ulChipID >= W32) && (pRequestedMode->bitsPerPlane != 1)) {
pRequestedMode->wbytes = (pRequestedMode->hres * pRequestedMode->bitsPerPlane * pRequestedMode->numPlanes) >> 3;
pRequestedMode->CmdStrings = NULL;
}
//
// Set the vertical refresh frequency
//
//
// This code is used to determine if the BIOS call to set frequencies
// is available. If you can, then after the BIOS call AL=12.
// See page 233 of the W32p data book for details.
//
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = 0x1200; biosArguments.Ebx = 0xf1; biosArguments.Ecx = 0x0; status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR) {
VideoDebugPrint((1, "VgaSetMode - VideoPortInt10 failed (%d)\n", __LINE__)); return status;
}
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = 0x1200; biosArguments.Ebx = 0xf1; biosArguments.Ecx = 0x1; status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR) {
VideoDebugPrint((1, "VgaSetMode - VideoPortInt10 failed (%d)\n", __LINE__)); return status;
}
VideoDebugPrint((1, "VgaSetMode - BIOS returned %x in AL\n", (biosArguments.Eax & 0xff)));
if ((biosArguments.Eax & 0xff) == 0x12) {
VideoDebugPrint((1, "VgaSetMode - using BIOS to set refresh rate\n"));
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = 0x1200;
switch (pRequestedMode->hres) {
case 320: case 512: case 640:
biosArguments.Ebx = 0xf1;
if (pRequestedMode->Frequency == 60) biosArguments.Ecx = 0x0; else if (pRequestedMode->Frequency == 72) biosArguments.Ecx = 0x1; else if (pRequestedMode->Frequency == 75) biosArguments.Ecx = 0x2; else if (pRequestedMode->Frequency == 85) biosArguments.Ecx = 0x3; else if (pRequestedMode->Frequency == 90) biosArguments.Ecx = 0x4; break;
case 800:
biosArguments.Ebx = 0x1f1;
if (pRequestedMode->Frequency == 56) biosArguments.Ecx = 0x0; else if (pRequestedMode->Frequency == 60) biosArguments.Ecx = 0x1; else if (pRequestedMode->Frequency == 72) biosArguments.Ecx = 0x2; else if (pRequestedMode->Frequency == 75) biosArguments.Ecx = 0x3; else if (pRequestedMode->Frequency == 85) biosArguments.Ecx = 0x4; else if (pRequestedMode->Frequency == 90) biosArguments.Ecx = 0x5; break;
case 1024:
biosArguments.Ebx = 0x2f1;
if (pRequestedMode->Frequency == 45) biosArguments.Ecx = 0x0; else if (pRequestedMode->Frequency == 60) biosArguments.Ecx = 0x1; else if (pRequestedMode->Frequency == 70) biosArguments.Ecx = 0x2;
// For some BIOS 3 will give us 72 Hz, and
// on others, 3 will give us 75
else if (pRequestedMode->Frequency == 72) biosArguments.Ecx = 0x3; else if (pRequestedMode->Frequency == 75) biosArguments.Ecx = 0x3; break;
case 1280:
biosArguments.Ebx = 0x3f1;
if (pRequestedMode->Frequency == 45) biosArguments.Ecx = 0x0; else if (pRequestedMode->Frequency == 60) biosArguments.Ecx = 0x1; else if (pRequestedMode->Frequency == 70) biosArguments.Ecx = 0x2;
// For some BIOS 3 will give us 72 Hz, and
// on others, 3 will give us 75
else if (pRequestedMode->Frequency == 72) biosArguments.Ecx = 0x3; else if (pRequestedMode->Frequency == 75) biosArguments.Ecx = 0x3; break;
default:
biosArguments.Ebx = 0xf1; biosArguments.Ecx = 0x0; break; }
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR) {
VideoDebugPrint((1, "VgaSetMode - VideoPortInt10 failed (%d)\n", __LINE__));
}
VideoDebugPrint((1, "VgaSetMode - BIOS returned %x in CL\n", (biosArguments.Ecx & 0xff))); }
else if (HwDeviceExtension->BoardID == STEALTH32) {
usTemp = 0xffff; // flag value, this is reserved
switch (pRequestedMode->hres) {
case 640:
if (pRequestedMode->Frequency == 90) {
usTemp = 4;
} else if (pRequestedMode->Frequency == 75) {
usTemp = 2;
} else if (pRequestedMode->Frequency == 72) {
usTemp = 0;
} else if (pRequestedMode->Frequency == 60) {
usTemp = 8;
}
break;
case 800:
if (pRequestedMode->Frequency == 90) {
usTemp = 4;
} else if (pRequestedMode->Frequency == 75) {
usTemp = 2;
} else if (pRequestedMode->Frequency == 72) {
usTemp = 1;
} else if (pRequestedMode->Frequency == 60) {
usTemp = 0;
} else if (pRequestedMode->Frequency == 56) {
usTemp = 8;
}
break;
case 1024:
if (pRequestedMode->Frequency == 75) {
usTemp = 2;
} else if (pRequestedMode->Frequency == 72) {
usTemp = 4;
} else if (pRequestedMode->Frequency == 70) {
usTemp = 3;
} else if (pRequestedMode->Frequency == 60) {
usTemp = 5;
} else if (pRequestedMode->Frequency == 43) {
usTemp = 0;
}
break;
case 1280:
if (pRequestedMode->Frequency == 75) {
usTemp = 2;
} else if (pRequestedMode->Frequency == 72) {
usTemp = 4;
} else if (pRequestedMode->Frequency == 60) {
usTemp = 5;
} else if (pRequestedMode->Frequency == 43) {
usTemp = 6;
}
break;
default:
//
// !!! Reset for DOS modes?
//
// usDataSet = HwDeviceExtension->OriginalBiosData;
break;
}
if (usTemp != 0xffff) { USHORT usOldBits;
UnlockET4000ExtendedRegs(HwDeviceExtension);
//
// select CRTC.31 and write usTemp to bits 3-0
//
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR, 0x31);
usOldBits = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR);
usTemp = ((usTemp & 0x0f) | (usOldBits & 0xf0));
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR, (UCHAR)usTemp);
LockET4000ExtendedRegs(HwDeviceExtension); }
} // HwDeviceExtension->BoardID == STEALTH32
#if defined(i386)
//
// Ok, we'll try to stuff the right values in to the bios data
// area so that the int10 modeset sets the freq for us.
//
else {
//
// NOTE :
//
// We assume an int10 was made as some point before we reach this code.
// This ensures the BiosData got initialized properly.
//
//
// Get the BiosData area value and save the original value.
//
if (!HwDeviceExtension->BiosArea) {
switch (HwDeviceExtension->BoardID) {
case PRODESIGNERIISEISA:
//
// Initialize this to something.
// It is not used however, since we always use hardware defaults
// for this card.
//
HwDeviceExtension->BiosArea = (PUSHORT)PRODESIGNER_BIOS_INFO;
break;
case PRODESIGNER2: case PRODESIGNERIIS:
HwDeviceExtension->BiosArea = (PUSHORT)PRODESIGNER_BIOS_INFO; HwDeviceExtension->OriginalBiosData = VideoPortReadRegisterUshort(HwDeviceExtension->BiosArea);
break;
case SPEEDSTAR: case SPEEDSTARPLUS: case SPEEDSTAR24: case OTHER: default:
HwDeviceExtension->BiosArea = (PUSHORT)BIOS_INFO_1; HwDeviceExtension->OriginalBiosData = VideoPortReadRegisterUshort(HwDeviceExtension->BiosArea);
break; } }
pBios = HwDeviceExtension->BiosArea;
//
// Set the refresh rates for the various boards
//
switch(HwDeviceExtension->BoardID) {
case SPEEDSTAR: case SPEEDSTARPLUS: case SPEEDSTAR24:
switch (pRequestedMode->hres) {
case 640: if (pRequestedMode->Frequency == 72) usDataSet = 2; else usDataSet = 1; break;
case 800: if (pRequestedMode->Frequency == 72) usDataSet = 2; else if (pRequestedMode->Frequency == 56) usDataSet = 1; else usDataSet = 3; break;
case 1024: if (pRequestedMode->Frequency == 70) usDataSet = 4; else if (pRequestedMode->Frequency == 45) usDataSet = 1; else usDataSet = 2; break;
default: usDataSet = 1; break;
}
//
// now we got to unlock the CRTC extension registers!?!
//
UnlockET4000ExtendedRegs(HwDeviceExtension);
if (HwDeviceExtension->BoardID == SPEEDSTAR24) {
//
// SpeedSTAR 24 uses 31.0 for LSB select CRTC.31 and read it
//
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR, 0x31);
usTemp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR) & ~0x01;
//
// CRTC.31 bit 0 is the LSB of the monitor type on SpeedSTAR 24
//
usTemp |= (usDataSet&1); VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR, (UCHAR)usTemp);
} else { // SpeedSTAR and SpeedSTAR Plus use 37.4 for LSB
//
// select CRTC.37 and read it
//
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR, 0x37);
usTemp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR) & ~0x10;
//
// CRTC.37 bit 4 is the LSB of the monitor type on SpeedSTAR PLUS
//
usTemp |= (usDataSet&1)<<4; VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR, (UCHAR)usTemp); }
LockET4000ExtendedRegs(HwDeviceExtension);
//
// these two bits are the rest of the monitor type...
//
usTemp = VideoPortReadRegisterUshort(pBios) & ~0x6000; usTemp |= (usDataSet&6)<<12; usTemp |= VideoPortReadRegisterUshort(pBios); VideoPortWriteRegisterUshort(pBios,usTemp);
break;
//
// Do nothing for the EISA machine - use the default in the EISA config.
//
case PRODESIGNERIISEISA:
break;
//
// The old prodesigner 2 is not able toset refresh rates
//
case PRODESIGNER2:
break;
case PRODESIGNERIIS:
switch (pRequestedMode->hres) {
case 640:
//
// Bit 0: 1=72Hz 0=60Hz
//
if (pRequestedMode->Frequency == 72) {
usDataSet = 0x0001;
} else { // 60 Hz
usDataSet = 0x0000;
}
break;
case 800:
//
// Bit 1-2: 10=72Hz 01=60Hz 00=56Hz
//
if (pRequestedMode->Frequency == 72) {
usDataSet = 0x0004;
} else {
if (pRequestedMode->Frequency == 56) {
usDataSet = 0x0000;
} else { // 60 Hz
usDataSet = 0x0002;
} }
break;
case 1024:
//
// Bit 3-4: 10=70Hz 01=60Hz 00=45Hz
//
if (pRequestedMode->Frequency == 70) {
usDataSet = 0x0010;
} else {
if (pRequestedMode->Frequency == 45) {
usDataSet = 0x0000;
} else { // 60 Hz
usDataSet = 0x0008;
} }
break;
// case 1280
//
// Bit 5 1=45Hz 0=43 Hz
//
default:
//
// Reset for DOS modes
//
usDataSet = HwDeviceExtension->OriginalBiosData;
break;
}
VideoPortWriteRegisterUshort(pBios,usDataSet);
break;
case OTHER: default:
{
VideoDebugPrint((2, "### VgaSetMode - hres(%d) freq(%d)\n", pRequestedMode->hres, pRequestedMode->Frequency ));
VideoDebugPrint((2, "### VgaSetMode - NOT using BIOS to set refresh rate\n"));
switch (pRequestedMode->hres) {
case 640:
if (pRequestedMode->Frequency == 72) {
usDataSet = 0x0040; // set bit 6
usDataClr = (USHORT)~0; // no bits to be cleared
} else { // 60 Hz
usDataSet = 0; // no bits to set
usDataClr = (USHORT)~0x0040; // clear bit 6
}
break;
case 800:
if (pRequestedMode->Frequency == 72) {
usDataSet = 0x4020; // set bits 5 and 14
usDataClr = (USHORT)~0; // no bits to clear
} else {
if (pRequestedMode->Frequency == 56) {
usDataSet = 0x4000; // set bit 14
usDataClr = (USHORT)~0x0020; // clr bit 5
} else { // 60 Hz
usDataSet = 0; // no bits to set
usDataClr = (USHORT)~0x4020; // clr bits 5 and 14
} }
break;
case 1024:
if (pRequestedMode->Frequency == 70) {
usDataSet = 0x2010; // set bits 4 and 13
usDataClr = (USHORT)~0; // no bits to clear
} else {
if (pRequestedMode->Frequency == 45) { //interlaced
usDataSet = 0; // no bits to set
usDataClr = (USHORT)~0x2010; // clear bits 4 and 13
} else { // 60 Hz
usDataSet = 0x2000; // set bit 13
usDataClr = (USHORT)~0x0010; // clear bit 4
} }
break;
default:
//
// Restore to original Value
//
usDataSet = HwDeviceExtension->OriginalBiosData; usDataClr = 0x0000;
break;
}
usTemp = VideoPortReadRegisterUshort(pBios) & usDataClr; usTemp |= usDataSet; VideoPortWriteRegisterUshort(pBios,usTemp);
}
break;
}
}
#endif
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
biosArguments.Eax = pRequestedMode->Int10ModeNumber;
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR) {
VideoDebugPrint((1, "VgaSetMode - VideoPortInt10 failed (%d)\n", __LINE__)); return status;
}
if (HwDeviceExtension->ulChipID == ET4000 && HwDeviceExtension->AdapterMemorySize < 0x100000) {
//
// ET4000 less than 1 meg set TLI mode in CRTC.36
//
UnlockET4000ExtendedRegs(HwDeviceExtension); VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR, 0x36);
usTemp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR) | 0x20;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR, (UCHAR)usTemp); LockET4000ExtendedRegs(HwDeviceExtension);
}
//
// If this is a 16bpp or 24bpp mode, call the bios to switch it from
// 8bpp to the new mode.
//
if (pRequestedMode->bitsPerPlane == 16) {
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
biosArguments.Eax = 0x10F0; biosArguments.Ebx = pRequestedMode->Int10ModeNumber;
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR) {
VideoDebugPrint((1, "VgaSetMode - VideoPortInt10 failed (%d)\n", __LINE__)); return status;
} } else if (pRequestedMode->bitsPerPlane == 24) {
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
biosArguments.Eax = 0x10F0; biosArguments.Ebx = pRequestedMode->Int10ModeNumber; biosArguments.Ebx <<= 8; biosArguments.Ebx |= 0xff;
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR) {
VideoDebugPrint((1, "VgaSetMode - VideoPortInt10 failed (%d)\n", __LINE__)); return status;
} }
if (pRequestedMode->hres >= 800) { VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEGMENT_SELECT_PORT,0); }
if (pRequestedMode->CmdStrings != NULL) { VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings); }
//
// Reset the Bios Value to the default so DOS modes will work.
// Do this for all cards except the EISA prodesigner
//
if ((pBios != NULL) && (HwDeviceExtension->BoardID != PRODESIGNERIISEISA)) { VideoPortWriteRegisterUshort(pBios, HwDeviceExtension->OriginalBiosData); }
{ UCHAR temp; UCHAR dummy; UCHAR bIsColor;
if (!(pRequestedMode->fbType & VIDEO_MODE_GRAPHICS)) {
//
// Fix to make sure we always set the colors in text mode to be
// intensity, and not flashing
// For this zero out the Mode Control Regsiter bit 3 (index 0x10
// of the Attribute controller).
//
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + MISC_OUTPUT_REG_READ_PORT) & 0x01) {
bIsColor = TRUE;
} else {
bIsColor = FALSE;
}
if (bIsColor) {
dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR); } else {
dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO); }
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE)); temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + ATT_DATA_READ_PORT);
temp &= 0xF7;
if (bIsColor) {
dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR); } else {
dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO); }
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE)); VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_DATA_WRITE_PORT, temp); } }
//
// Set up the card to use the linear address ranges
//
{ UCHAR bits;
VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->ulSlot, (PVOID) &bits, 0x40, 1);
bits &= ~0x6;
if (HwDeviceExtension->bInLinearMode) { //
// set low 4 bits to 1011
//
bits |= 0xb; } else { //
// set low 4 bits to 0110
//
bits |= 0x6; }
VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->ulSlot, (PVOID) &bits, 0x40, 1); }
//
// Update the location of the physical frame buffer within video memory.
//
HwDeviceExtension->PhysicalFrameLength = MemoryMaps[pRequestedMode->MemMap].MaxSize;
HwDeviceExtension->PhysicalFrameBase.HighPart = 0; HwDeviceExtension->PhysicalFrameBase.LowPart = MemoryMaps[pRequestedMode->MemMap].Start;
//
// Store the new mode value.
//
HwDeviceExtension->CurrentMode = pRequestedMode; HwDeviceExtension->ModeIndex = Mode->RequestedMode;
VideoDebugPrint((1, "VgaSetMode - exit\n")); return NO_ERROR;
} //end VgaSetMode()
VP_STATUS VgaQueryAvailableModes( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE_INFORMATION ModeInformation, ULONG ModeInformationSize, PULONG OutputSize )
/*++
Routine Description:
This routine returns the list of all available available modes on the card.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
ModeInformation - Pointer to the output buffer supplied by the user. This is where the list of all valid modes is stored.
ModeInformationSize - Length of the output buffer supplied by the user.
OutputSize - Pointer to a buffer in which to return the actual size of the data in the buffer. If the buffer was not large enough, this contains the minimum required buffer size.
Return Value:
ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough for the data being returned.
NO_ERROR if the operation completed successfully.
--*/
{ PVIDEO_MODE_INFORMATION videoModes = ModeInformation; ULONG i;
//
// Find out the size of the data to be put in the buffer and return
// that in the status information (whether or not the information is
// there). If the buffer passed in is not large enough return an
// appropriate error code.
//
if (ModeInformationSize < (*OutputSize = HwDeviceExtension->NumAvailableModes * sizeof(VIDEO_MODE_INFORMATION)) ) {
VideoDebugPrint((1,"VgaQueryAvailableModes: ERROR_INSUFFICIENT_BUFFER\n")); return ERROR_INSUFFICIENT_BUFFER;
}
//
// For each mode supported by the card, store the mode characteristics
// in the output buffer.
//
for (i = 0; i < NumVideoModes; i++) {
if (ModesVGA[i].ValidMode) {
videoModes->Length = sizeof(VIDEO_MODE_INFORMATION); videoModes->ModeIndex = i; videoModes->VisScreenWidth = ModesVGA[i].hres; videoModes->ScreenStride = ModesVGA[i].wbytes; videoModes->VisScreenHeight = ModesVGA[i].vres; videoModes->NumberOfPlanes = ModesVGA[i].numPlanes; videoModes->BitsPerPlane = ModesVGA[i].bitsPerPlane; videoModes->Frequency = ModesVGA[i].Frequency; videoModes->XMillimeter = 320; // temporary hardcoded constant
videoModes->YMillimeter = 240; // temporary hardcoded constant
videoModes->NumberRedBits = 6; videoModes->NumberGreenBits = 6; videoModes->NumberBlueBits = 6;
videoModes->AttributeFlags = ModesVGA[i].fbType; videoModes->AttributeFlags |= ModesVGA[i].Interlaced ? VIDEO_MODE_INTERLACED : 0;
//
// Calculate the VideoMemoryBitmapWidth
//
{ LONG x;
x = videoModes->BitsPerPlane;
if( x == 15 ) x = 16;
videoModes->VideoMemoryBitmapWidth = (videoModes->ScreenStride * 8 ) / x; }
videoModes->VideoMemoryBitmapHeight = HwDeviceExtension->AdapterMemorySize / videoModes->ScreenStride;
if (ModesVGA[i].bitsPerPlane == 16) {
videoModes->RedMask = 0x7c00; videoModes->GreenMask = 0x03e0; videoModes->BlueMask = 0x001f;
} else if (ModesVGA[i].bitsPerPlane == 24) {
videoModes->RedMask = 0xff0000; videoModes->GreenMask = 0x00ff00; videoModes->BlueMask = 0x0000ff;
} else {
videoModes->RedMask = 0; videoModes->GreenMask = 0; videoModes->BlueMask = 0; videoModes->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE; }
videoModes++;
} }
return NO_ERROR;
} // end VgaGetAvailableModes()
VP_STATUS VgaQueryNumberOfAvailableModes( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_NUM_MODES NumModes, ULONG NumModesSize, PULONG OutputSize )
/*++
Routine Description:
This routine returns the number of available modes for this particular video card.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
NumModes - Pointer to the output buffer supplied by the user. This is where the number of modes is stored.
NumModesSize - Length of the output buffer supplied by the user.
OutputSize - Pointer to a buffer in which to return the actual size of the data in the buffer.
Return Value:
ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough for the data being returned.
NO_ERROR if the operation completed successfully.
--*/
{ //
// Find out the size of the data to be put in the the buffer and return
// that in the status information (whether or not the information is
// there). If the buffer passed in is not large enough return an
// appropriate error code.
//
if (NumModesSize < (*OutputSize = sizeof(VIDEO_NUM_MODES)) ) {
return ERROR_INSUFFICIENT_BUFFER;
}
//
// Store the number of modes into the buffer.
//
NumModes->NumModes = HwDeviceExtension->NumAvailableModes; NumModes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
VideoDebugPrint((1,"NumAvailableModes = %d\n", HwDeviceExtension->NumAvailableModes)); return NO_ERROR;
} // end VgaGetNumberOfAvailableModes()
VP_STATUS VgaQueryCurrentMode( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE_INFORMATION ModeInformation, ULONG ModeInformationSize, PULONG OutputSize )
/*++
Routine Description:
This routine returns a description of the current video mode.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
ModeInformation - Pointer to the output buffer supplied by the user. This is where the current mode information is stored.
ModeInformationSize - Length of the output buffer supplied by the user.
OutputSize - Pointer to a buffer in which to return the actual size of the data in the buffer. If the buffer was not large enough, this contains the minimum required buffer size.
Return Value:
ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough for the data being returned.
NO_ERROR if the operation completed successfully.
--*/
{ //
// Find out the size of the data to be put in the the buffer and return
// that in the status information (whether or not the information is
// there). If the buffer passed in is not large enough return an
// appropriate error code.
//
if (ModeInformationSize < (*OutputSize = sizeof(VIDEO_MODE_INFORMATION))) {
return ERROR_INSUFFICIENT_BUFFER;
}
//
// Store the characteristics of the current mode into the buffer.
//
ModeInformation->Length = sizeof(VIDEO_MODE_INFORMATION); ModeInformation->ModeIndex = HwDeviceExtension->ModeIndex; ModeInformation->VisScreenWidth = HwDeviceExtension->CurrentMode->hres; ModeInformation->ScreenStride = HwDeviceExtension->CurrentMode->wbytes; ModeInformation->VisScreenHeight = HwDeviceExtension->CurrentMode->vres; ModeInformation->NumberOfPlanes = HwDeviceExtension->CurrentMode->numPlanes; ModeInformation->BitsPerPlane = HwDeviceExtension->CurrentMode->bitsPerPlane; ModeInformation->Frequency = HwDeviceExtension->CurrentMode->Frequency; ModeInformation->XMillimeter = 320; // temporary hardcoded constant
ModeInformation->YMillimeter = 240; // temporary hardcoded constant
ModeInformation->NumberRedBits = 6; ModeInformation->NumberGreenBits = 6; ModeInformation->NumberBlueBits = 6; ModeInformation->RedMask = 0; ModeInformation->GreenMask = 0; ModeInformation->BlueMask = 0; ModeInformation->AttributeFlags = HwDeviceExtension->CurrentMode->fbType | VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE; ModeInformation->AttributeFlags |= HwDeviceExtension->CurrentMode->Interlaced ? VIDEO_MODE_INTERLACED : 0;
//
// Calculate the VideoMemoryBitmapWidth
//
{ LONG x;
x = ModeInformation->BitsPerPlane;
if( x == 15 ) x = 16;
ModeInformation->VideoMemoryBitmapWidth = (ModeInformation->ScreenStride * 8 ) / x; }
ModeInformation->VideoMemoryBitmapHeight = HwDeviceExtension->AdapterMemorySize / ModeInformation->ScreenStride;
return NO_ERROR;
} // end VgaQueryCurrentMode()
VOID VgaZeroVideoMemory( PHW_DEVICE_EXTENSION HwDeviceExtension )
/*++
Routine Description:
This routine zeros the first 256K on the VGA.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/ { // return;
{ UCHAR temp;
VideoDebugPrint((1, "VgaZeroVideoMemory - entry et4000\n"));
//
// Map font buffer at A0000
//
VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
//
// Enable all planes.
//
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT, IND_MAP_MASK);
temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT) | (UCHAR)0x0F;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT, temp);
//
// Zero the memory.
//
VideoPortZeroDeviceMemory(HwDeviceExtension->VideoMemoryAddress, 0xFFFF);
VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color); VideoDebugPrint((1, "VgaZeroVideoMemory - exit et4000\n")); } }
VOID VgaValidateModes( PHW_DEVICE_EXTENSION HwDeviceExtension )
/*++
Routine Description:
Determines which modes are valid and which are not.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/ {
ULONG i;
HwDeviceExtension->NumAvailableModes = 0;
VideoDebugPrint((2, "NumVideoModes(%d)\n",NumVideoModes));
for (i = 0; i < NumVideoModes; i++) {
if (ModesVGA[i].fbType & VIDEO_MODE_GRAPHICS) {
#if !defined(i386)
if (ModesVGA[i].bitsPerPlane < 8) {
//
// no 16 color allowed on non x86
//
continue;
} #endif
switch (HwDeviceExtension->ulChipID) {
case ET6000:
//
// can do all modes
//
break;
case W32P:
//
// Can't do 24bpp if banking, which this is.
// Can't do modes below 640x480.
//
if ((ModesVGA[i].bitsPerPlane == 24) || (ModesVGA[i].vres < 480)) {
continue;
}
break;
case W32I: case W32:
//
// Can't do 24bpp if banking, which this is,
// or if resolution > 640x480.
// Can't do modes below 640x480.
//
//
// !!! fix this expression
//
if ((ModesVGA[i].bitsPerPlane == 24) || (ModesVGA[i].vres < 480) || ((ModesVGA[i].hres > 800) && (ModesVGA[i].bitsPerPlane > 8))) {
continue;
}
break;
default:
//
// Can't do 1280x1024 or 24bpp.
// Can't do modes below 640x480.
//
if ((ModesVGA[i].hres > 1024) || (ModesVGA[i].vres < 480) || (ModesVGA[i].bitsPerPlane > 16)) {
continue;
}
//
// can't do 16bpp if resolution > 640x480
//
if ((ModesVGA[i].hres > 640) && (ModesVGA[i].bitsPerPlane > 8)) {
continue;
}
break;
}
if ((HwDeviceExtension->ulChipID != ET6000) && (HwDeviceExtension->BoardID != STEALTH32)) {
switch (ModesVGA[i].hres) {
case 640:
if ((ModesVGA[i].Frequency == 90) || (ModesVGA[i].Frequency == 85) || (ModesVGA[i].Frequency == 75)) {
continue;
}
break;
case 800:
if ((ModesVGA[i].Frequency == 90) || (ModesVGA[i].Frequency == 85) || (ModesVGA[i].Frequency == 75)) {
continue;
}
break;
case 1024:
if ((ModesVGA[i].Frequency == 75) || (ModesVGA[i].Frequency == 72)) {
continue;
}
break;
case 1280:
if ((ModesVGA[i].Frequency == 75) || (ModesVGA[i].Frequency == 72)) {
continue;
}
break;
} }
if (HwDeviceExtension->BoardID == PRODESIGNER2) {
//
// Original Pro designer 2 only supports
// 640x480x60Hz
// 800x600x56Hz
// 1024x768x60Hz
//
if (ModesVGA[i].bitsPerPlane >= 16) {
continue;
}
if ( ((ModesVGA[i].hres == 640) && (ModesVGA[i].Frequency != 60)) || ((ModesVGA[i].hres == 800) && (ModesVGA[i].Frequency != 56)) || ((ModesVGA[i].hres == 1024) && (ModesVGA[i].Frequency != 60)) ) {
continue;
} }
}
//
// Do not support refresh rates with the EISA pro designer card.
//
if (HwDeviceExtension->BoardID == PRODESIGNERIISEISA) {
ModesVGA[i].Frequency = 1; ModesVGA[i].Interlaced = 0;
}
//
// Make modes that fit in video memory valid.
//
if (HwDeviceExtension->AdapterMemorySize >= ModesVGA[i].numPlanes * ModesVGA[i].sbytes) {
ModesVGA[i].ValidMode = TRUE; HwDeviceExtension->NumAvailableModes++; VideoDebugPrint((2, "mode[%d] valid\n",i)); VideoDebugPrint((2, " hres(%d)\n",ModesVGA[i].hres)); VideoDebugPrint((2, " bitsPerPlane(%d)\n",ModesVGA[i].bitsPerPlane)); VideoDebugPrint((2, " freq(%d)\n",ModesVGA[i].Frequency)); VideoDebugPrint((2, " interlace(%d)\n",ModesVGA[i].Interlaced)); VideoDebugPrint((2, " numPlanes(%d)\n",ModesVGA[i].numPlanes)); VideoDebugPrint((2, " sbytes(%d)\n",ModesVGA[i].sbytes)); VideoDebugPrint((2, " memory reqd(%d)\n",ModesVGA[i].numPlanes * ModesVGA[i].sbytes)); VideoDebugPrint((2, " memory pres(%d)\n",HwDeviceExtension->AdapterMemorySize));
} else { VideoDebugPrint((2, "mode[%d] invalid\n",i)); VideoDebugPrint((2, " hres(%d)\n",ModesVGA[i].hres)); VideoDebugPrint((2, " bitsPerPlane(%d)\n",ModesVGA[i].bitsPerPlane)); VideoDebugPrint((2, " freq(%d)\n",ModesVGA[i].Frequency)); VideoDebugPrint((2, " interlace(%d)\n",ModesVGA[i].Interlaced)); VideoDebugPrint((2, " numPlanes(%d)\n",ModesVGA[i].numPlanes)); VideoDebugPrint((2, " sbytes(%d)\n",ModesVGA[i].sbytes)); VideoDebugPrint((2, " memory reqd(%d)\n",ModesVGA[i].numPlanes * ModesVGA[i].sbytes)); VideoDebugPrint((2, " memory pres(%d)\n",HwDeviceExtension->AdapterMemorySize)); }
} }
|