Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2429 lines
67 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
modeset.c
Abstract:
This is the modeset code for the CL6410/20 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 "cirrus.h"
#include "cmdcnst.h"
extern UCHAR EDIDBuffer[] ;
extern UCHAR EDIDTiming_I ;
extern UCHAR EDIDTiming_II ;
extern UCHAR EDIDTiming_III ;
extern UCHAR DDC2BFlag ;
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
CirrusValidateModes(
PHW_DEVICE_EXTENSION HwDeviceExtension
);
// LCD Support
VP_STATUS
CheckLCDSupportMode(
PHW_DEVICE_EXTENSION HwDeviceExtension,
ULONG i
);
// DDC2B support
BOOLEAN
CheckDDC2B(
PHW_DEVICE_EXTENSION HwDeviceExtension,
ULONG i
);
VOID
AdjFastPgMdOperOnCL5424(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVIDEOMODE pRequestedMode
);
VP_STATUS
CheckGD5446Rev(
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,CirrusValidateModes)
#pragma alloc_text(PAGE,GetAttributeFlags)
#pragma alloc_text(PAGE,CheckLCDSupportMode)
#pragma alloc_text(PAGE,CheckDDC2B)
#pragma alloc_text(PAGE,AdjFastPgMdOperOnCL5424)
#pragma alloc_text(PAGE,CheckGD5446Rev)
#endif
// the following is defined in cirrus.c
VOID
SetCirrusBanking(
PHW_DEVICE_EXTENSION HwDeviceExtension,
ULONG BankNumber
);
//---------------------------------------------------------------------------
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;
PUSHORT pusCmdStream;
VP_STATUS status;
VIDEO_X86_BIOS_ARGUMENTS biosArguments;
USHORT Int10ModeNumber;
ULONG RequestedModeNum;
// crus
UCHAR originalGRIndex, tempB ;
UCHAR SEQIndex ;
//
// Check if the size of the data in the input buffer is large enough.
//
if (ModeSize < sizeof(VIDEO_MODE))
{
return ERROR_INSUFFICIENT_BUFFER;
}
//
// Extract the clear memory, and map linear bits.
//
RequestedModeNum = Mode->RequestedMode &
~(VIDEO_MODE_NO_ZERO_MEMORY | VIDEO_MODE_MAP_MEM_LINEAR);
if (!(Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY))
{
#if defined(_X86_)
VgaZeroVideoMemory(HwDeviceExtension);
#endif
}
//
// Check to see if we are requesting a valid mode
//
if ( (RequestedModeNum >= NumVideoModes) ||
(!ModesVGA[RequestedModeNum].ValidMode) )
{
VideoDebugPrint((0, "Invalide Mode Number = %d!\n", RequestedModeNum));
return ERROR_INVALID_PARAMETER;
}
//
// Check to see if we are trying to map a non linear
// mode linearly.
//
// We will fail early if we are trying to set a mode
// with a linearly mapped frame buffer, and either of the
// following two conditions are true:
//
// 1) The mode can not be mapped linearly because it is
// a vga mode, etc.
//
// or,
//
// 2) We did not find the card in a PCI slot, and thus
// can not do linear mappings period.
//
VideoDebugPrint((0, "Linear Mode Requested: %x\n"
"Linear Mode Supported: %x\n",
Mode->RequestedMode & VIDEO_MODE_MAP_MEM_LINEAR,
ModesVGA[RequestedModeNum].LinearSupport));
if ((Mode->RequestedMode & VIDEO_MODE_MAP_MEM_LINEAR) &&
((!ModesVGA[RequestedModeNum].LinearSupport) ||
(!VgaAccessRange[3].RangeLength)))
{
VideoDebugPrint((0, "Cannot set linear mode!\n"));
return ERROR_INVALID_PARAMETER;
}
else
{
#if defined(_X86_) || defined(_ALPHA_)
HwDeviceExtension->LinearMode =
(Mode->RequestedMode & VIDEO_MODE_MAP_MEM_LINEAR) ?
TRUE : FALSE;
#else
HwDeviceExtension->LinearMode = TRUE;
#endif
VideoDebugPrint((1, "Linear Mode = %s\n",
Mode->RequestedMode & VIDEO_MODE_MAP_MEM_LINEAR ?
"TRUE" : "FALSE"));
}
VideoDebugPrint((2, "Attempting to set mode %d\n",
RequestedModeNum));
pRequestedMode = &ModesVGA[RequestedModeNum];
VideoDebugPrint((2, "Info on Requested Mode:\n"
"\tResolution: %dx%d\n",
pRequestedMode->hres,
pRequestedMode->vres ));
#ifdef INT10_MODE_SET
//
// Set SR14 bit 2 to lock panel, Panel will not be turned on if setting
// this bit. For laptop products only.
//
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
if ((HwDeviceExtension->ChipType == CL756x) ||
(HwDeviceExtension->ChipType == CL755x) ||
(HwDeviceExtension->ChipType == CL754x))
{
biosArguments.Eax = pRequestedMode->BiosModes.BiosModeCL542x;
biosArguments.Eax |= 0x1200;
biosArguments.Ebx = 0xA0; // query video mode availability
status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
//
// bit3=1:panel support, bit2=1:panel enable,
// bit1=1:crt enable(in AH)
//
if ((biosArguments.Eax & 0x0400) &&
!(biosArguments.Eax & 0x0800))
{
return ERROR_INVALID_PARAMETER;
}
else if (!(biosArguments.Eax & 0x0800) &&
!(biosArguments.Eax & 0x0400))
{
//
// Lock turn on panel
//
SEQIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT);
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT, 0x14);
tempB = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) | 0x04;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT,tempB);
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT, SEQIndex);
}
}
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
//
// first, set the montype, if valid
//
if ((pRequestedMode->MonitorType) &&
(HwDeviceExtension->ChipType != CL754x) &&
(HwDeviceExtension->ChipType != CL756x) &&
(HwDeviceExtension->ChipType != CL755x) )
{
biosArguments.Eax = 0x1200 | pRequestedMode->MonitorType;
biosArguments.Ebx = 0xA2; // set monitor type command
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR)
return status;
//
// for 640x480 modes, determine the refresh type
//
if (pRequestedMode->hres == 640)
{
if ((HwDeviceExtension->ChipType != CL754x) &&
(HwDeviceExtension->ChipType != CL756x) &&
(HwDeviceExtension->ChipType != CL755x) )
{
if (HwDeviceExtension->ChipType == CL543x)
{
switch (pRequestedMode->Frequency) {
case 72 :
biosArguments.Eax = 0x1200; // set HIGH refresh to 72hz
break;
case 75:
biosArguments.Eax = 0x1201; // set HIGH refresh to 75hz
break;
case 85:
biosArguments.Eax = 0x1202; // set HIGH refresh to 85hz
break;
#if defined(_ALPHA_)
default:
//
// Fix this for all platforms after we ship.
//
// If we don't do this, eax won't be initialized
// properly below. Thus we may do something we
// don't mean to, such as set as do character writes,
// etc.
//
biosArguments.Eax = 0x1200; // make sure eax is initialized
break;
#endif
}
biosArguments.Ebx = 0xAF; // set refresh type
status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
biosArguments.Eax = 0x1200;
biosArguments.Ebx = 0xAE; // get refresh type
status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
} else {
if (pRequestedMode->Frequency == 72)
{
// 72 hz refresh setup only takes effect in 640x480
biosArguments.Eax = 0x1201; // enable HIGH refresh
}
else
{
// set low refresh rate
biosArguments.Eax = 0x1200; // enable LOW refresh, 640x480 only
}
biosArguments.Ebx = 0xA3; // set refresh type
status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
}
}
if (status != NO_ERROR)
{
return status;
}
}
}
//
// Set the Vertical Monitor type, if BIOS supports it
//
if ((pRequestedMode->MonTypeAX) &&
(HwDeviceExtension->ChipType != CL754x) &&
(HwDeviceExtension->ChipType != CL756x) &&
(HwDeviceExtension->ChipType != CL755x) )
{
biosArguments.Eax = pRequestedMode->MonTypeAX;
biosArguments.Ebx = pRequestedMode->MonTypeBX; // set monitor type
biosArguments.Ecx = pRequestedMode->MonTypeCX;
status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
if (status != NO_ERROR)
{
return status;
}
}
else if ((pRequestedMode->MonTypeAX) &&
((HwDeviceExtension->ChipType == CL754x) ||
(HwDeviceExtension->ChipType == CL756x) ||
(HwDeviceExtension->ChipType == CL755x)) )
{
//
// Re-write this part.
//
biosArguments.Eax = 0x1200;
biosArguments.Ebx = 0x9A;
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (status != NO_ERROR)
{
return status;
}
else
{
biosArguments.Eax = ((biosArguments.Ecx >> 4) & 0x000F);
biosArguments.Ebx = 0x00A4;
biosArguments.Ecx = 0;
if (pRequestedMode->vres == 480)
{
biosArguments.Eax |= 0x1200;
if (pRequestedMode->Frequency == 75)
biosArguments.Eax |= 0x20;
else if (pRequestedMode->Frequency == 72)
biosArguments.Eax |= 0x10;
}
else if (pRequestedMode->vres == 600)
{
biosArguments.Eax |= 0x1200;
if (pRequestedMode->Frequency == 75)
biosArguments.Ebx |= 0x0300;
else if (pRequestedMode->Frequency == 72)
biosArguments.Ebx |= 0x0200;
else if (pRequestedMode->Frequency == 60)
biosArguments.Ebx |= 0x0100;
}
else if (pRequestedMode->vres == 768)
{
biosArguments.Eax |= 0x1200;
if (pRequestedMode->Frequency == 75)
biosArguments.Ebx |= 0x4000;
else if (pRequestedMode->Frequency == 72)
biosArguments.Ebx |= 0x3000;
else if (pRequestedMode->Frequency == 70)
biosArguments.Ebx |= 0x2000;
else if (pRequestedMode->Frequency == 60)
biosArguments.Ebx |= 0x1000;
}
else if (pRequestedMode->vres == 1024)
{
biosArguments.Eax |= 0x1200;
if (pRequestedMode->Frequency == 45)
biosArguments.Ecx |= 0x0000;
}
status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
if (status != NO_ERROR)
{
return status;
}
}
}
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
//
// then, set the mode
//
switch (HwDeviceExtension->ChipType)
{
case CL6410:
Int10ModeNumber = pRequestedMode->BiosModes.BiosModeCL6410;
break;
case CL6420:
Int10ModeNumber = pRequestedMode->BiosModes.BiosModeCL6420;
break;
case CL542x:
case CL543x:
case CL754x:
case CL755x:
case CL756x:
Int10ModeNumber = pRequestedMode->BiosModes.BiosModeCL542x;
break;
}
biosArguments.Eax = Int10ModeNumber;
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
if (HwDeviceExtension->AutoFeature)
{
// i 3ce originalGRIndex
originalGRIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
GRAPH_ADDRESS_PORT);
// o 3ce 31
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
GRAPH_ADDRESS_PORT, INDEX_ENABLE_AUTO_START);
// i 3cf tempB
tempB = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
GRAPH_DATA_PORT);
tempB |= (UCHAR) 0x80; //enable auto start bit 7
// o 3cf tempB
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
GRAPH_DATA_PORT, tempB);
// o 3ce originalGRIndex
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
GRAPH_ADDRESS_PORT, originalGRIndex);
}
//
// Lets check to see that we actually went into the mode
// we just tried to set. If not, then return failure.
//
biosArguments.Eax = 0x0f00;
VideoPortInt10(HwDeviceExtension, &biosArguments);
if ((biosArguments.Eax & 0xff) != Int10ModeNumber)
{
//
// The int10 modeset failed. Return the failure back to
// the system.
//
VideoDebugPrint((0, "The INT 10 modeset didn't set the mode.\n"));
return ERROR_INVALID_PARAMETER;
}
AdjFastPgMdOperOnCL5424 (HwDeviceExtension, pRequestedMode) ;
//
// this code fixes a bug for color TFT panels only
// when on the 6420 and in 640x480 8bpp only
//
if ( (HwDeviceExtension->ChipType == CL6420) &&
(pRequestedMode->bitsPerPlane == 8) &&
(pRequestedMode->hres == 640) )
{
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
GRAPH_ADDRESS_PORT, 0xDC); // color LCD config reg.
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
GRAPH_DATA_PORT) & 01) // if TFT panel
{
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
GRAPH_ADDRESS_PORT, 0xD6); // greyscale offset LCD reg.
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
GRAPH_DATA_PORT,
(UCHAR)((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
GRAPH_DATA_PORT) & 0x3f) | 0x40));
}
}
#endif
//
// Select proper command array for adapter type
//
switch (HwDeviceExtension->ChipType)
{
case CL6410:
VideoDebugPrint((1, "VgaSetMode - Setting mode for 6410\n"));
if (HwDeviceExtension->DisplayType == crt)
pusCmdStream = pRequestedMode->CmdStrings[pCL6410_crt];
else
pusCmdStream = pRequestedMode->CmdStrings[pCL6410_panel];
break;
case CL6420:
VideoDebugPrint((1, "VgaSetMode - Setting mode for 6420\n"));
if (HwDeviceExtension->DisplayType == crt)
pusCmdStream = pRequestedMode->CmdStrings[pCL6420_crt];
else
pusCmdStream = pRequestedMode->CmdStrings[pCL6420_panel];
break;
case CL542x:
VideoDebugPrint((1, "VgaSetMode - Setting mode for 542x\n"));
pusCmdStream = pRequestedMode->CmdStrings[pCL542x];
break;
case CL543x:
if (HwDeviceExtension->BoardType == NEC_ONBOARD_CIRRUS)
{
VideoDebugPrint((1, "VgaSetMode - Setting mode for NEC 543x\n"));
pusCmdStream = pRequestedMode->CmdStrings[pNEC_CL543x];
}
else
{
VideoDebugPrint((1, "VgaSetMode - Setting mode for 543x\n"));
pusCmdStream = pRequestedMode->CmdStrings[pCL543x];
}
break;
case CL754x: // Use 543x cmd strs (16k granularity, >1M modes)
VideoDebugPrint((1, "VgaSetMode - Setting mode for 754x\n"));
pusCmdStream = pRequestedMode->CmdStrings[pCL543x];
if ( (pRequestedMode->bitsPerPlane == 16) &&
(pRequestedMode->hres == 640) )
{
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_COLOR, 0x2E); //expension_reg.
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_COLOR,
(UCHAR)((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_COLOR) & 0xF0)));
}
break;
case CL755x: // Use 543x cmd strs (16k granularity, >1M modes)
VideoDebugPrint((1, "VgaSetMode - Setting mode for 755x\n"));
pusCmdStream = pRequestedMode->CmdStrings[pCL543x];
break;
case CL756x: // Use 543x cmd strs (16k granularity, >1M modes)
VideoDebugPrint((1, "VgaSetMode - Setting mode for 756x\n"));
pusCmdStream = pRequestedMode->CmdStrings[pCL543x];
break;
default:
VideoDebugPrint((0, "HwDeviceExtension->ChipType is INVALID.\n"));
return ERROR_INVALID_PARAMETER;
}
VgaInterpretCmdStream(HwDeviceExtension, pusCmdStream);
#if defined (_PPC_) || (_MIPS_)
//
// Fiddle with DRAM Control register for PPC which does not use int 10
// to set the mode. Specifically:
// Data Bus width in SRF[4,3] is set to 32 bits by default.
// Set to 64-bits for 2 or 4 Megabyte configuration on 5434
// Set Bank Switch control bit (SRF[7] on 5434 w/4MB
//
if (((HwDeviceExtension->ChipRevision == CL5434_ID) ||
(HwDeviceExtension->ChipRevision == CL5430_ID) ||
(HwDeviceExtension->ChipRevision == CL5436_ID) ||
(HwDeviceExtension->ChipRevision == CL5446_ID)) &&
(HwDeviceExtension->AdapterMemorySize >= 0x200000) )
{
UCHAR DRAMCtlVal;
VideoDebugPrint((2, "Modeset: Make data bus width 64-bits\n"));
VideoPortWritePortUchar (HwDeviceExtension->IOAddress
+ SEQ_ADDRESS_PORT, 0x0F);
DRAMCtlVal = (VideoPortReadPortUchar (HwDeviceExtension->
IOAddress + SEQ_DATA_PORT)) | 0x08; // Set Data Bus
// width to 64
// bits
if (HwDeviceExtension->AdapterMemorySize == 0x400000)
{
DRAMCtlVal |= 0x80; // for 4Meg set the Bank Switch Control bit
}
VideoPortWritePortUchar (HwDeviceExtension->IOAddress
+ SEQ_DATA_PORT, DRAMCtlVal);
}
#endif
#if defined(_X86_) || defined(_ALPHA_)
//
// Set linear mode on X86 systems w/PCI bus
//
if (HwDeviceExtension->LinearMode)
{
VideoPortWritePortUchar (HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT, 0x07);
VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
(UCHAR) (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) | 0x10));
}
else
{
VideoPortWritePortUchar (HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT, 0x07);
VideoPortWritePortUchar (HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
(UCHAR) (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) & ~0x10));
}
#endif
//
// Support 256 color modes by stretching the scan lines.
//
if (pRequestedMode->CmdStrings[pStretchScan])
{
VgaInterpretCmdStream(HwDeviceExtension,
pRequestedMode->CmdStrings[pStretchScan]);
}
{
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);
}
}
//
// Update the location of the physical frame buffer within video memory.
//
if (HwDeviceExtension->LinearMode)
{
HwDeviceExtension->PhysicalVideoMemoryBase = VgaAccessRange[3].RangeStart;
HwDeviceExtension->PhysicalVideoMemoryLength = HwDeviceExtension->AdapterMemorySize;
HwDeviceExtension->PhysicalFrameLength = 0;
HwDeviceExtension->PhysicalFrameOffset.LowPart = 0;
}
else
{
HwDeviceExtension->PhysicalVideoMemoryBase = VgaAccessRange[2].RangeStart;
HwDeviceExtension->PhysicalVideoMemoryLength = VgaAccessRange[2].RangeLength;
HwDeviceExtension->PhysicalFrameLength =
MemoryMaps[pRequestedMode->MemMap].MaxSize;
HwDeviceExtension->PhysicalFrameOffset.LowPart =
MemoryMaps[pRequestedMode->MemMap].Offset;
}
//
// Store the new mode value.
//
HwDeviceExtension->CurrentMode = pRequestedMode;
HwDeviceExtension->ModeIndex = Mode->RequestedMode;
//
// BUGBUG - should I include 5430 here?
//
if ((HwDeviceExtension->ChipRevision < CL5434_ID) // we saved chip ID here
&& (pRequestedMode->numPlanes != 4) )
{
if ((HwDeviceExtension->ChipRevision >= 0x0B) && //Nordic(Lite,Viking)
(HwDeviceExtension->ChipRevision <= 0x0E) && //and Everest
(HwDeviceExtension->DisplayType & (panel8x6)) &&
(pRequestedMode->hres == 640) &&
(pRequestedMode->bitsPerPlane == 8) )
{ // For 754x on 800x600 panel, disable HW cursor in 640x480 mode
HwDeviceExtension->VideoPointerEnabled = FALSE; // disable HW Cursor
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_COLOR, 0x2E);
HwDeviceExtension->cursor_vert_exp_flag =
VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_COLOR) & 0x02;
if (HwDeviceExtension->cursor_vert_exp_flag)
{
HwDeviceExtension->CursorEnable = FALSE;
}
}
else
{
HwDeviceExtension->VideoPointerEnabled = TRUE; // enable HW Cursor
}
}
else
{ // For 5434 and 4-bit modes, use value from VideoMode structure
HwDeviceExtension->VideoPointerEnabled = pRequestedMode->HWCursorEnable;
}
//
// Adjust the FIFO Demand Threshold value for the 5436+.
// The 5434 values work for all of the other registers
// except this one.
//
if (HwDeviceExtension->ChipRevision >= CL5436_ID)
{
UCHAR PerfTuningReg, FifoDemandThreshold;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT, IND_PERF_TUNING);
PerfTuningReg = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT);
//
// Add an offset to the threshold that makes the 5434 values work
// for the 5436+. We do this rather than building a whole new set
// of 5436-specific structures.
//
if ((FifoDemandThreshold = (PerfTuningReg & 0x0F) + 4) > 15)
{
FifoDemandThreshold = 15;
}
PerfTuningReg = (PerfTuningReg & ~0x0F) | FifoDemandThreshold;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT, PerfTuningReg);
}
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;
ULONG ulFlags;
//
// 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)) ) {
return ERROR_INSUFFICIENT_BUFFER;
}
//
// The driver specific attribute flags for each mode remains
// constant, so only calculate them once.
//
ulFlags = GetAttributeFlags(HwDeviceExtension);
//
// 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->AttributeFlags = ModesVGA[i].fbType;
videoModes->AttributeFlags |= ModesVGA[i].Interlaced ?
VIDEO_MODE_INTERLACED : 0;
#if defined(_MIPS_)
videoModes->AttributeFlags |= VIDEO_MODE_NO_64_BIT_ACCESS;
#endif
videoModes->DriverSpecificAttributeFlags = ulFlags;
//
// The 5434 has a hardware cursor problem at 1280x1024
// resolution. Use a software cursor on these chips.
//
if ((videoModes->VisScreenWidth == 1280) &&
(HwDeviceExtension->ChipRevision == 0x2A))
{
videoModes->DriverSpecificAttributeFlags
|= CAPS_SW_POINTER;
}
//
// Account for vertical expansion on laptops
//
if ((HwDeviceExtension->ChipType == CL754x) &&
(videoModes->VisScreenHeight == 480) &&
(videoModes->BitsPerPlane == 8))
{
videoModes->DriverSpecificAttributeFlags
|= CAPS_SW_POINTER;
}
//
// 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 == 32) ||
(ModesVGA[i].bitsPerPlane == 24))
{
videoModes->NumberRedBits = 8;
videoModes->NumberGreenBits = 8;
videoModes->NumberBlueBits = 8;
videoModes->RedMask = 0xff0000;
videoModes->GreenMask = 0x00ff00;
videoModes->BlueMask = 0x0000ff;
}
else if (ModesVGA[i].bitsPerPlane == 16)
{
videoModes->NumberRedBits = 6;
videoModes->NumberGreenBits = 6;
videoModes->NumberBlueBits = 6;
videoModes->RedMask = 0x1F << 11;
videoModes->GreenMask = 0x3F << 5;
videoModes->BlueMask = 0x1F;
}
else
{
videoModes->NumberRedBits = 6;
videoModes->NumberGreenBits = 6;
videoModes->NumberBlueBits = 6;
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);
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.
--*/
{
//
// check if a mode has been set
//
if (HwDeviceExtension->CurrentMode == NULL ) {
return ERROR_INVALID_FUNCTION;
}
//
// 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->AttributeFlags = HwDeviceExtension->CurrentMode->fbType |
(HwDeviceExtension->CurrentMode->Interlaced ?
VIDEO_MODE_INTERLACED : 0);
#if defined(_MIPS_)
ModeInformation->AttributeFlags |= VIDEO_MODE_NO_64_BIT_ACCESS;
#endif
ModeInformation->DriverSpecificAttributeFlags =
GetAttributeFlags(HwDeviceExtension);
//
// The 5434 has a hardware cursor problem at 1280x1024
// resolution. Use a software cursor on these chips.
//
if ((ModeInformation->VisScreenWidth == 1280) &&
(HwDeviceExtension->ChipRevision == 0x2A))
{
ModeInformation->DriverSpecificAttributeFlags
|= CAPS_SW_POINTER;
}
//
// Account for vertical expansion on laptops
//
if ((HwDeviceExtension->ChipType == CL754x) &&
(ModeInformation->VisScreenHeight == 480) &&
(ModeInformation->BitsPerPlane == 8))
{
ModeInformation->DriverSpecificAttributeFlags
|= CAPS_SW_POINTER;
if (HwDeviceExtension->cursor_vert_exp_flag)
{
ModeInformation->DriverSpecificAttributeFlags
|= CAPS_CURSOR_VERT_EXP;
}
}
if ((ModeInformation->BitsPerPlane == 24) ||
(ModeInformation->BitsPerPlane == 32)) {
ModeInformation->NumberRedBits = 8;
ModeInformation->NumberGreenBits = 8;
ModeInformation->NumberBlueBits = 8;
ModeInformation->RedMask = 0xff0000;
ModeInformation->GreenMask = 0x00ff00;
ModeInformation->BlueMask = 0x0000ff;
} else if (ModeInformation->BitsPerPlane == 16) {
ModeInformation->NumberRedBits = 6;
ModeInformation->NumberGreenBits = 6;
ModeInformation->NumberBlueBits = 6;
ModeInformation->RedMask = 0x1F << 11;
ModeInformation->GreenMask = 0x3F << 5;
ModeInformation->BlueMask = 0x1F;
} else {
ModeInformation->NumberRedBits = 6;
ModeInformation->NumberGreenBits = 6;
ModeInformation->NumberBlueBits = 6;
ModeInformation->RedMask = 0;
ModeInformation->GreenMask = 0;
ModeInformation->BlueMask = 0;
ModeInformation->AttributeFlags |=
VIDEO_MODE_PALETTE_DRIVEN | VIDEO_MODE_MANAGED_PALETTE;
}
//
// 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.
--*/
{
UCHAR temp;
//
// 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);
VideoPortZeroDeviceMemory(HwDeviceExtension->VideoMemoryAddress, 0xFFFF);
VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
}
VOID
CirrusValidateModes(
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;
ULONG AdapterMemorySize;
USHORT usChipIndex;
//
// Calculate the amount of memory actually available for
// our use. Laptop machines with DSTN panels reserve a
// portion of the frame buffer for half frame acceleration.
//
AdapterMemorySize = HwDeviceExtension->AdapterMemorySize;
if (GetAttributeFlags(HwDeviceExtension) & CAPS_DSTN_PANEL) {
AdapterMemorySize -= 0x24000; // space for half frame accelerator
}
switch (HwDeviceExtension->ChipType)
{
case CL6410: if (HwDeviceExtension->DisplayType == crt)
{
usChipIndex = pCL6410_crt;
}
else
{
usChipIndex = pCL6410_panel;
}
break;
case CL6420: if (HwDeviceExtension->DisplayType == crt)
{
usChipIndex = pCL6420_crt;
}
else
{
usChipIndex = pCL6420_panel;
}
break;
case CL542x: usChipIndex = pCL542x; break;
case CL543x:
case CL5434:
case CL5434_6:
case CL5436:
case CL5446:
case CL754x:
case CL756x:
case CL755x:
if (HwDeviceExtension->BoardType == NEC_ONBOARD_CIRRUS)
{
usChipIndex = pNEC_CL543x;
}
else
{
usChipIndex = pCL543x;
}
break;
default: usChipIndex = 0xffff; break;
}
HwDeviceExtension->NumAvailableModes = 0;
VideoDebugPrint((2, "Checking for available modes:\n"));
VideoDebugPrint((2, "\tMemory Size = %x\n"
"\tChipType = %x\n"
"\tDisplayType = %x\n",
AdapterMemorySize,
HwDeviceExtension->ChipType,
HwDeviceExtension->DisplayType));
for (i = 0; i < NumVideoModes; i++) {
//
// The SpeedStarPRO does not support refresh rates.
// we must return hardware default for all of the modes.
// clean out the mode tables of duplicates ...
//
if (HwDeviceExtension->BoardType == SPEEDSTARPRO)
{
ModesVGA[i].Frequency = 1;
ModesVGA[i].Interlaced = 0;
if (i &&
(ModesVGA[i].numPlanes == ModesVGA[i-1].numPlanes) &&
(ModesVGA[i].bitsPerPlane == ModesVGA[i-1].bitsPerPlane) &&
(ModesVGA[i].hres == ModesVGA[i-1].hres) &&
(ModesVGA[i].vres == ModesVGA[i-1].vres))
{
//
// duplicate mode - skip it.
//
continue;
}
}
VideoDebugPrint((2, "Mode #%ld %dx%d at %d bpp\n"
"\tAdapterMemoryRequired: %x\n"
"\tChipType: %x\n"
"\tDisplayType: %x\n",
i, ModesVGA[i].hres, ModesVGA[i].vres,
ModesVGA[i].bitsPerPlane * ModesVGA[i].numPlanes,
ModesVGA[i].numPlanes * ModesVGA[i].sbytes,
ModesVGA[i].ChipType,
ModesVGA[i].DisplayType));
if ( (AdapterMemorySize >=
ModesVGA[i].numPlanes * ModesVGA[i].sbytes) &&
(HwDeviceExtension->ChipType & ModesVGA[i].ChipType) &&
(HwDeviceExtension->DisplayType & ModesVGA[i].DisplayType) &&
((ModesVGA[i].bitsPerPlane * ModesVGA[i].numPlanes == 24)
? VgaAccessRange[3].RangeLength : TRUE) &&
(HwDeviceExtension->BIOSPresent ||
((usChipIndex != 0xffff) && (ModesVGA[i].CmdStrings[usChipIndex]))))
{
ModesVGA[i].ValidMode = TRUE;
HwDeviceExtension->NumAvailableModes++;
VideoDebugPrint((2, "This mode is valid.\n"));
}
else
{
ModesVGA[i].ValidMode = FALSE;
VideoDebugPrint((2, "This mode is not valid.\n"));
}
#if 0
if (HwDeviceExtension->ChipRevision == 0x3A) {
if (((ModesVGA[i].numPlanes * ModesVGA[i].sbytes) <= 0x200000) &&
(HwDeviceExtension->DisplayType & ModesVGA[i].DisplayType)) {
if (CheckDDC2B(HwDeviceExtension, i)) {
ModesVGA[i].ValidMode = TRUE ;
HwDeviceExtension->NumAvailableModes++ ;
continue ;
}
}
}
#endif
if (CheckGD5446Rev(HwDeviceExtension)) {
// Block 1152x864, 16-bpp
if ((ModesVGA[i].hres == 1152) &&
(ModesVGA[i].vres == 864) &&
(ModesVGA[i].bitsPerPlane == 16))
{
continue ;
}
}
#if 0
if ((HwDeviceExtension->AdapterMemorySize >=
ModesVGA[i].numPlanes * ModesVGA[i].sbytes) &&
(HwDeviceExtension->ChipType != CL754x) &&
(HwDeviceExtension->ChipType != CL756x) &&
(HwDeviceExtension->ChipType != CL755x) &&
(HwDeviceExtension->ChipType & ModesVGA[i].ChipType) &&
(HwDeviceExtension->DisplayType & ModesVGA[i].DisplayType)) {
if (CheckDDC2B(HwDeviceExtension, i)) {
ModesVGA[i].ValidMode = TRUE ;
HwDeviceExtension->NumAvailableModes++ ;
}
}
else if ((HwDeviceExtension->AdapterMemorySize >=
ModesVGA[i].numPlanes * ModesVGA[i].sbytes) &&
((HwDeviceExtension->ChipType == CL754x) ||
(HwDeviceExtension->ChipType == CL756x) ||
(HwDeviceExtension->ChipType == CL755x)) &&
(HwDeviceExtension->ChipType & ModesVGA[i].ChipType) &&
(HwDeviceExtension->DisplayType & ModesVGA[i].DisplayType))
{
if ((HwDeviceExtension->DisplayType & 0x220e) &&
(HwDeviceExtension->AdapterMemorySize >=
((ULONG)(ModesVGA[i].wbytes * ModesVGA[i].vres) +0x20000)) )
{
if (CheckDDC2B(HwDeviceExtension, i)) {
if ((HwDeviceExtension->DisplayType & 0x0006) &&
(CheckLCDSupportMode(HwDeviceExtension, i)) )
{
ModesVGA[i].ValidMode = TRUE ;
HwDeviceExtension->NumAvailableModes++ ;
}
else
{
ModesVGA[i].ValidMode = TRUE ;
HwDeviceExtension->NumAvailableModes++ ;
}
}
}
else
{
if (CheckDDC2B(HwDeviceExtension, i)) {
if ((HwDeviceExtension->DisplayType & 0x0006) &&
(CheckLCDSupportMode(HwDeviceExtension, i)) )
{
ModesVGA[i].ValidMode = TRUE ;
HwDeviceExtension->NumAvailableModes++ ;
}
else
{
ModesVGA[i].ValidMode = TRUE ;
HwDeviceExtension->NumAvailableModes++ ;
}
}
}
}
#endif
}
VideoDebugPrint((2, "NumAvailableModes = %ld\n",
HwDeviceExtension->NumAvailableModes));
}
ULONG
GetAttributeFlags(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
This routine determines whether or not the detected
cirrus chip supports Blt's.
NOTE: This device should not be called until after
CirrusLogicIsPresent has been called.
Arguments:
HwDeviceExtension - Pointer to the device extension.
Return Value:
TRUE - If the device supports Blt's
FALSE - otherwise
--*/
{
ULONG ChipId = HwDeviceExtension->ChipRevision;
ULONG ChipType = HwDeviceExtension->ChipType;
ULONG ulFlags = 0;
//
// Check for BLT support
//
// All 543x & 754x/755x/756x do BLTs
//
if ((ChipType == CL543x) || (ChipType == CL754x) ||
(ChipType == CL755x) || (ChipType == CL756x))
{
ulFlags |= CAPS_BLT_SUPPORT;
}
else if ((ChipType == CL542x) && // 5426-5429 have BLT engines
(ChipId >= 0x26) || // 26 is CL5428
(ChipId == 0x24) ) // 24 is CL5426
{
ulFlags |= CAPS_BLT_SUPPORT;
}
//
// Check for true color support
//
if ((ChipType == CL543x) || (ChipType == CL755x) || (ChipType == CL756x))
{
ulFlags |= CAPS_TRUE_COLOR;
// crus
// Set CL-GD5436, CL-GD54UM36 and CL-GD5446 for autostart routine
// in display driver
if (HwDeviceExtension->AutoFeature)
ulFlags |= CAPS_IS_5436;
}
//
// Can't do host transfers on ISA 5434s
//
if ((HwDeviceExtension->BusType == Isa) &&
(ChipType == CL543x))
{
ulFlags |= CAPS_NO_HOST_XFER;
}
//
// Is this a 542x
//
if (ChipType == CL542x)
{
ulFlags |= CAPS_IS_542x;
if (ChipId == CL5429_ID)
{
//
// Some 5429s have a problem doing host transfers.
//
ulFlags |= CAPS_NO_HOST_XFER;
}
//
// 5428's have problems with HOST_TRANSFERS on MicroChannel bus.
//
if ((HwDeviceExtension->BusType == MicroChannel) &&
(ChipId == CL5428_ID))
{
//
// this is a 5428. We've noticed that some of these have mono
// expand problems on MCA IBM machines.
//
ulFlags |= CAPS_NO_HOST_XFER;
}
}
//
// DSTN panels need 128K of video memory for the
// half frame accelerator.
//
if ((HwDeviceExtension->DisplayType & (STN_LCD | Dual_LCD)) ==
(STN_LCD | Dual_LCD))
{
ulFlags |= CAPS_DSTN_PANEL;
}
#if defined(_MIPS_)
ulFlags |= CAPS_NO_HOST_XFER;
#endif
return ulFlags;
}
BOOLEAN
CheckDDC2B(
PHW_DEVICE_EXTENSION HwDeviceExtension,
ULONG i
)
/*++
Routine Description:
Determines if refresh rate support according to DDC2B standard.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/
{
VideoDebugPrint((2, "CheckDDC2B\n"));
VideoDebugPrint((2, "refresh rate = %ld\n", ModesVGA[i].Frequency));
VideoDebugPrint((2, "hres = %d\n", ModesVGA[i].hres));
VideoDebugPrint((2, "vres = %d\n", ModesVGA[i].vres));
VideoDebugPrint((2, "EDIDTiming_I = %d\n", EDIDTiming_I));
VideoDebugPrint((2, "EDIDTiming_II = %d\n", EDIDTiming_II));
VideoDebugPrint((2, "EDIDTiming_III = %d\n", EDIDTiming_III));
// crus
// Temporarily block DDC2B support
return TRUE ;
if (!DDC2BFlag)
return TRUE ;
if (ModesVGA[i].Frequency == 85) {
if (ModesVGA[i].vres == 1200) { // 1600x1200
// if (!(EDIDTiming_III & 0x02))
// return FALSE ;
;
} else if (ModesVGA[i].vres == 1024) { // 1280x1024
// if (!(EDIDTiming_III & 0x10))
// return FALSE ;
;
} else if (ModesVGA[i].vres == 864) { // 1152x864
;
} else if (ModesVGA[i].vres == 768) { // 1024x768
// if (!(EDIDTiming_III & 0x08))
// return FALSE ;
;
} else if (ModesVGA[i].vres == 600) { // 800x600
// if (!(EDIDTiming_III & 0x20))
// return FALSE ;
;
} else if (ModesVGA[i].vres == 480) { // 640x480
// if (!(EDIDTiming_III & 0x40))
// return FALSE ;
;
}
} else if (ModesVGA[i].Frequency == 75) {
if (ModesVGA[i].vres == 1200) { // 1600x1200
// if (!(EDIDTiming_III & 0x04))
// return FALSE ;
;
} else if (ModesVGA[i].vres == 1024) { // 1280x1024
if (!(EDIDTiming_II & 0x01))
return FALSE ;
} else if (ModesVGA[i].vres == 864) { // 1152x864
if (!(EDIDTiming_III & 0x80))
return FALSE ;
} else if (ModesVGA[i].vres == 768) { // 1024x768
if (!(EDIDTiming_II & 0x02))
return FALSE ;
} else if (ModesVGA[i].vres == 600) { // 800x600
if (!(EDIDTiming_II & 0x40))
return FALSE ;
} else if (ModesVGA[i].vres == 480) { // 640x480
if (!(EDIDTiming_I & 0x04))
return FALSE ;
}
} else if (ModesVGA[i].Frequency == 72) {
if (ModesVGA[i].vres == 600) { // 800x600
if (!(EDIDTiming_II & 0x80))
return FALSE ;
} else if (ModesVGA[i].vres == 480) { // 640x480
if (!(EDIDTiming_I & 0x08))
return FALSE ;
}
} else if (ModesVGA[i].Frequency == 70) {
if (ModesVGA[i].vres == 768) { // 1024x768
if (!(EDIDTiming_II & 0x04))
return FALSE ;
}
} else if (ModesVGA[i].Frequency == 60) {
if (ModesVGA[i].vres == 768) { // 1024x768
if (!(EDIDTiming_II & 0x08))
return FALSE ;
} else if (ModesVGA[i].vres == 600) { // 800x600
if (!(EDIDTiming_I & 0x01))
return FALSE ;
}
} else if (ModesVGA[i].Frequency == 56) {
if (ModesVGA[i].vres == 600) { // 800x600
if (!(EDIDTiming_I & 0x02))
return FALSE ;
}
}
return TRUE ;
} // end CheckDDC2B ()
VOID
AdjFastPgMdOperOnCL5424(
PHW_DEVICE_EXTENSION HwDeviceExtension,
PVIDEOMODE pRequestedMode
)
/*++
Routine Description:
Undesired bars happen on CL5424 800x600x16 color, 512Kb, 56, 60 and 72 Hz
Compaq Prosignia 300 machine. This can be solved by setting SRF(6) to 1.
This bit restricts the write buffer to one level, disabling fast page
mode operation; The faulty control logic is therefore disabled. The
downside is that the performance will take a hit, since we are dealing
with a 5424, so we make a slow chip slower.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
pRequestedMode
Return Value:
None.
--*/
{
UCHAR uc ;
/*--- CL5424 : ID = 100101xx ---*/
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
MISC_OUTPUT_REG_READ_PORT) & 0x01)
{
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_COLOR, 0x27) ;
uc = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_COLOR) ;
} else {
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_MONO, 0x27) ;
uc = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_MONO) ;
}
if ((uc & 0xFC) != 0x94)
return ;
/*--- 800x600x16 color, 60 or 72 Hz ---*/
if (pRequestedMode->hres != 800)
return ;
if (pRequestedMode->vres != 600)
return ;
if (pRequestedMode->bitsPerPlane != 1)
return ;
if (!((pRequestedMode->Frequency == 56) ||
(pRequestedMode->Frequency == 60) ||
(pRequestedMode->Frequency == 72)))
return ;
/*--- 512k ---*/
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT, 0x0A) ;
uc = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) ;
if ((uc & 0x38) != 0x08)
return ;
/*--- SRF(6)=1 --- */
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_ADDRESS_PORT, 0x0F) ;
uc = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT) ;
uc &= 0xBF ;
uc |= 0x40 ;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
SEQ_DATA_PORT, uc) ;
} // end AdjFastPgMdOperOnCL5424 ()
VP_STATUS
CheckGD5446Rev(
PHW_DEVICE_EXTENSION HwDeviceExtension
)
/*++
Routine Description:
Check if it is CL-GD5446 (rev AB/AC)
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
FALSE : It isn't CL-GD5446 rev AB/AC
TRUE : It is CL-GD5446 rev AB/AC
--*/
{
UCHAR uc1, uc2 ;
USHORT us = 0 ;
/*--- CL-GD5446 : Chip ID = 101110xx ---*/
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
MISC_OUTPUT_REG_READ_PORT) & 0x01)
{
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_COLOR, 0x27) ;
uc1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_COLOR) ;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_COLOR, 0x25) ;
uc2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_COLOR) ;
} else {
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_MONO, 0x27) ;
uc1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_MONO) ;
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
CRTC_ADDRESS_PORT_MONO, 0x25) ;
uc2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
CRTC_DATA_PORT_MONO) ;
}
if ((uc1 & 0xFC) != 0xB8)
return FALSE ;
/*--- CL-GD5446 : Rev AB = xxxx xx00 0010 0010 ---*/
/*--- CL-GD5446 : Rev AB = xxxx xx00 0010 0011 ---*/
us += (uc1 & 0x03) ;
us << 8 ;
us += uc2 ;
if ((us == 0x22) || // Rev AB
(us == 0x23)) { // Rev AC
return TRUE ;
} else {
return FALSE ;
}
} // end CheckGD5446Rev ()
VP_STATUS
CheckLCDSupportMode(
PHW_DEVICE_EXTENSION HwDeviceExtension,
ULONG i
)
/*++
Routine Description:
Determines if LCD support the modes.
Arguments:
HwDeviceExtension - Pointer to the miniport driver's device extension.
Return Value:
None.
--*/
{
VP_STATUS status;
VIDEO_X86_BIOS_ARGUMENTS biosArguments;
// DbgBreakPoint();
// biosArguments.Eax = 0x1202;
// biosArguments.Ebx = 0x92; // set LCD & CRT turn on
// status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
// VideoDebugPrint((1, "LCD & CRT all Turn ON\n"));
biosArguments.Eax = 0x1200 | ModesVGA[i].BiosModes.BiosModeCL542x;
biosArguments.Ebx = 0xA0; // query video mode availability
status = VideoPortInt10 (HwDeviceExtension, &biosArguments);
if (status == NO_ERROR)
{
if ( (biosArguments.Eax & 0x00000800) ) //bit3=1:support
return TRUE ;
else
{
return FALSE ;
}
}
else
return FALSE ;
} // end CheckLCDSupportMode()