mirror of https://github.com/lianthony/NT4.0
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.
1842 lines
46 KiB
1842 lines
46 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
Copyright (c) 1994-1995 IBM Corporation
|
|
|
|
Module Name:
|
|
|
|
modeset.c
|
|
|
|
Abstract:
|
|
|
|
This is the modeset code for the WD 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 "wd90c24a.h"
|
|
#include "pvgaequ.h"
|
|
|
|
#include "cmdcnst.h"
|
|
|
|
//
|
|
// Public functions
|
|
//
|
|
|
|
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
|
|
//
|
|
|
|
BOOLEAN
|
|
CRTDetect(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|
);
|
|
|
|
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
|
|
);
|
|
|
|
#ifdef PPC
|
|
VOID
|
|
TurnOnLCD(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
BOOLEAN PowerState
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// External variables
|
|
//
|
|
|
|
extern PVIDEO_CLUT CurrClutBuffer;
|
|
|
|
#if defined(ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE,VgaInterpretCmdStream)
|
|
#pragma alloc_text(PAGE,VgaSetMode)
|
|
#pragma alloc_text(PAGE,VgaQueryAvailableModes)
|
|
#pragma alloc_text(PAGE,VgaQueryNumberOfAvailableModes)
|
|
#pragma alloc_text(PAGE,VgaQueryCurrentMode)
|
|
#pragma alloc_text(PAGE,VgaZeroVideoMemory)
|
|
#pragma alloc_text(PAGE,VgaValidateModes)
|
|
#pragma alloc_text(PAGE,VgaSetActiveDisplay)
|
|
#pragma alloc_text(PAGE,CRTDetect)
|
|
#pragma alloc_text(PAGE,DisableLCD)
|
|
#pragma alloc_text(PAGE,EnableLCD)
|
|
#pragma alloc_text(PAGE,DisableCRT)
|
|
#pragma alloc_text(PAGE,EnableCRT)
|
|
#pragma alloc_text(PAGE,UnlockAll)
|
|
#ifdef PPC
|
|
#pragma alloc_text(PAGE,TurnOnLCD)
|
|
#endif
|
|
#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;
|
|
#ifdef INT10_MODE_SET
|
|
VP_STATUS status;
|
|
UCHAR temp;
|
|
UCHAR dummy;
|
|
UCHAR bIsColor;
|
|
VIDEO_X86_BIOS_ARGUMENTS biosArguments;
|
|
UCHAR frequencySetting;
|
|
PUCHAR CrtAddressPort, CrtDataPort;
|
|
UCHAR bModeFirst = 1;
|
|
#endif
|
|
|
|
//
|
|
// 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 bit.
|
|
//
|
|
|
|
if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY) {
|
|
|
|
Mode->RequestedMode &= ~VIDEO_MODE_NO_ZERO_MEMORY;
|
|
|
|
}
|
|
|
|
//
|
|
// Check to see if we are requesting a valid mode
|
|
//
|
|
|
|
if ( (Mode->RequestedMode >= NumVideoModes) ||
|
|
(!ModesVGA[Mode->RequestedMode].ValidMode) ) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
pRequestedMode = &ModesVGA[Mode->RequestedMode];
|
|
|
|
#ifdef INT10_MODE_SET
|
|
|
|
//
|
|
// Mode set block that can be repeated.
|
|
//
|
|
|
|
SetAgain:
|
|
|
|
//
|
|
// First set up the frequency so the modeset grabs it properly.
|
|
//
|
|
|
|
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);
|
|
|
|
//
|
|
// Set the mode
|
|
//
|
|
|
|
VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
|
|
biosArguments.Eax = pRequestedMode->Int10ModeNumber;
|
|
|
|
status = VideoPortInt10(HwDeviceExtension, &biosArguments);
|
|
|
|
if (status != NO_ERROR) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
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. To lets set it twice!
|
|
//
|
|
|
|
if (bModeFirst == 1) {
|
|
|
|
bModeFirst = 0;
|
|
goto SetAgain;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
//
|
|
// Disable the hardware cursor.
|
|
//
|
|
|
|
VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->ExtendedIOAddress + 0), 0x1002);
|
|
VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->ExtendedIOAddress + 2), 0);
|
|
VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->ExtendedIOAddress + 2), 0x7FFF);
|
|
|
|
//
|
|
// Switch to CRT only display mode
|
|
//
|
|
|
|
VgaSetActiveDisplay(HwDeviceExtension, LCD_DISABLE | CRT_ENABLE);
|
|
|
|
//
|
|
// Check the presence of external CRT
|
|
//
|
|
// Note: It is assumed that v7310 is not active at this moment.
|
|
//
|
|
|
|
if (HwDeviceExtension->VirtualScreenOption & (USHORT)0x02) {
|
|
|
|
VideoPortSynchronizeExecution(HwDeviceExtension,
|
|
VpHighPriority,
|
|
(PMINIPORT_SYNCHRONIZE_ROUTINE) CRTDetect,
|
|
HwDeviceExtension);
|
|
VideoDebugPrint((1, "CRT Present =%x\n", HwDeviceExtension->CRTPresent));
|
|
|
|
} else {
|
|
|
|
HwDeviceExtension->CRTPresent = (HwDeviceExtension->VirtualScreenOption & (USHORT)0x01) ? FALSE : TRUE;
|
|
|
|
} /* endif */
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
if ((pRequestedMode->DisplayDevices[HwDeviceExtension->CRTPresent] & LCD_ENABLE) &&
|
|
(HwDeviceExtension->PanelType != NoLCD)) {
|
|
HwDeviceExtension->LCDEnable = TRUE;
|
|
} else {
|
|
HwDeviceExtension->LCDEnable = FALSE;
|
|
} /* endif */
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
VgaInterpretCmdStream(HwDeviceExtension,
|
|
pRequestedMode->CmdStrings[HwDeviceExtension->CRTPresent]);
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
HwDeviceExtension->VirtualScreenEnable = FALSE;
|
|
|
|
if (HwDeviceExtension->LCDEnable) {
|
|
if ((pRequestedMode->hres > HwDeviceExtension->PanelXResolution) ||
|
|
(pRequestedMode->vres > HwDeviceExtension->PanelYResolution)) {
|
|
|
|
//
|
|
// enable virtual screen and set the position to the upper left corner of
|
|
// logical screen
|
|
//
|
|
|
|
HwDeviceExtension->VirtualScreenEnable = TRUE;
|
|
HwDeviceExtension->VirtualScreenPosX = 0;
|
|
HwDeviceExtension->VirtualScreenPosY = 0;
|
|
|
|
//
|
|
// Change the logical width to use as a panning mode.
|
|
//
|
|
// Note: "wbytes" should not exceed 2040.
|
|
//
|
|
|
|
VideoPortWritePortUshort(
|
|
(PUSHORT)(HwDeviceExtension->IOAddress + CRTC_ADDRESS_PORT_COLOR),
|
|
(USHORT)(0x13 | ((pRequestedMode->wbytes/8) << 8)));
|
|
|
|
} /* endif */
|
|
} /* endif */
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
if (HwDeviceExtension->LCDEnable) {
|
|
VgaSetActiveDisplay(HwDeviceExtension, LCD_ENABLE | CRT_ENABLE);
|
|
} else {
|
|
VgaSetActiveDisplay(HwDeviceExtension, LCD_DISABLE | CRT_ENABLE);
|
|
} /* endif */
|
|
|
|
#endif
|
|
|
|
//
|
|
// 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);
|
|
|
|
//
|
|
// Update the location of the physical frame buffer within video memory.
|
|
//
|
|
|
|
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
|
SEQ_ADDRESS_PORT, pr30a);
|
|
|
|
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT) & 0x20) {
|
|
|
|
HwDeviceExtension->PhysicalFrameLength =
|
|
MemoryMaps[pRequestedMode->MemMap].MaxSize / 2;
|
|
|
|
} else {
|
|
|
|
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;
|
|
|
|
VgaZeroVideoMemory(HwDeviceExtension);
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
} /* endif */
|
|
|
|
videoModes->DriverSpecificAttributeFlags = 0;
|
|
if ((HwDeviceExtension->PanelType != NoLCD) &&
|
|
((HwDeviceExtension->PanelXResolution != videoModes->VisScreenWidth) ||
|
|
(HwDeviceExtension->PanelYResolution != videoModes->VisScreenHeight))) {
|
|
videoModes->DriverSpecificAttributeFlags |= CAPS_NEED_SW_POINTER;
|
|
} /* endif */
|
|
|
|
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 (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;
|
|
|
|
} /* endif */
|
|
|
|
ModeInformation->DriverSpecificAttributeFlags = 0;
|
|
if ((HwDeviceExtension->PanelType != NoLCD) &&
|
|
((HwDeviceExtension->PanelXResolution != ModeInformation->VisScreenWidth) ||
|
|
(HwDeviceExtension->PanelYResolution != ModeInformation->VisScreenHeight))) {
|
|
ModeInformation->DriverSpecificAttributeFlags |= CAPS_NEED_SW_POINTER;
|
|
} /* endif */
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
// The following code was added for clearing the screen using a hardware
|
|
// bitblt.
|
|
|
|
ULONG i;
|
|
ULONG SrcAddr, DstAddr;
|
|
USHORT Width, Height, lDeltaScan, Bpp;
|
|
PUCHAR IoBase = HwDeviceExtension->IOAddress;
|
|
PUCHAR ExtIoBase = HwDeviceExtension->ExtendedIOAddress;
|
|
|
|
SrcAddr = DstAddr = 0;
|
|
Width = HwDeviceExtension->CurrentMode->hres;
|
|
Height = HwDeviceExtension->CurrentMode->vres;
|
|
lDeltaScan = HwDeviceExtension->CurrentMode->wbytes;
|
|
Bpp = HwDeviceExtension->CurrentMode->bitsPerPlane;
|
|
|
|
VideoPortWritePortUshort((PUSHORT)ExtIoBase, 0x1001); // select BitBlt registers
|
|
// auto-increment disable
|
|
while (VideoPortReadPortUshort((PUSHORT)(ExtIoBase + 2)) & BLT_IN_PROG)
|
|
; // still in progress ?
|
|
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
(USHORT)(BLT_SRC_LO | SrcAddr & 0xFFF));
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
(USHORT)(BLT_SRC_HI | (SrcAddr >> 12) & 0x1FF));
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
(USHORT)(BLT_DST_LO | DstAddr & 0xFFF));
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
(USHORT)(BLT_DST_HI | (DstAddr >> 12) & 0x1FF));
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
(USHORT)(BLT_SIZE_X | Width*Bpp/8));
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
(USHORT)(BLT_SIZE_Y | Height));
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
(USHORT)(BLT_DELTA | lDeltaScan));
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
BLT_PLANE | 0xFF ); // enable all planes
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
BLT_ROPS | 0x000); // zero clear
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
BLT_CTRL2 | 0x02 ); // Do not interrupt when finish
|
|
VideoPortWritePortUshort((PUSHORT)(ExtIoBase + 2),
|
|
BLT_CTRL1 | 0x900 | ((TRUE) ? 0 : 0x400));
|
|
// direction = increase
|
|
// Start BitBlt
|
|
// Packed pixel mode
|
|
// src: rect, dst: rect
|
|
// src: screen, dst: screen
|
|
|
|
while (VideoPortReadPortUshort((PUSHORT)(ExtIoBase + 2)) & BLT_IN_PROG)
|
|
; // still in progress ?
|
|
|
|
//
|
|
// Clear CLUT registers
|
|
//
|
|
|
|
CurrClutBuffer->NumEntries = VIDEO_MAX_COLOR_REGISTER + 1;
|
|
CurrClutBuffer->FirstEntry = 0;
|
|
|
|
VideoPortWritePortUchar(IoBase + DAC_ADDRESS_WRITE_PORT, (UCHAR)0x00);
|
|
|
|
for (i = 0; i < VIDEO_MAX_COLOR_REGISTER + 1; i++) {
|
|
|
|
VideoPortWritePortUchar(IoBase + DAC_DATA_REG_PORT, 0x00); // Red
|
|
VideoPortWritePortUchar(IoBase + DAC_DATA_REG_PORT, 0x00); // Green
|
|
VideoPortWritePortUchar(IoBase + DAC_DATA_REG_PORT, 0x00); // Blue
|
|
|
|
CurrClutBuffer->LookupTable[i].RgbLong = (ULONG)0;
|
|
|
|
} /* endfor */
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
for (i = 0; i < NumVideoModes; i++) {
|
|
|
|
if (HwDeviceExtension->AdapterMemorySize >=
|
|
ModesVGA[i].numPlanes * ModesVGA[i].sbytes) {
|
|
|
|
ModesVGA[i].ValidMode = TRUE;
|
|
HwDeviceExtension->NumAvailableModes++;
|
|
|
|
}
|
|
|
|
//
|
|
// Older boards do not support 72HZ in 1024x768 modes.
|
|
// So disable those.
|
|
//
|
|
|
|
if ( (HwDeviceExtension->BoardID < WD90C31) &&
|
|
(ModesVGA[i].hres == 1024) &&
|
|
(ModesVGA[i].vres == 768) &&
|
|
(ModesVGA[i].Frequency == 72) &&
|
|
(ModesVGA[i].ValidMode) ) {
|
|
|
|
ModesVGA[i].ValidMode = FALSE;
|
|
HwDeviceExtension->NumAvailableModes--;
|
|
|
|
}
|
|
|
|
//
|
|
// Boards do not support different type of LCD modes.
|
|
// So disable those.
|
|
//
|
|
|
|
if ( !(HwDeviceExtension->PanelType & ModesVGA[i].LCDtype) &&
|
|
(ModesVGA[i].ValidMode) ) {
|
|
|
|
ModesVGA[i].ValidMode = FALSE;
|
|
HwDeviceExtension->NumAvailableModes--;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
#ifdef PPC
|
|
if (status != NO_ERROR) {
|
|
TurnOnLCD(HwDeviceExtension, TRUE);
|
|
} /* endif */
|
|
#endif
|
|
|
|
} else {
|
|
|
|
#ifdef PPC
|
|
if (status != NO_ERROR) {
|
|
TurnOnLCD(HwDeviceExtension, FALSE);
|
|
} /* endif */
|
|
#endif
|
|
|
|
DisableLCD(HwDeviceExtension);
|
|
|
|
} /* endif */
|
|
|
|
//
|
|
// Enable or Disable CRT output
|
|
//
|
|
|
|
if (ActiveDisplay & CRT_ENABLE) {
|
|
EnableCRT(HwDeviceExtension);
|
|
} else {
|
|
DisableCRT(HwDeviceExtension);
|
|
} /* endif */
|
|
|
|
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,
|
|
(UCHAR)(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,
|
|
(UCHAR)(VideoPortReadPortUchar(IoBase + GRAPH_DATA_PORT) & ~0x20));
|
|
|
|
//
|
|
// Enables LCD interface
|
|
//
|
|
|
|
VideoPortWritePortUchar(IoBase + CRTC_ADDRESS_PORT_COLOR, pr19);
|
|
VideoPortWritePortUchar(
|
|
IoBase + CRTC_DATA_PORT_COLOR,
|
|
(UCHAR)(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()
|
|
|
|
|
|
BOOLEAN
|
|
CRTDetect(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks if an external CRT is connected or not
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR IoBase = HwDeviceExtension->IOAddress;
|
|
UCHAR status;
|
|
|
|
//
|
|
// Enables internal RAMDAC
|
|
//
|
|
|
|
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + DAC_PIXEL_MASK_PORT, 0);
|
|
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT, pr58a);
|
|
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT, 0);
|
|
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT, 0x01);
|
|
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
|
|
(UCHAR)(VideoPortReadPortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT) & ~0x20));
|
|
|
|
//
|
|
// Wait until next vertical retrace interval
|
|
//
|
|
|
|
while (0 != (VideoPortReadPortUchar(IoBase + INPUT_STATUS_1_COLOR) & 0x08));
|
|
while (0 == (VideoPortReadPortUchar(IoBase + INPUT_STATUS_1_COLOR) & 0x08));
|
|
|
|
//
|
|
// Program index 0 of CLUT
|
|
//
|
|
// Note: It is assumed that DAC pel mask register is set to 0 so that DAC
|
|
// looks up only index 0.
|
|
//
|
|
|
|
VideoPortWritePortUchar(IoBase + DAC_ADDRESS_WRITE_PORT, 0);
|
|
VideoPortWritePortUchar(IoBase + DAC_DATA_REG_PORT, 0x04); // Red
|
|
VideoPortWritePortUchar(IoBase + DAC_DATA_REG_PORT, 0x12); // Green
|
|
VideoPortWritePortUchar(IoBase + DAC_DATA_REG_PORT, 0x04); // Blue
|
|
|
|
//
|
|
// Read DAC comparator status during the active video output
|
|
//
|
|
|
|
while (0 != (VideoPortReadPortUchar(IoBase + INPUT_STATUS_1_COLOR) & 0x01));
|
|
status = VideoPortReadPortUchar(IoBase + INPUT_STATUS_0_PORT);
|
|
|
|
HwDeviceExtension->CRTPresent = (status & 0x10) ? TRUE : FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
#ifdef PPC
|
|
VOID
|
|
TurnOnLCD(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
BOOLEAN PowerState
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine turns on/off LCD.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR PmIoBase = NULL;
|
|
BOOLEAN found = FALSE;
|
|
ULONG i;
|
|
PCI_SLOT_NUMBER slot;
|
|
PCI_COMMON_CONFIG PCIDeviceConfig;
|
|
VIDEO_ACCESS_RANGE pmadd = {0x00004100, 0x00000000, 2, 1, 1, 0};
|
|
|
|
slot.u.AsULONG = (ULONG)0;
|
|
|
|
//
|
|
// Locates the controller on the PCI bus, and configures it
|
|
//
|
|
|
|
for (i = 0; i < PCI_MAX_DEVICES; i++) {
|
|
|
|
slot.u.bits.DeviceNumber = i;
|
|
VideoPortGetBusData(HwDeviceExtension,
|
|
PCIConfiguration, // data type
|
|
slot.u.AsULONG, // slot number
|
|
&PCIDeviceConfig, // buffer
|
|
0, // offset
|
|
PCI_COMMON_HDR_LENGTH); // length
|
|
|
|
if ((PCIDeviceConfig.VendorID == 0x1014) &&
|
|
(PCIDeviceConfig.DeviceID == 0x001C)) {
|
|
|
|
PCIDeviceConfig.Command |= PCI_ENABLE_IO_SPACE;
|
|
PCIDeviceConfig.u.type0.BaseAddresses[0] = (ULONG)0x4100;
|
|
|
|
VideoPortSetBusData(HwDeviceExtension,
|
|
PCIConfiguration, // data type
|
|
slot.u.AsULONG, // slot number
|
|
&PCIDeviceConfig, // buffer
|
|
0, // offset
|
|
PCI_COMMON_HDR_LENGTH); // length
|
|
|
|
PmIoBase = VideoPortGetDeviceBase(HwDeviceExtension,
|
|
pmadd.RangeStart,
|
|
pmadd.RangeLength,
|
|
pmadd.RangeInIoSpace);
|
|
|
|
found = TRUE;
|
|
break;
|
|
} /* endif */
|
|
} /* endfor */
|
|
|
|
if (!found) {
|
|
return;
|
|
} /* endif */
|
|
|
|
//
|
|
// Turns on/off LCD
|
|
//
|
|
|
|
if (PowerState) {
|
|
|
|
VideoPortStallExecution(100 * 1000); // wait 100ms for panel protection
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x0C);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) | 0x02));
|
|
|
|
VideoPortStallExecution(5 * 1000); // wait 5ms for DC/DC converter
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x0C);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) | 0x0c));
|
|
|
|
VideoPortStallExecution(1);
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x00);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) & ~0x80));
|
|
|
|
VideoPortStallExecution(1);
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x0C);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) | 0x01));
|
|
|
|
} else {
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x0C);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) & ~0x01));
|
|
|
|
VideoPortStallExecution(1);
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x00);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) | 0x80));
|
|
|
|
VideoPortStallExecution(1);
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x0C);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) & ~0x0C));
|
|
|
|
VideoPortStallExecution(1);
|
|
|
|
VideoPortWritePortUchar(PmIoBase, 0x0C);
|
|
VideoPortWritePortUchar(
|
|
PmIoBase + 1,
|
|
(UCHAR)(VideoPortReadPortUchar(PmIoBase + 1) & ~0x02));
|
|
|
|
} /* endif */
|
|
|
|
VideoPortFreeDeviceBase(HwDeviceExtension,PmIoBase);
|
|
|
|
|
|
} // end TurnOnLCD()
|
|
#endif
|
|
|
|
|