1909 lines
48 KiB
C
1909 lines
48 KiB
C
/*++
|
||
|
||
Copyright (c) 1992-1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
modeset.c
|
||
|
||
Abstract:
|
||
|
||
This is the modeset code for the WD VGA 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 "wdvga.h"
|
||
|
||
#include "cmdcnst.h"
|
||
|
||
#include "pvgaequ.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
|
||
);
|
||
|
||
VP_STATUS
|
||
VgaSetActiveDisplay(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
||
ULONG ActiveDisplay
|
||
);
|
||
|
||
//
|
||
// Private functions
|
||
//
|
||
|
||
VOID
|
||
DisableLCD(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
);
|
||
|
||
VOID
|
||
EnableLCD(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
);
|
||
|
||
VOID
|
||
DisableCRT(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
);
|
||
|
||
VOID
|
||
EnableCRT(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
);
|
||
|
||
VOID
|
||
UnlockAll(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
);
|
||
|
||
#if defined(ALLOC_PRAGMA)
|
||
#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)
|
||
|
||
//
|
||
// This routine is NOT pagable because it is called a high IRQL
|
||
//
|
||
|
||
//#pragma alloc_text(PAGE,ExternalMonitorPresent)
|
||
|
||
//
|
||
// This routine is NOT pagable because it is called during WdResetHw,
|
||
// which can be called when paging is disabled.
|
||
//
|
||
|
||
//#pragma alloc_text(PAGE,VgaInterpretCmdStream)
|
||
#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;
|
||
UCHAR temp;
|
||
UCHAR dummy;
|
||
UCHAR bIsColor;
|
||
VIDEO_X86_BIOS_ARGUMENTS biosArguments;
|
||
UCHAR frequencySetting;
|
||
PUCHAR CrtAddressPort, CrtDataPort;
|
||
UCHAR bModeFirst = 1;
|
||
BOOLEAN bMonitorPresent;
|
||
|
||
//
|
||
// 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 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];
|
||
|
||
#ifdef INT10_MODE_SET
|
||
|
||
//
|
||
// Make sure we unlock extended registers since the BIOS on some machines
|
||
// does not do it properly.
|
||
//
|
||
|
||
VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT), 0x050F);
|
||
|
||
//
|
||
// Initialize CrtAddressPort, and CrtDataPort
|
||
//
|
||
|
||
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
MISC_OUTPUT_REG_READ_PORT) & 0x01) {
|
||
|
||
bIsColor = TRUE;
|
||
CrtAddressPort = HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR;
|
||
CrtDataPort = HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR;
|
||
|
||
} else {
|
||
|
||
bIsColor = FALSE;
|
||
CrtAddressPort = HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_MONO;
|
||
CrtDataPort = HwDeviceExtension->IOAddress + CRTC_DATA_PORT_MONO;
|
||
|
||
}
|
||
|
||
//
|
||
// Make sure we unlock extended registers since the BIOS on some machines
|
||
// does not do it properly.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, 0x0F);
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, 0x05);
|
||
|
||
|
||
VideoPortWritePortUchar(CrtAddressPort, 0x2b);
|
||
|
||
temp = VideoPortReadPortUchar(CrtDataPort);
|
||
|
||
//
|
||
// Adjust the frequency setting register and write it back out.
|
||
// Also support Diamond changes to frequency settings
|
||
//
|
||
|
||
temp &= pRequestedMode->FrequencyMask;
|
||
|
||
frequencySetting = pRequestedMode->FrequencySetting;
|
||
|
||
|
||
if ( (HwDeviceExtension->BoardID == SPEEDSTAR31) &&
|
||
(pRequestedMode->hres == 1024) ) {
|
||
|
||
//
|
||
// Diamond has inversed the refresh rates of interlaced and 72 Hz
|
||
// on the 1024 modes
|
||
//
|
||
|
||
if (pRequestedMode->Frequency == 72) {
|
||
|
||
frequencySetting = 0x00;
|
||
|
||
} else {
|
||
|
||
if (pRequestedMode->Frequency == 44) {
|
||
|
||
frequencySetting = 0x30;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
temp |= frequencySetting;
|
||
|
||
VideoPortWritePortUchar(CrtDataPort, temp);
|
||
|
||
//
|
||
// Mode set block that can be repeated.
|
||
//
|
||
|
||
SetAgain:
|
||
|
||
//
|
||
// Set the mode
|
||
//
|
||
|
||
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
||
|
||
if (HwDeviceExtension->IsIBM &&
|
||
(pRequestedMode->Int10ModeNumber & 0xffff0000))
|
||
{
|
||
biosArguments.Eax = 0x4f02;
|
||
biosArguments.Ebx = pRequestedMode->Int10ModeNumber >> 16;
|
||
}
|
||
else
|
||
{
|
||
biosArguments.Eax = pRequestedMode->Int10ModeNumber & 0xff;
|
||
}
|
||
|
||
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
|
||
|
||
if (status != NO_ERROR) {
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
//
|
||
// Check to see if the modeset worked. If not, then if we
|
||
// don't have an SVGA Bios, and do have a modetable, then
|
||
// set the mode. Else, fail.
|
||
//
|
||
|
||
if (HwDeviceExtension->BoardID == WD90C24A)
|
||
{
|
||
biosArguments.Eax = 0x0f00;
|
||
VideoPortInt10(HwDeviceExtension, &biosArguments);
|
||
|
||
if ((biosArguments.Eax & 0xff) != (pRequestedMode->Int10ModeNumber & 0xff))
|
||
{
|
||
if ((HwDeviceExtension->SVGABios < FULL_SVGA_BIOS) &&
|
||
(pRequestedMode->ModeTable != NULL))
|
||
{
|
||
BOOLEAN bLCD=FALSE;
|
||
|
||
VideoDebugPrint((1, "\n*** Setting mode with mode table!\n\n"));
|
||
|
||
//
|
||
// NOTE: Certain models of IBM Thinkpads can switch
|
||
// between LCD, Monitor, and Simultaneous modes while
|
||
// the machine is running. Other models cannot.
|
||
// Currently we have noticed a coralation between
|
||
// machines which have SVGA Bios's and machines which
|
||
// can set the mode.
|
||
//
|
||
// IF MACHINE HAS SVGA BIOS THEN
|
||
// MACHINE CAN TURN ON/OFF LCD ON THE FLY
|
||
// ELSE
|
||
// MACHINE CANNOT TURN ON/OFF LCD ON THE FLY
|
||
//
|
||
// If a user has a machine where the LCD can be turned
|
||
// on dynamically, then it is possible that the user
|
||
// will turn on the LCD when we think it is off. Then
|
||
// we may try to set a mode which does not work with
|
||
// the LCD off. To avoid this problem, we will try
|
||
// to determine if the LCD is on/off before setting
|
||
// the mode. If the LCD is on, and it needs to be
|
||
// off in order for the modeset to succeed, we'll fail
|
||
// the modeset.
|
||
//
|
||
// Unfortunately, this does not solve all of our
|
||
// problems. The code which we use to try to detect
|
||
// whether or not the LCD is on fails on some
|
||
// machines. The code seems to fail on machines
|
||
// which do not have SVGA Bios's. As mentioned above
|
||
// machines which do not have SVGA Bios's can not
|
||
// switch on their LCD's dynamically. Therefore we
|
||
// do not need to execute this special code on these
|
||
// machines because the LCD state wont change on us
|
||
// anyway.
|
||
//
|
||
|
||
if (HwDeviceExtension->SVGABios > NO_SVGA_BIOS)
|
||
{
|
||
//
|
||
// If the LCD is enabled we also need to SET bit 0
|
||
// of PR2.
|
||
//
|
||
// We will check to see if the LCD is enabled by
|
||
// checking bit 2 of CRTC register 0x31, and bit
|
||
// 4 of CRTC register 0x32. If either of these
|
||
// is set, then we'll assume an LCD is enabled.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
CRTC_ADDRESS_PORT_COLOR, 0x31);
|
||
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
CRTC_DATA_PORT_COLOR) & 0x04)
|
||
{
|
||
bLCD = TRUE;
|
||
}
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
CRTC_ADDRESS_PORT_COLOR, 0x32);
|
||
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
CRTC_DATA_PORT_COLOR) & 0x10)
|
||
{
|
||
bLCD = TRUE;
|
||
}
|
||
|
||
//
|
||
// For some reason, on the 755CDV, if we set a high res mode,
|
||
// while the LCD is on, then the LCD won't be disabled
|
||
// properly. Therefore, fail the mode set if the LCD
|
||
// is on, and we need to turn it off to set this mode.
|
||
//
|
||
|
||
if (bLCD &&
|
||
!(HwDeviceExtension->DisplayType &
|
||
pRequestedMode->LCDtype &
|
||
~MONITOR))
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
}
|
||
|
||
VgaSetActiveDisplay(HwDeviceExtension, LCD_DISABLE | CRT_ENABLE);
|
||
|
||
VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->ModeTable);
|
||
|
||
//
|
||
// if the LCD can do this mode, then turn the LCD
|
||
// back on. Else, leave it off.
|
||
//
|
||
// add the code!!
|
||
//
|
||
|
||
if (pRequestedMode->LCDtype & HwDeviceExtension->DisplayType & ~MONITOR)
|
||
{
|
||
VgaSetActiveDisplay(HwDeviceExtension, LCD_ENABLE | CRT_ENABLE);
|
||
|
||
VideoDebugPrint((1, "LCD Enabled!\n"));
|
||
}
|
||
else
|
||
{
|
||
VgaSetActiveDisplay(HwDeviceExtension, LCD_DISABLE | CRT_ENABLE);
|
||
|
||
VideoDebugPrint((1, "LCD Disabled!\n"));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pRequestedMode->CmdStrings != NULL)
|
||
{
|
||
VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings);
|
||
}
|
||
|
||
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 (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);
|
||
|
||
}
|
||
|
||
//
|
||
// A few wd cards do not work properly on the first mode set. You have
|
||
// to set the mode twice. So lets set it twice!
|
||
//
|
||
|
||
if (bModeFirst == 1 && HwDeviceExtension->BoardID != WD90C24A)
|
||
{
|
||
|
||
bModeFirst = 0;
|
||
goto SetAgain;
|
||
|
||
}
|
||
|
||
#else
|
||
|
||
VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings);
|
||
|
||
#endif
|
||
|
||
//
|
||
// Make sure we unlock extended registers since the BIOS on some machines
|
||
// does not do it properly.
|
||
//
|
||
|
||
VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT), 0x050F);
|
||
|
||
if (HwDeviceExtension->BoardID == WD90C24A)
|
||
{
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_PIXEL_MASK_PORT, 0xFF);
|
||
}
|
||
|
||
//
|
||
// Update the location of the physical frame buffer within video memory.
|
||
//
|
||
|
||
HwDeviceExtension->PhysicalFrameLength =
|
||
MemoryMaps[pRequestedMode->MemMap].MaxSize;
|
||
|
||
HwDeviceExtension->PhysicalFrameBase.LowPart =
|
||
MemoryMaps[pRequestedMode->MemMap].Start;
|
||
|
||
//
|
||
// Store the new mode value.
|
||
//
|
||
|
||
HwDeviceExtension->CurrentMode = pRequestedMode;
|
||
HwDeviceExtension->ModeIndex = Mode->RequestedMode;
|
||
|
||
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)) ) {
|
||
|
||
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->AttributeFlags = ModesVGA[i].fbType;
|
||
videoModes->AttributeFlags |= ModesVGA[i].Interlaced ?
|
||
VIDEO_MODE_INTERLACED : 0;
|
||
videoModes->DriverSpecificAttributeFlags = 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->NumberRedBits = 5;
|
||
videoModes->NumberGreenBits = 6;
|
||
videoModes->NumberBlueBits = 5;
|
||
videoModes->RedMask = 0xF800;
|
||
videoModes->GreenMask = 0x07E0;
|
||
videoModes->BlueMask = 0x001F;
|
||
|
||
}
|
||
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;
|
||
|
||
}
|
||
|
||
//
|
||
// Validate the modes each time on the portables since an external monitor
|
||
// can be connected or disconnected dynamically.
|
||
//
|
||
|
||
VgaValidateModes(HwDeviceExtension);
|
||
|
||
//
|
||
// 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);
|
||
|
||
ModeInformation->DriverSpecificAttributeFlags = 0;
|
||
|
||
if (ModeInformation->BitsPerPlane == 16) {
|
||
|
||
ModeInformation->NumberRedBits = 5;
|
||
ModeInformation->NumberGreenBits = 6;
|
||
ModeInformation->NumberBlueBits = 5;
|
||
ModeInformation->RedMask = 0xF800;
|
||
ModeInformation->GreenMask = 0x07E0;
|
||
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);
|
||
|
||
//
|
||
// Zero the memory.
|
||
//
|
||
|
||
VideoPortZeroDeviceMemory(HwDeviceExtension->VideoMemoryAddress, 0xFFFF);
|
||
|
||
VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
|
||
|
||
}
|
||
|
||
|
||
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((1, "VgaValidateModes:\n"));
|
||
|
||
VideoDebugPrint((1, "Avail Adapter Mem: 0x%x\n"
|
||
"Avail Monitor Type: 0x%x\n",
|
||
HwDeviceExtension->AdapterMemorySize,
|
||
HwDeviceExtension->DisplayType));
|
||
|
||
for (i = 0; i < NumVideoModes; i++) {
|
||
|
||
VideoDebugPrint((1, "Mode %d %dx%d at %d bpp\n"
|
||
"\tAdapterMemoryRequired: 0x%x\n"
|
||
"\tMonitorType 0x%x\n",
|
||
i, ModesVGA[i].hres, ModesVGA[i].vres,
|
||
ModesVGA[i].bitsPerPlane * ModesVGA[i].numPlanes,
|
||
ModesVGA[i].numPlanes * ModesVGA[i].sbytes,
|
||
ModesVGA[i].LCDtype));
|
||
|
||
if ((HwDeviceExtension->AdapterMemorySize >=
|
||
ModesVGA[i].numPlanes * ModesVGA[i].sbytes) &&
|
||
(HwDeviceExtension->DisplayType &
|
||
ModesVGA[i].LCDtype))
|
||
{
|
||
|
||
ModesVGA[i].ValidMode = TRUE;
|
||
HwDeviceExtension->NumAvailableModes++;
|
||
}
|
||
|
||
|
||
//
|
||
// invalidates some modes we may have enabled based on some specific
|
||
// chip\machine problems
|
||
//
|
||
|
||
if ( (ModesVGA[i].ValidMode) &&
|
||
(HwDeviceExtension->BoardID == WD90C24A))
|
||
|
||
{
|
||
if (HwDeviceExtension->IsIBM == TRUE)
|
||
{
|
||
//
|
||
// get rid of 256 color modes > 640x480 on
|
||
// machines with STN displays
|
||
//
|
||
|
||
if ((ModesVGA[i].bitsPerPlane == 8) &&
|
||
(ModesVGA[i].hres > 640) &&
|
||
(HwDeviceExtension->DisplayType & TOSHIBA_DSTNC))
|
||
{
|
||
ModesVGA[i].ValidMode = FALSE;
|
||
HwDeviceExtension->NumAvailableModes--;
|
||
}
|
||
|
||
//
|
||
// get rid of 64K color support for machines without
|
||
// SVGABios support
|
||
//
|
||
|
||
else if ((ModesVGA[i].bitsPerPlane == 16) &&
|
||
(HwDeviceExtension->SVGABios == NO_SVGA_BIOS))
|
||
{
|
||
ModesVGA[i].ValidMode = FALSE;
|
||
HwDeviceExtension->NumAvailableModes--;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// 16bpp modes only work on the WD90C24A chip sets.
|
||
//
|
||
|
||
if( (ModesVGA[i].ValidMode) &&
|
||
(HwDeviceExtension->BoardID != WD90C24A) &&
|
||
(ModesVGA[i].bitsPerPlane == 16))
|
||
{
|
||
ModesVGA[i].ValidMode = FALSE;
|
||
HwDeviceExtension->NumAvailableModes--;
|
||
}
|
||
|
||
//
|
||
// Older boards do not support 72HZ in 1024x768 modes.
|
||
// So disable those.
|
||
//
|
||
|
||
if ( (ModesVGA[i].ValidMode) &&
|
||
(HwDeviceExtension->BoardID < WD90C31) &&
|
||
(ModesVGA[i].hres == 1024) &&
|
||
(ModesVGA[i].vres == 768) &&
|
||
(ModesVGA[i].Frequency == 72) )
|
||
{
|
||
|
||
ModesVGA[i].ValidMode = FALSE;
|
||
HwDeviceExtension->NumAvailableModes--;
|
||
|
||
}
|
||
|
||
if (ModesVGA[i].ValidMode == FALSE)
|
||
{
|
||
VideoDebugPrint((1, "The mode is not valid.\n"));
|
||
}
|
||
else
|
||
{
|
||
VideoDebugPrint((1, "The mode is valid.\n"));
|
||
}
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
ExternalMonitorPresent(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Determine whether an external monitor is connected to the
|
||
machine. This routine should only be called if the
|
||
BoardID == WD90C24A.
|
||
|
||
Note: This routine expects to be called after the WD extended
|
||
registers have been unlocked.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
||
Return Value:
|
||
|
||
Updated the DisplayType field in HwDeviceExtension to indicate
|
||
whether a monitor is connected.
|
||
|
||
The routine always returns TRUE.
|
||
|
||
--*/
|
||
{
|
||
UCHAR dac[3];
|
||
UCHAR _pr19, _pr1b;
|
||
int i,j;
|
||
int bExternal = 0;
|
||
|
||
//
|
||
// If we are on an IBM machine, use SMAPI routines
|
||
// instead of detetecting the monitor ourselves.
|
||
//
|
||
|
||
if (HwDeviceExtension->IsIBM)
|
||
{
|
||
bExternal = LCDIsMonitorPresent();
|
||
|
||
if (bExternal)
|
||
{
|
||
HwDeviceExtension->DisplayType |= MONITOR;
|
||
}
|
||
else
|
||
{
|
||
HwDeviceExtension->DisplayType &= ~MONITOR;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// Only refresh display with value in DAC 0
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_PIXEL_MASK_PORT, 0x00);
|
||
|
||
|
||
//
|
||
// lets preserve what's in the DAC
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_ADDRESS_READ_PORT,
|
||
(UCHAR) 0);
|
||
|
||
for (j=0; j<3; j++)
|
||
{
|
||
dac[j]= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_DATA_REG_PORT);
|
||
}
|
||
|
||
//
|
||
// Fill in DAC 0 with a value for the test
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_ADDRESS_WRITE_PORT, 0);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_DATA_REG_PORT, 0x04); // Red
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_DATA_REG_PORT, 0x12); // Green
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_DATA_REG_PORT, 0x04); // Blue
|
||
|
||
//
|
||
// We need to check bit 4 of 0x3c2. We only want to check
|
||
// this bit during actual display output. Therefore we will
|
||
// wait for a vertical refresh, and then try to wait 300
|
||
// nanoseconds for the monitor detection circuits to
|
||
// stabalize, and then read the bit. (I may have to adjust
|
||
// crtc registers to prevent refresh cycles).
|
||
//
|
||
// There are two bits in the Input Status #1 Register which
|
||
// will help us to detect if we are in a refresh cycle. If
|
||
// bit 3 is on then we are in a verticle refresh. If bit 0
|
||
// is off (0) then we are in a display mode, else we are in
|
||
// some sort of a refresh.
|
||
//
|
||
// Therefore, for our purposes, we will do the following. We
|
||
// will wait for a verticle refresh (bit 3 = 1) then we will
|
||
// wait for it to turn off. We are now starting to draw the
|
||
// screen. Now we will examine the monitor connection bit
|
||
// (bit 4 of 0x3c2) until the display mode bit (bit 0 of
|
||
// 0x3da) goes high. Now we will use our last recorded value
|
||
// for monitor detection.
|
||
//
|
||
|
||
//
|
||
// wait for V retrace
|
||
//
|
||
|
||
while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
INPUT_STATUS_1_COLOR) & 0x8) == 0);
|
||
|
||
//
|
||
// wait for V retrace to end
|
||
//
|
||
|
||
while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
INPUT_STATUS_1_COLOR) & 0x8) != 0);
|
||
|
||
//
|
||
// wait for display enable to start
|
||
//
|
||
|
||
while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
INPUT_STATUS_1_COLOR) & 0x1) != 0);
|
||
|
||
//
|
||
// wait for display enable to end. Use last value of
|
||
// bExternal to determine if an external monitor is
|
||
// connected.
|
||
//
|
||
|
||
{
|
||
int LoopCount=0, OnCount=0;
|
||
|
||
bExternal = FALSE;
|
||
|
||
while ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
INPUT_STATUS_1_COLOR) & 0x1) == 0)
|
||
{
|
||
if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
INPUT_STATUS_0_PORT) & 0x10) == 0x10)
|
||
{
|
||
OnCount++;
|
||
}
|
||
|
||
LoopCount++;
|
||
}
|
||
|
||
if (OnCount > (LoopCount / 2)) // should compile as LoopCount >> 1
|
||
{
|
||
bExternal = TRUE;
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// restore the DAC
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_ADDRESS_WRITE_PORT,
|
||
(UCHAR) 0);
|
||
|
||
for (j=0; j<3; j++)
|
||
{
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_DATA_REG_PORT,
|
||
dac[j]);
|
||
}
|
||
|
||
//
|
||
// Re-enable the DAC
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_PIXEL_MASK_PORT, 0xFF);
|
||
|
||
//
|
||
// restore _pr19, and _pr1b state
|
||
//
|
||
|
||
if (bExternal)
|
||
{
|
||
HwDeviceExtension->DisplayType |= MONITOR;
|
||
}
|
||
else
|
||
{
|
||
HwDeviceExtension->DisplayType &= ~MONITOR;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
VP_STATUS
|
||
VgaSetActiveDisplay(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
||
ULONG ActiveDisplay
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine selects the active display device(s).
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
||
ActiveDisplay - Devices to be active.
|
||
(See WD90C24A.H for the definition)
|
||
|
||
Return Value:
|
||
|
||
If successful, return NO_ERROR, else return FALSE.
|
||
|
||
--*/
|
||
|
||
{
|
||
VP_STATUS status = ERROR_INVALID_PARAMETER;
|
||
|
||
//
|
||
// Unlock paradise registers
|
||
//
|
||
|
||
UnlockAll(HwDeviceExtension);
|
||
|
||
//
|
||
// Enable or Disable LCD output
|
||
//
|
||
// Note: To prevent the fuse of LCD from blowing up, LCD should be turns off
|
||
// while output is disabled.
|
||
//
|
||
// If VideoPortPowerControl() returns an error for the absence of HALPM.SYS,
|
||
// we will try to control LCD by accessing the hardware directly.
|
||
//
|
||
|
||
if (ActiveDisplay & LCD_ENABLE) {
|
||
|
||
EnableLCD(HwDeviceExtension);
|
||
|
||
} else if (ActiveDisplay & LCD_DISABLE) {
|
||
|
||
DisableLCD(HwDeviceExtension);
|
||
|
||
}
|
||
|
||
//
|
||
// Enable or Disable CRT output
|
||
//
|
||
|
||
if (ActiveDisplay & CRT_ENABLE) {
|
||
EnableCRT(HwDeviceExtension);
|
||
} else {
|
||
DisableCRT(HwDeviceExtension);
|
||
}
|
||
|
||
return NO_ERROR;
|
||
} // end VgaSetActiveDisplay()
|
||
|
||
|
||
VOID
|
||
DisableLCD(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine disables LCD interface of WD90C24A/A2.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR IoBase = HwDeviceExtension->IOAddress;
|
||
|
||
//
|
||
// Wait until next vertical retrace interval
|
||
//
|
||
|
||
while (0 == (VideoPortReadPortUchar(IoBase + INPUT_STATUS_1_COLOR) & 0x08));
|
||
|
||
//
|
||
// Disables LCD interface
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x10));
|
||
|
||
//
|
||
// Tristates LCD control and data signals
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + GRAPH_ADDRESS_PORT, pr4);
|
||
VideoPortWritePortUchar(
|
||
IoBase + GRAPH_DATA_PORT,
|
||
(CHAR)(VideoPortReadPortUchar(IoBase + GRAPH_DATA_PORT) | 0x20));
|
||
|
||
//
|
||
// Unlocks CRTC shadow registers
|
||
//
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
|
||
(USHORT)pr1b | ((USHORT)pr1b_unlock << 8));
|
||
|
||
} // end DisableLCD()
|
||
|
||
|
||
VOID
|
||
EnableLCD(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables LCD interface of WD90C24A/A2.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR IoBase = HwDeviceExtension->IOAddress;
|
||
|
||
//
|
||
// Locks CRTC shadow registers
|
||
//
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
|
||
(USHORT)pr1b | ((USHORT)pr1b_unlock_pr << 8));
|
||
|
||
//
|
||
// Wait until next vertical retrace interval
|
||
//
|
||
|
||
while (0 == (VideoPortReadPortUchar(IoBase + INPUT_STATUS_1_COLOR) & 0x08));
|
||
|
||
//
|
||
// Drives LCD control and data signals
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + GRAPH_ADDRESS_PORT, pr4);
|
||
VideoPortWritePortUchar(
|
||
IoBase + GRAPH_DATA_PORT,
|
||
(CHAR)(VideoPortReadPortUchar(IoBase + GRAPH_DATA_PORT) & ~0x20));
|
||
|
||
//
|
||
// Enables LCD interface
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(CHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x10));
|
||
|
||
} // end EnableLCD()
|
||
|
||
|
||
VOID
|
||
DisableCRT(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine disables CRT interface of WD90C24A/A2
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR IoBase = HwDeviceExtension->IOAddress;
|
||
|
||
//
|
||
// Disables CRT interface
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x20));
|
||
|
||
//
|
||
// Shuts off internal RAMDAC
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr18);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x80));
|
||
|
||
//
|
||
// Disables CRT H-sync and V-sync signals
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr39);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x04));
|
||
|
||
} // end DisableCRT()
|
||
|
||
|
||
VOID
|
||
EnableCRT(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enables CRT interface of WD90C24A/A2
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR IoBase = HwDeviceExtension->IOAddress;
|
||
|
||
//
|
||
// Enables CRT interface
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x20));
|
||
|
||
//
|
||
// Enables internal RAMDAC
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr18);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) & ~0x80));
|
||
|
||
//
|
||
// Enables CRT H-sync and V-sync signals
|
||
//
|
||
|
||
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr39);
|
||
VideoPortWritePortUchar(
|
||
IoBase + CRTC_DATA_PORT_COLOR,
|
||
(UCHAR)(VideoPortReadPortUchar(IoBase + CRTC_DATA_PORT_COLOR) | 0x04));
|
||
|
||
} // end EnableCRT()
|
||
|
||
|
||
VOID
|
||
UnlockAll(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine unlocks all WD registers, except CRTC shadow registers
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR IoBase = HwDeviceExtension->IOAddress;
|
||
|
||
//
|
||
// Unlocks the all WD registers
|
||
//
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + GRAPH_ADDRESS_PORT),
|
||
(USHORT)pr5 | ((USHORT)pr5_unlock << 8));
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
|
||
(USHORT)pr10 | ((USHORT)pr10_unlock << 8));
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
|
||
(USHORT)pr11 | ((USHORT)pr11_unlock << 8));
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + SEQ_ADDRESS_PORT),
|
||
(USHORT)pr20 | ((USHORT)pr20_unlock << 8));
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + SEQ_ADDRESS_PORT),
|
||
(USHORT)pr72 | ((USHORT)pr72_unlock << 8));
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
|
||
(USHORT)pr1b | ((USHORT)pr1b_unlock_pr << 8));
|
||
|
||
VideoPortWritePortUshort(
|
||
(PUSHORT)(IoBase + CRTC_ADDRESS_PORT_COLOR),
|
||
(USHORT)pr30 | ((USHORT)pr30_unlock << 8));
|
||
|
||
return;
|
||
} // end UnlockAll()
|