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.
1866 lines
47 KiB
1866 lines
47 KiB
/*++
|
|
|
|
Copyright (c) 1990-1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
xga.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code that implements the XGA miniport driver.
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "dderror.h"
|
|
#include "devioctl.h"
|
|
#include "miniport.h"
|
|
|
|
#include "ntddvdeo.h"
|
|
#include "video.h"
|
|
#include "xga.h"
|
|
#include "xgaioctl.h"
|
|
|
|
#include "xgaloger.h"
|
|
|
|
|
|
//
|
|
// Function Prototypes
|
|
//
|
|
// Functions that start with 'Xga' are entry points for the OS port driver.
|
|
//
|
|
|
|
VP_STATUS
|
|
XgaFindAdapter(
|
|
PVOID HwDeviceExtension,
|
|
PVOID HwContext,
|
|
PWSTR ArgumentString,
|
|
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
|
|
PUCHAR Again
|
|
);
|
|
|
|
BOOLEAN
|
|
XgaInitialize(
|
|
PVOID HwDeviceExtension
|
|
);
|
|
|
|
BOOLEAN
|
|
XgaStartIO(
|
|
PVOID HwDeviceExtension,
|
|
PVIDEO_REQUEST_PACKET RequestPacket
|
|
);
|
|
|
|
BOOLEAN
|
|
XgaResetHW(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG Columns,
|
|
IN ULONG Rows
|
|
);
|
|
|
|
//
|
|
// Define device driver procedure prototypes.
|
|
//
|
|
|
|
VP_STATUS
|
|
XgaGetPosData(
|
|
PVOID HwDeviceExtension,
|
|
PVOID Context,
|
|
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
|
|
PVOID Identifier,
|
|
ULONG IdentifierLength,
|
|
PVOID ConfigurationData,
|
|
ULONG ConfigurationDataLength,
|
|
PVOID ComponentInformation,
|
|
ULONG ComponentInformationLength
|
|
);
|
|
|
|
VP_STATUS
|
|
XgaGetIsaData(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
PCM_MCA_POS_DATA PosData
|
|
);
|
|
|
|
ULONG
|
|
XgaFindXga(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
PCM_MCA_POS_DATA PosData
|
|
);
|
|
|
|
VP_STATUS
|
|
XgaSetMode(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
ULONG ModeNum
|
|
);
|
|
|
|
VP_STATUS
|
|
XgaGetBankSelectCode(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
PVIDEO_BANK_SELECT BankSelect,
|
|
ULONG BankSelectSize,
|
|
PULONG OutputSize
|
|
);
|
|
|
|
VP_STATUS
|
|
XgaGetRegistryParamaterCallback(
|
|
PVOID HwDeviceExtension,
|
|
PVOID Context,
|
|
PWSTR ValueName,
|
|
PVOID ValueData,
|
|
ULONG ValueLength
|
|
);
|
|
|
|
#if defined(ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE,DriverEntry)
|
|
#pragma alloc_text(PAGE,XgaFindAdapter)
|
|
#pragma alloc_text(PAGE,XgaInitialize)
|
|
#pragma alloc_text(PAGE,XgaStartIO)
|
|
#pragma alloc_text(PAGE,XgaGetPosData)
|
|
#pragma alloc_text(PAGE,XgaGetIsaData)
|
|
#pragma alloc_text(PAGE,XgaFindXga)
|
|
#pragma alloc_text(PAGE,XgaSetMode)
|
|
#pragma alloc_text(PAGE,XgaGetBankSelectCode)
|
|
#pragma alloc_text(PAGE,XgaGetRegistryParamaterCallback)
|
|
#endif
|
|
|
|
// XgaResetHW is not pageable
|
|
|
|
|
|
ULONG
|
|
DriverEntry (
|
|
PVOID Context1,
|
|
PVOID Context2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Installable driver initialization entry point.
|
|
This entry point is called directly by the I/O system.
|
|
|
|
Arguments:
|
|
|
|
Context1 - First context value passed by the operating system. This is
|
|
the value with which the miniport driver calls VideoPortInitialize().
|
|
|
|
Context2 - Second context value passed by the operating system. This is
|
|
the value with which the miniport driver calls VideoPortInitialize().
|
|
|
|
Return Value:
|
|
|
|
Status from VideoPortInitialize()
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
VIDEO_HW_INITIALIZATION_DATA hwInitData;
|
|
ULONG status;
|
|
ULONG initializationStatus;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Zero out structure.
|
|
//
|
|
|
|
VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
|
|
|
|
//
|
|
// Specify sizes of structure and extension.
|
|
//
|
|
|
|
hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
|
|
|
|
//
|
|
// Set entry points.
|
|
//
|
|
|
|
hwInitData.HwFindAdapter = XgaFindAdapter;
|
|
hwInitData.HwInitialize = XgaInitialize;
|
|
hwInitData.HwInterrupt = NULL;
|
|
hwInitData.HwStartIO = XgaStartIO;
|
|
hwInitData.HwResetHw = XgaResetHW;
|
|
|
|
//
|
|
// Determine the size we require for the device extension.
|
|
//
|
|
|
|
hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
|
|
|
|
//
|
|
// Always start with parameters for device0 in this case.
|
|
//
|
|
|
|
// hwInitData.StartingDeviceNumber = 0;
|
|
|
|
//
|
|
// This device only supports the internal bus type. So return the status
|
|
// value directly to the operating system.
|
|
//
|
|
|
|
hwInitData.AdapterInterfaceType = Isa;
|
|
|
|
initializationStatus = VideoPortInitialize(Context1,
|
|
Context2,
|
|
&hwInitData,
|
|
(PVOID)hwInitData.AdapterInterfaceType);
|
|
|
|
hwInitData.AdapterInterfaceType = Eisa;
|
|
|
|
status = VideoPortInitialize(Context1,
|
|
Context2,
|
|
&hwInitData,
|
|
(PVOID)hwInitData.AdapterInterfaceType);
|
|
|
|
if (initializationStatus > status) {
|
|
initializationStatus = status;
|
|
}
|
|
|
|
hwInitData.AdapterInterfaceType = MicroChannel;
|
|
|
|
status = VideoPortInitialize(Context1,
|
|
Context2,
|
|
&hwInitData,
|
|
(PVOID)hwInitData.AdapterInterfaceType);
|
|
|
|
if (initializationStatus > status) {
|
|
initializationStatus = status;
|
|
}
|
|
|
|
return initializationStatus;
|
|
|
|
} // end DriverEntry()
|
|
|
|
VP_STATUS
|
|
XgaFindAdapter(
|
|
PVOID HwDeviceExtension,
|
|
PVOID HwContext,
|
|
PWSTR ArgumentString,
|
|
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
|
|
PUCHAR Again
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called to determine if the adapter for this driver
|
|
is present in the system.
|
|
If it is present, the function fills out some information describing
|
|
the adapter.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Supplies the miniport driver's adapter storage. This
|
|
storage is initialized to zero before this call.
|
|
|
|
HwContext - Supplies the context value which was passed to
|
|
VideoPortInitialize().
|
|
|
|
ArgumentString - Suuplies a NULL terminated ASCII string. This string
|
|
originates from the user.
|
|
|
|
ConfigInfo - Returns the configuration information structure which is
|
|
filled by the miniport driver. This structure is initialized with
|
|
any knwon configuration information (such as SystemIoBusNumber) by
|
|
the port driver. Where possible, drivers should have one set of
|
|
defaults which do not require any supplied configuration information.
|
|
|
|
Again - Indicates if the miniport driver wants the port driver to call
|
|
its VIDEO_HW_FIND_ADAPTER function again with a new device extension
|
|
and the same config info. This is used by the miniport drivers which
|
|
can search for several adapters on a bus.
|
|
|
|
Return Value:
|
|
|
|
This routine must return:
|
|
|
|
NO_ERROR - Indicates a host adapter was found and the
|
|
configuration information was successfully determined.
|
|
|
|
ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
|
|
error obtaining the configuration information. If possible an error
|
|
should be logged.
|
|
|
|
ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
|
|
supplied configuration information.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Number of entries in the access range structure passed to the port driver.
|
|
//
|
|
|
|
#define NUM_XGA_ACCESS_RANGES 6
|
|
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
CM_MCA_POS_DATA posData;
|
|
ULONG ioAddress;
|
|
VP_STATUS status;
|
|
VIDEO_ACCESS_RANGE accessRange[NUM_XGA_ACCESS_RANGES];
|
|
PHYSICAL_ADDRESS A0000PhysicalAddress;
|
|
PHYSICAL_ADDRESS passThroughPort;
|
|
|
|
A0000PhysicalAddress.LowPart = 0x000A0000;
|
|
A0000PhysicalAddress.HighPart = 0x00000000;
|
|
|
|
passThroughPort.LowPart = 0x000003C3;
|
|
passThroughPort.HighPart = 0x00000000;
|
|
|
|
//
|
|
// Indicate we do not wish to be called over
|
|
//
|
|
|
|
*Again = 0;
|
|
|
|
//
|
|
// Make sure the size of the structure is at least as large as what we
|
|
// are expecting (check version of the config info structure).
|
|
//
|
|
|
|
if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) {
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Reset the Slot number being examined to zero if we are processing
|
|
// a new bus number.
|
|
//
|
|
|
|
if (BusNumber != (LONG)ConfigInfo->SystemIoBusNumber) {
|
|
|
|
BusNumber = ConfigInfo->SystemIoBusNumber;
|
|
XgaSlot = 0;
|
|
|
|
}
|
|
|
|
//
|
|
// On the Microchanel machine, we can use the POS information, which is
|
|
// really nice.
|
|
// However, on ISA/EISA, we have to call the equivalent of the POS
|
|
// registers (same addresses) and the card will fake it and return the
|
|
// configuration information
|
|
//
|
|
|
|
if ((ULONG)HwContext == MicroChannel) {
|
|
|
|
//
|
|
// This picks up the POS registers.
|
|
//
|
|
|
|
if (NO_ERROR != VideoPortGetDeviceData(hwDeviceExtension,
|
|
VpBusData,
|
|
XgaGetPosData,
|
|
&posData)) {
|
|
|
|
VideoDebugPrint((2, "Xga: GetDeviceData returned error - probably no XGAs\n"));
|
|
|
|
return ERROR_DEV_NOT_EXIST;
|
|
}
|
|
|
|
//
|
|
// Since we got the data properly, make sure we get called again to find
|
|
// the next XGA adapter.
|
|
//
|
|
// Only Microchannels have the possibility of multiple XGAs ?
|
|
//
|
|
|
|
*Again = 1;
|
|
|
|
} else {
|
|
|
|
//
|
|
// on non-microchannel, we have to run as a banked frame buffer
|
|
//
|
|
|
|
framebufMode = TRUE;
|
|
|
|
//
|
|
// Get fake POS info
|
|
//
|
|
|
|
if (NO_ERROR != XgaGetIsaData(hwDeviceExtension,
|
|
&posData)) {
|
|
|
|
VideoDebugPrint((2, "Xga: GetIsaData returned error - probably no XGAs\n"));
|
|
|
|
return ERROR_DEV_NOT_EXIST;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine the XGA registers by munging the POS register data.
|
|
//
|
|
|
|
ioAddress = (posData.PosData1 &0x0E) >> 1;
|
|
|
|
hwDeviceExtension->PhysicalRomBaseAddress.LowPart =
|
|
(((posData.PosData1 & 0xF0) >> 4) * 0x2000) + 0xC0000;
|
|
hwDeviceExtension->PhysicalRomBaseAddress.HighPart = 0x00000000;
|
|
|
|
hwDeviceExtension->PhysicalIoRegBaseAddress.LowPart = 0x2100 +
|
|
(ioAddress << 4);
|
|
hwDeviceExtension->PhysicalIoRegBaseAddress.HighPart = 0x00000000;
|
|
|
|
//
|
|
// Choose a size of 1 MEG for video memory as a default
|
|
//
|
|
|
|
//
|
|
// Find the virtual address of the frame buffer. Get the 4Meg aperture
|
|
// if it is available, otherwise take the 1MEG.
|
|
//
|
|
|
|
if (posData.PosData3 & 0x01) {
|
|
|
|
VideoDebugPrint((1, "Xga: using the 4 MEG Aperture\n"));
|
|
|
|
hwDeviceExtension->FrameBufferLength = 0x00100000;
|
|
hwDeviceExtension->PhysicalVideoMemoryLength = 0x00400000;
|
|
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.HighPart = 0x00000000;
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.LowPart =
|
|
((posData.PosData3 &0xFE) << 24) | (ioAddress << 22);
|
|
|
|
} else {
|
|
|
|
VideoDebugPrint((1, "Xga: trying the 1 MEG aperture\n"));
|
|
|
|
hwDeviceExtension->FrameBufferLength = 0x00100000;
|
|
hwDeviceExtension->PhysicalVideoMemoryLength = 0x00100000;
|
|
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.HighPart = 0x00000000;
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.LowPart =
|
|
(posData.PosData4 &0x0F) << 20;
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// If none of these apertures are open, (64K aperture) then fail.
|
|
// 1 MEG aperture is disabled if the base is 0
|
|
//
|
|
|
|
if (!hwDeviceExtension->PhysicalVideoMemoryAddress.LowPart) {
|
|
|
|
VideoDebugPrint((1, "Xga: 64K aperture\n"));
|
|
|
|
// VideoPortLogError(hwDeviceExtension,
|
|
// NULL,
|
|
// XGA_WRONG_APERTURE,
|
|
// __LINE__);
|
|
//
|
|
// return ERROR_INVALID_PARAMETER;
|
|
|
|
//
|
|
// We now support the XGA with the 64K aperture by running it with the
|
|
// vga256.dll
|
|
//
|
|
|
|
framebufMode = TRUE;
|
|
|
|
hwDeviceExtension->FrameBufferLength = 0x00100000;
|
|
hwDeviceExtension->PhysicalVideoMemoryLength = 0x00010000;
|
|
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.HighPart = 0x00000000;
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.LowPart = 0x000A0000;
|
|
}
|
|
|
|
//
|
|
// Get the address of the Co processor registers.
|
|
//
|
|
|
|
hwDeviceExtension->PhysicalCoProcessorAddress.LowPart = 0x80 * ioAddress
|
|
+ 0x1C00 + hwDeviceExtension->PhysicalRomBaseAddress.LowPart;
|
|
hwDeviceExtension->PhysicalCoProcessorAddress.HighPart = 0x00000000;
|
|
|
|
//
|
|
// Save the data for access ranges
|
|
//
|
|
|
|
//
|
|
// Io Ports
|
|
//
|
|
|
|
accessRange[0].RangeStart = hwDeviceExtension->PhysicalIoRegBaseAddress;
|
|
accessRange[0].RangeLength = XGA_IO_REGS_SIZE;
|
|
accessRange[0].RangeInIoSpace = TRUE;
|
|
accessRange[0].RangeVisible = TRUE;
|
|
accessRange[0].RangeShareable = FALSE;
|
|
|
|
//
|
|
// Video Memory
|
|
//
|
|
|
|
accessRange[1].RangeStart = hwDeviceExtension->PhysicalVideoMemoryAddress;
|
|
accessRange[1].RangeLength = hwDeviceExtension->PhysicalVideoMemoryLength;
|
|
accessRange[1].RangeInIoSpace = FALSE;
|
|
accessRange[1].RangeVisible = TRUE;
|
|
accessRange[1].RangeShareable = framebufMode ? TRUE : FALSE;
|
|
|
|
//
|
|
// ROM Location
|
|
//
|
|
|
|
accessRange[2].RangeStart = hwDeviceExtension->PhysicalRomBaseAddress;
|
|
accessRange[2].RangeLength = XGA_ROM_SIZE;
|
|
accessRange[2].RangeInIoSpace = FALSE;
|
|
accessRange[2].RangeVisible = TRUE;
|
|
accessRange[2].RangeShareable = FALSE;
|
|
|
|
//
|
|
// Co-Processor Location
|
|
//
|
|
|
|
accessRange[3].RangeStart = hwDeviceExtension->PhysicalCoProcessorAddress;
|
|
accessRange[3].RangeLength = XGA_CO_PROCESSOR_REGS_SIZE;
|
|
accessRange[3].RangeInIoSpace = FALSE;
|
|
accessRange[3].RangeVisible = TRUE;
|
|
accessRange[3].RangeShareable = FALSE;
|
|
|
|
//
|
|
// Resources shared with the VGA
|
|
//
|
|
|
|
//
|
|
// Io Ports
|
|
//
|
|
|
|
accessRange[4].RangeStart = passThroughPort;
|
|
accessRange[4].RangeLength = 0x00000001;
|
|
accessRange[4].RangeInIoSpace = TRUE;
|
|
accessRange[4].RangeVisible = FALSE;
|
|
accessRange[4].RangeShareable = TRUE;
|
|
|
|
//
|
|
// Video Memory
|
|
//
|
|
|
|
accessRange[5].RangeStart = A0000PhysicalAddress;
|
|
accessRange[5].RangeLength = 0x00010000;
|
|
accessRange[5].RangeInIoSpace = FALSE;
|
|
accessRange[5].RangeVisible = FALSE;
|
|
accessRange[5].RangeShareable = TRUE;
|
|
|
|
//
|
|
// Check to see if there is a hardware resource conflict.
|
|
//
|
|
|
|
status = VideoPortVerifyAccessRanges(HwDeviceExtension,
|
|
NUM_XGA_ACCESS_RANGES,
|
|
accessRange);
|
|
|
|
if (status != NO_ERROR) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Clear out the Emulator entries and the state size since this driver
|
|
// does not support them.
|
|
//
|
|
|
|
ConfigInfo->NumEmulatorAccessEntries = 0;
|
|
ConfigInfo->EmulatorAccessEntries = NULL;
|
|
ConfigInfo->EmulatorAccessEntriesContext = 0;
|
|
|
|
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x00000000;
|
|
ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
|
|
ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00000000;
|
|
|
|
ConfigInfo->HardwareStateSize = 0;
|
|
|
|
//
|
|
// Map in the memory at A0000 so we can test the card for the amount of
|
|
// memory afterwards.
|
|
//
|
|
|
|
if ( ( hwDeviceExtension->A0000MemoryAddress =
|
|
VideoPortGetDeviceBase(hwDeviceExtension,
|
|
A0000PhysicalAddress,
|
|
0x00010000,
|
|
FALSE)) == NULL) {
|
|
|
|
VideoDebugPrint((2, "XgaFindAdapter - Fail to get A0000 aperture address\n"));
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Map in the IO registers so we can access them.
|
|
//
|
|
|
|
if ( ( hwDeviceExtension->IoRegBaseAddress = (ULONG)
|
|
VideoPortGetDeviceBase(hwDeviceExtension,
|
|
hwDeviceExtension->PhysicalIoRegBaseAddress,
|
|
XGA_IO_REGS_SIZE,
|
|
TRUE)) == 0) {
|
|
|
|
VideoDebugPrint((2, "XgaFindAdapter - Fail to get io register addresses\n"));
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Map in the pass-throught port.
|
|
//
|
|
|
|
if ( ( hwDeviceExtension->PassThroughPort =
|
|
VideoPortGetDeviceBase(hwDeviceExtension,
|
|
passThroughPort,
|
|
1,
|
|
TRUE)) == 0) {
|
|
|
|
VideoDebugPrint((2, "XgaFindAdapter - Fail to get io register addresses\n"));
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
//
|
|
// Everything is successful. Put some information in the registry.
|
|
//
|
|
|
|
{
|
|
PWSTR pwszChip;
|
|
ULONG cbChip;
|
|
|
|
if (hwDeviceExtension->BoardType == XGA_TYPE_1) {
|
|
|
|
pwszChip = L"XGA 1";
|
|
cbChip = sizeof(L"XGA 1");
|
|
|
|
} else if (hwDeviceExtension->BoardType == XGA_TYPE_2) {
|
|
|
|
pwszChip = L"XGA 2";
|
|
cbChip = sizeof(L"XGA 2");
|
|
|
|
} else {
|
|
|
|
pwszChip = L"bad XGA type";
|
|
cbChip = sizeof(L"bad XGA type");
|
|
|
|
}
|
|
|
|
VideoPortSetRegistryParameters(hwDeviceExtension,
|
|
L"HardwareInformation.ChipType",
|
|
pwszChip,
|
|
cbChip);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Indicate a successful completion status.
|
|
//
|
|
|
|
return NO_ERROR;
|
|
|
|
} // end XgaFindAdapter()
|
|
|
|
|
|
VP_STATUS
|
|
XgaGetPosData(
|
|
PVOID HwDeviceExtension,
|
|
PVOID Context,
|
|
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
|
|
PVOID Identifier,
|
|
ULONG IdentifierLength,
|
|
PVOID ConfigurationData,
|
|
ULONG ConfigurationDataLength,
|
|
PVOID ComponentInformation,
|
|
ULONG ComponentInformationLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback for the GetDeviceData function.
|
|
This routine will scan for an XGA adapter, and if it finds one, will
|
|
save the POS information in the device extension so it can be further
|
|
processed in the FindAdapter() routine.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the miniport drivers device extension.
|
|
|
|
Context - Context value passed to the VideoPortGetDeviceData function.
|
|
|
|
DeviceDataType - The type of data that was requested in
|
|
VideoPortGetDeviceData.
|
|
|
|
Identifier - Pointer to a string that contains the name of the device,
|
|
as setup by the ROM or ntdetect.
|
|
|
|
IdentifierLength - Length of the Identifier string.
|
|
|
|
ConfigurationData - Pointer to the configuration data for the device or
|
|
BUS.
|
|
|
|
ConfigurationDataLength - Length of the data in the configurationData
|
|
field.
|
|
|
|
ComponentInformation - Undefined.
|
|
|
|
ComponentInformationLength - Undefined.
|
|
|
|
Return Value:
|
|
|
|
Returns NO_ERROR if the function completed properly.
|
|
Returns ERROR_DEV_NOT_EXIST if we did not find the device.
|
|
Returns ERROR_INVALID_PARAMETER otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
USHORT adapterId;
|
|
BOOLEAN found = FALSE;
|
|
PCM_MCA_POS_DATA posData = Context;
|
|
|
|
//
|
|
// Find the XGA.
|
|
// Loop through all the POS data in the PosData array
|
|
//
|
|
|
|
while ((XgaSlot + 1) * sizeof(CM_MCA_POS_DATA) <= ConfigurationDataLength) {
|
|
|
|
adapterId = *((PUSHORT)((PCM_MCA_POS_DATA)ConfigurationData + XgaSlot));
|
|
|
|
VideoDebugPrint((3, "PosAdapterId for slot %d is %x \n", XgaSlot,
|
|
adapterId));
|
|
|
|
switch ( adapterId ) {
|
|
|
|
case 0x8FDB:
|
|
|
|
hwDeviceExtension->BoardType = XGA_TYPE_1;
|
|
|
|
found = TRUE;
|
|
break;
|
|
|
|
case 0x8FDA:
|
|
|
|
hwDeviceExtension->BoardType = XGA_TYPE_2;
|
|
|
|
found = TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// Go to the next slot.
|
|
//
|
|
|
|
XgaSlot++;
|
|
|
|
//
|
|
// We have found an XGA adapter. Save the data in the device extension
|
|
// so we can process it further.
|
|
//
|
|
|
|
if (found) {
|
|
|
|
*posData = *((PCM_MCA_POS_DATA)ConfigurationData + XgaSlot - 1);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return ERROR_DEV_NOT_EXIST;
|
|
|
|
}
|
|
|
|
VP_STATUS
|
|
XgaGetIsaData(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
PCM_MCA_POS_DATA PosData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the XGA configuration information from an ISA system.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Supplies a pointer to the miniport's device extension.
|
|
|
|
PosData - Pointer to a buffer containing the POS information for the
|
|
device if it was found.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR if the XGA device was found.
|
|
ERROR_DEV_NOT_EXIST otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
VIDEO_ACCESS_RANGE accessRange[2];
|
|
VP_STATUS status;
|
|
USHORT adapterId = 0;
|
|
UCHAR i;
|
|
|
|
//
|
|
// Temporary Access ranges.
|
|
// These will be deleted later on since we do not really own them ...
|
|
//
|
|
|
|
accessRange[0].RangeStart.LowPart = POS_SELECT_PORT;
|
|
accessRange[0].RangeStart.HighPart = 0x0;
|
|
accessRange[0].RangeLength = 1;
|
|
accessRange[0].RangeInIoSpace = TRUE;
|
|
accessRange[0].RangeVisible = FALSE;
|
|
accessRange[0].RangeShareable = TRUE;
|
|
|
|
accessRange[1].RangeStart.LowPart = POS_DATA_BASE;
|
|
accessRange[1].RangeStart.HighPart = 0x0;
|
|
accessRange[1].RangeLength = 6;
|
|
accessRange[1].RangeInIoSpace = TRUE;
|
|
accessRange[1].RangeVisible = FALSE;
|
|
accessRange[1].RangeShareable = TRUE;
|
|
|
|
//
|
|
// Check to see if there is a hardware resource conflict.
|
|
//
|
|
|
|
status = VideoPortVerifyAccessRanges(HwDeviceExtension,
|
|
2,
|
|
accessRange);
|
|
|
|
if (status != NO_ERROR) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
//
|
|
// Go through the 8 slot numbers trying to find an XGA.
|
|
//
|
|
|
|
status = ERROR_DEV_NOT_EXIST;
|
|
|
|
for (i = 0; i < POS_MAX_SLOTS; i++) {
|
|
|
|
VideoPortWritePortUchar((PUCHAR) POS_SELECT_PORT,
|
|
(UCHAR) (POS_SELECT_ON | i));
|
|
|
|
adapterId = VideoPortReadPortUchar((PUCHAR) (POS_DATA_BASE + 0));
|
|
adapterId |= VideoPortReadPortUchar((PUCHAR) (POS_DATA_BASE + 1)) << 8;
|
|
|
|
if (adapterId == 0x8FDB) {
|
|
|
|
HwDeviceExtension->BoardType = XGA_TYPE_1;
|
|
status = NO_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (adapterId == 0x8FDA) {
|
|
|
|
HwDeviceExtension->BoardType = XGA_TYPE_2;
|
|
status = NO_ERROR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
VideoPortWritePortUchar((PUCHAR) POS_SELECT_PORT,
|
|
(UCHAR) (POS_SELECT_OFF | i));
|
|
}
|
|
|
|
if (status == NO_ERROR) {
|
|
|
|
PosData->AdapterId = adapterId;
|
|
PosData->PosData1 = VideoPortReadPortUchar((PUCHAR)(POS_DATA_BASE + 2));
|
|
PosData->PosData2 = VideoPortReadPortUchar((PUCHAR)(POS_DATA_BASE + 3));
|
|
PosData->PosData3 = VideoPortReadPortUchar((PUCHAR)(POS_DATA_BASE + 4));
|
|
PosData->PosData4 = VideoPortReadPortUchar((PUCHAR)(POS_DATA_BASE + 5));
|
|
|
|
VideoPortWritePortUchar((PUCHAR) POS_SELECT_PORT,
|
|
(UCHAR) (POS_SELECT_OFF | i));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
XgaInitialize(
|
|
PVOID HwDeviceExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does one time initialization of the device.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Supplies a pointer to the miniport's device extension.
|
|
|
|
Return Value:
|
|
|
|
|
|
Always returns TRUE since this routine can never fail.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
volatile PUCHAR videoMemory;
|
|
UCHAR testValue = 0xA5;
|
|
ULONG i;
|
|
ULONG color;
|
|
|
|
videoMemory = hwDeviceExtension->A0000MemoryAddress;
|
|
|
|
//
|
|
// Disable interrupts on the card since they will not be used
|
|
//
|
|
|
|
VideoPortWritePortUchar(
|
|
(PUCHAR) (hwDeviceExtension->IoRegBaseAddress | INT_ENABLE_REG), 0x00);
|
|
|
|
//
|
|
// Blank the palette so we get a black screen.
|
|
//
|
|
|
|
VideoPortWritePortUchar(
|
|
(PUCHAR) (hwDeviceExtension->IoRegBaseAddress | INDEX_REG), 0x64);
|
|
|
|
VideoPortWritePortUchar(
|
|
(PUCHAR) (hwDeviceExtension->IoRegBaseAddress | DATA_IN_REG), 0x00);
|
|
|
|
//
|
|
// Put the adapter in a temporary Extended Graphics Mode, set up video
|
|
// memory at A0000, put the aperture at 768 K higher and try to access
|
|
// it to determine how much memory is present.
|
|
//
|
|
|
|
VideoPortWritePortUchar(
|
|
(PUCHAR) (hwDeviceExtension->IoRegBaseAddress | OP_MODE_REG), 0x04);
|
|
|
|
VideoPortWritePortUchar(
|
|
(PUCHAR) (hwDeviceExtension->IoRegBaseAddress | APP_CTL_REG), 0x01);
|
|
|
|
VideoPortWritePortUchar(
|
|
(PUCHAR) (hwDeviceExtension->IoRegBaseAddress | APP_INDEX_REG), 0x0C);
|
|
|
|
//
|
|
// To test if memory is present, use a test value (make sure the same
|
|
// value is not currently stored in video memory, otherwise change it),
|
|
// store it in video memory, and read it back. If the value is identical
|
|
// to the value we stored then there must be memory present at that
|
|
// location (which, in this case, means we have 1 MEG of Video RAM).
|
|
//
|
|
|
|
if (*videoMemory == testValue) {
|
|
|
|
testValue >>= 1;
|
|
|
|
}
|
|
|
|
*videoMemory = testValue;
|
|
|
|
if (*videoMemory == testValue) {
|
|
|
|
hwDeviceExtension->FrameBufferLength = 0x00100000;
|
|
|
|
} else {
|
|
|
|
hwDeviceExtension->FrameBufferLength = 0x00080000;
|
|
|
|
}
|
|
|
|
VideoDebugPrint((2, "XgaInitialize\n The amount of memory on the card is %d K\n",
|
|
hwDeviceExtension->FrameBufferLength >> 10));
|
|
|
|
//
|
|
// hwDeviceExtension->FrameBufferLength contains the amount of memory
|
|
// on the device. Lets write this information into the registry.
|
|
//
|
|
// This value is in bytes, which is what I believe we want.
|
|
//
|
|
|
|
VideoPortSetRegistryParameters(hwDeviceExtension,
|
|
L"HardwareInformation.MemorySize",
|
|
&hwDeviceExtension->FrameBufferLength,
|
|
sizeof(ULONG));
|
|
|
|
//
|
|
// For now, we only support color devices
|
|
//
|
|
|
|
hwDeviceExtension->Color = TRUE;
|
|
|
|
//
|
|
// Now compute the number of available modes based on the infromation
|
|
// we found out.
|
|
//
|
|
|
|
hwDeviceExtension->NumAvailableModes = 0;
|
|
|
|
for (i = 0; i < XgaNumModes; i++) {
|
|
|
|
XgaModes[i].modeInformation.ModeIndex = i;
|
|
|
|
//
|
|
// For framebuffer mode, we must stretch scan lines to 1024.
|
|
// This means 800x600 requires 1 MEG.
|
|
//
|
|
|
|
if (framebufMode) {
|
|
|
|
if (XgaModes[i].modeInformation.ScreenStride > 1024) {
|
|
|
|
XgaModes[i].modeInformation.ScreenStride = 2048;
|
|
|
|
} else {
|
|
|
|
XgaModes[i].modeInformation.ScreenStride = 1024;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the right amount of memory and the right board type is present ...
|
|
//
|
|
|
|
if (XgaModes[i].modeInformation.ScreenStride *
|
|
XgaModes[i].modeInformation.VisScreenHeight <=
|
|
hwDeviceExtension->FrameBufferLength) {
|
|
|
|
//
|
|
// Check we have the right type of board.
|
|
//
|
|
|
|
if ( (XgaModes[i].Xga1Mode &&
|
|
(hwDeviceExtension->BoardType & XGA_TYPE_1)) ||
|
|
(XgaModes[i].Xga2Mode &&
|
|
(hwDeviceExtension->BoardType & XGA_TYPE_2)) ) {
|
|
|
|
color = XgaModes[i].modeInformation.AttributeFlags &
|
|
VIDEO_MODE_COLOR;
|
|
|
|
//
|
|
// check that both the mode and what we support is the same
|
|
// in terms of color.
|
|
//
|
|
|
|
if ( (color && (ULONG)hwDeviceExtension->Color) || // color
|
|
(color == (ULONG)hwDeviceExtension->Color) ) { // monochrome
|
|
|
|
hwDeviceExtension->Valid[i] = TRUE;
|
|
hwDeviceExtension->NumAvailableModes++;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VideoPortGetRegistryParameters(hwDeviceExtension,
|
|
L"Monitor",
|
|
TRUE,
|
|
XgaGetRegistryParamaterCallback,
|
|
NULL);
|
|
|
|
//
|
|
// Make sure we leave the hardware in a state where int10 from vga will
|
|
// work. This is necessary for detection where only Initialize will
|
|
// be called, without a setmode\resetdevice being done afterwards.
|
|
//
|
|
|
|
XgaResetHW(HwDeviceExtension, 0, 0);
|
|
|
|
return TRUE;
|
|
|
|
} // end XgaInitialize()
|
|
|
|
|
|
VP_STATUS
|
|
XgaGetRegistryParamaterCallback(
|
|
PVOID HwDeviceExtension,
|
|
PVOID Context,
|
|
PWSTR ValueName,
|
|
PVOID ValueData,
|
|
ULONG ValueLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback routine to process the information coming back from the registry.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|
|
|
Context - Context parameter passed to the callback routine.
|
|
|
|
ValueName - Pointer to the name of the requested data field.
|
|
|
|
ValueData - Pointer to a buffer containing the information.
|
|
|
|
ValueLength - Size of the data.
|
|
|
|
Return Value:
|
|
|
|
|
|
Environment:
|
|
|
|
Can only be called During initialization.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
VideoDebugPrint((3, "In the GetRegistryParameters callback routine\n"));
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
XgaStartIO(
|
|
PVOID HwDeviceExtension,
|
|
PVIDEO_REQUEST_PACKET RequestPacket
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the main execution routine for the miniport driver. It
|
|
acceptss a Video Request Packet, performs the request, and then returns
|
|
with the appropriate status.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Supplies a pointer to the miniport's device extension.
|
|
|
|
RequestPacket - Pointer to the video request packet. This structure
|
|
contains all the parameters passed to the VideoIoControl function.
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
VP_STATUS status;
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
|
|
PVIDEO_MEMORY_INFORMATION memoryInformation;
|
|
PVIDEO_MODE_INFORMATION modeInformation;
|
|
ULONG inIoSpace;
|
|
|
|
PVIDEO_CLUT clutBuffer;
|
|
PVIDEO_CLUTDATA pClutData;
|
|
|
|
ULONG i;
|
|
ULONG length;
|
|
PHYSICAL_ADDRESS physicalAddress;
|
|
ULONG offset;
|
|
|
|
|
|
//
|
|
// Switch on the IoContolCode in the RequestPacket. It indicates which
|
|
// function must be performed by the driver.
|
|
//
|
|
|
|
switch (RequestPacket->IoControlCode) {
|
|
|
|
|
|
case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - MapVideoMemory\n"));
|
|
|
|
if ( (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
sizeof(VIDEO_MEMORY_INFORMATION))) ||
|
|
(RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
|
|
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
memoryInformation = RequestPacket->OutputBuffer;
|
|
|
|
memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
|
|
(RequestPacket->InputBuffer))->RequestedVirtualAddress;
|
|
|
|
memoryInformation->VideoRamLength =
|
|
hwDeviceExtension->PhysicalVideoMemoryLength;
|
|
|
|
inIoSpace = 0;
|
|
|
|
status = VideoPortMapMemory(hwDeviceExtension,
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress,
|
|
&(memoryInformation->VideoRamLength),
|
|
&inIoSpace,
|
|
&(memoryInformation->VideoRamBase));
|
|
|
|
//
|
|
// The frame buffer and virtual memory and equivalent in this
|
|
// case.
|
|
//
|
|
|
|
memoryInformation->FrameBufferBase =
|
|
memoryInformation->VideoRamBase;
|
|
|
|
memoryInformation->FrameBufferLength =
|
|
XgaModes[hwDeviceExtension->CurrentMode].modeInformation.VisScreenHeight *
|
|
XgaModes[hwDeviceExtension->CurrentMode].modeInformation.ScreenStride;
|
|
|
|
VideoDebugPrint((3, "Xga IOCLT_MAP_MEMORY\n physical = %x\n \
|
|
virtual = %x\n length = %x\n framebase = %x\n frameLength = %x\n",
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.LowPart,
|
|
memoryInformation->VideoRamBase,
|
|
memoryInformation->VideoRamLength,
|
|
memoryInformation->FrameBufferBase,
|
|
memoryInformation->FrameBufferLength));
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - UnMapVideoMemory\n"));
|
|
|
|
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) {
|
|
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
status = VideoPortUnmapMemory(hwDeviceExtension,
|
|
((PVIDEO_MEMORY)
|
|
(RequestPacket->InputBuffer))->
|
|
RequestedVirtualAddress,
|
|
0);
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - QueryNumberAvaialbleModes\n"));
|
|
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
sizeof(VIDEO_NUM_MODES)) ) {
|
|
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
} else {
|
|
|
|
((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes =
|
|
hwDeviceExtension->NumAvailableModes;
|
|
((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength =
|
|
sizeof(VIDEO_MODE_INFORMATION);
|
|
|
|
status = NO_ERROR;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_QUERY_AVAIL_MODES:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - QueryAvailableModes\n"));
|
|
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
hwDeviceExtension->NumAvailableModes *
|
|
sizeof(VIDEO_MODE_INFORMATION)) ) {
|
|
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
} else {
|
|
|
|
modeInformation = RequestPacket->OutputBuffer;
|
|
|
|
for (i = 0; i < XgaNumModes; i++) {
|
|
|
|
if (hwDeviceExtension->Valid[i]) {
|
|
|
|
*modeInformation = XgaModes[i].modeInformation;
|
|
modeInformation++;
|
|
|
|
}
|
|
}
|
|
|
|
status = NO_ERROR;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_QUERY_CURRENT_MODE:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - QueryCurrentMode\n"));
|
|
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
sizeof(VIDEO_MODE_INFORMATION)) ) {
|
|
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
} else {
|
|
|
|
*((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer) =
|
|
XgaModes[hwDeviceExtension->CurrentMode].modeInformation;
|
|
|
|
status = NO_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_SET_CURRENT_MODE:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - SetCurrentMode\n"));
|
|
|
|
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) {
|
|
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
} else {
|
|
|
|
status = XgaSetMode(hwDeviceExtension,
|
|
((PVIDEO_MODE)RequestPacket->InputBuffer)->
|
|
RequestedMode);
|
|
|
|
if (status == NO_ERROR) {
|
|
|
|
if (framebufMode) {
|
|
|
|
//
|
|
// If we are in framebuf mode, which means we
|
|
// are running in 64K,
|
|
// then switch to VGA decode
|
|
//
|
|
|
|
XGAOUT(APP_CTL_REG, 0x1);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_SET_COLOR_REGISTERS:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - SetColorRegs\n"));
|
|
|
|
clutBuffer = RequestPacket->InputBuffer;
|
|
|
|
/* Load simple 16 entry palette */
|
|
|
|
XGAIDXOUT(INDEX_REG, 0x66, 0x0);
|
|
|
|
/* Start at beginning of palette */
|
|
|
|
XGAIDXOUT(INDEX_REG, 0x60, clutBuffer->FirstEntry);
|
|
XGAIDXOUT(INDEX_REG, 0x61, 0x0);
|
|
|
|
|
|
for ( i = 0; i < clutBuffer->NumEntries; i++ ) {
|
|
|
|
pClutData = &clutBuffer->LookupTable[i].RgbArray;
|
|
|
|
XGAOUT(INDEX_REG, 0x65);
|
|
XGAOUT(0x0B, pClutData->Red);
|
|
|
|
XGAOUT(INDEX_REG, 0x65);
|
|
XGAOUT(0x0B, pClutData->Green);
|
|
|
|
XGAOUT(INDEX_REG, 0x65);
|
|
XGAOUT(0x0B, pClutData->Blue);
|
|
}
|
|
|
|
status = NO_ERROR;
|
|
|
|
break;
|
|
|
|
case IOCTL_VIDEO_XGA_MAP_COPROCESSOR:
|
|
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
sizeof(VIDEO_XGA_COPROCESSOR_INFORMATION)) ) {
|
|
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// If we decided to run in framebuffer mode, then fail mapping the
|
|
// coprocessor
|
|
//
|
|
|
|
if (framebufMode) {
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
|
|
}
|
|
|
|
length = XGA_CO_PROCESSOR_REGS_SIZE;
|
|
|
|
// Map in at the page ganularity, then add in the page offset
|
|
// to the linear address.
|
|
|
|
offset = hwDeviceExtension->PhysicalCoProcessorAddress.LowPart & 0x00000FFF;
|
|
|
|
physicalAddress.LowPart =
|
|
hwDeviceExtension->PhysicalCoProcessorAddress.LowPart & 0xFFFFF000;
|
|
|
|
physicalAddress.HighPart = 0x00000000;
|
|
|
|
((PVIDEO_XGA_COPROCESSOR_INFORMATION)RequestPacket->OutputBuffer)->
|
|
CoProcessorVirtualAddress = 0;
|
|
|
|
inIoSpace = 0;
|
|
|
|
status = VideoPortMapMemory(hwDeviceExtension,
|
|
physicalAddress,
|
|
&length,
|
|
&inIoSpace,
|
|
&((PVIDEO_XGA_COPROCESSOR_INFORMATION)RequestPacket->
|
|
OutputBuffer)->CoProcessorVirtualAddress);
|
|
|
|
(PCHAR) ((PVIDEO_XGA_COPROCESSOR_INFORMATION)
|
|
RequestPacket->OutputBuffer)->CoProcessorVirtualAddress += offset;
|
|
|
|
//
|
|
// Also return the physical address of the video memory so the
|
|
// co-processor can access it.
|
|
//
|
|
|
|
|
|
(ULONG) ((PVIDEO_XGA_COPROCESSOR_INFORMATION)
|
|
RequestPacket->OutputBuffer)->PhysicalVideoMemoryAddress =
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.LowPart;
|
|
|
|
//
|
|
// Also return the XGA IO Register Base Address.
|
|
//
|
|
|
|
(ULONG) ((PVIDEO_XGA_COPROCESSOR_INFORMATION)
|
|
RequestPacket->OutputBuffer)->XgaIoRegisterBaseAddress =
|
|
hwDeviceExtension->PhysicalIoRegBaseAddress.LowPart;
|
|
|
|
|
|
VideoDebugPrint((3, "Xga IOCLT_MAP_CO_PROCESSOR\n physicalco = %x\n virtualco = %x\n physicalmem = %x\n",
|
|
hwDeviceExtension->PhysicalCoProcessorAddress.LowPart,
|
|
((PVIDEO_XGA_COPROCESSOR_INFORMATION)
|
|
RequestPacket->OutputBuffer)->CoProcessorVirtualAddress,
|
|
hwDeviceExtension->PhysicalVideoMemoryAddress.LowPart));
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
|
|
|
|
VideoDebugPrint((2, "XgaStartIO - GetBankSelectCode\n"));
|
|
|
|
status = XgaGetBankSelectCode(HwDeviceExtension,
|
|
(PVIDEO_BANK_SELECT) RequestPacket->OutputBuffer,
|
|
RequestPacket->OutputBufferLength,
|
|
&RequestPacket->StatusBlock->Information);
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_RESET_DEVICE:
|
|
|
|
XgaResetHW(HwDeviceExtension, 0, 0);
|
|
|
|
status = NO_ERROR;
|
|
|
|
break;
|
|
|
|
//
|
|
// if we get here, an invalid IoControlCode was specified.
|
|
//
|
|
|
|
default:
|
|
|
|
VideoDebugPrint((1, "Fell through Xga startIO routine - invalid command\n"));
|
|
|
|
status = ERROR_INVALID_FUNCTION;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RequestPacket->StatusBlock->Status = status;
|
|
|
|
return TRUE;
|
|
|
|
} // end XgaStartIO()
|
|
|
|
|
|
VP_STATUS
|
|
XgaSetMode(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
ULONG ModeNum
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the main execution routine for the miniport driver. It
|
|
acceptss a Video Request Packet, performs the request, and then returns
|
|
with the appropriate status.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Supplies a pointer to the miniport's device extension.
|
|
|
|
ModeNum - Index of the mode in which the adapter must be programmed.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR if the function completed successfully
|
|
ERROR_INVALID_PARAMETER if the requested mode is invalid for the device.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
PUCHAR indexRegister = (PUCHAR) (hwDeviceExtension->IoRegBaseAddress + INDEX_REG);
|
|
PMODE_REGISTER_DATA_TABLE modeTable;
|
|
UCHAR input;
|
|
|
|
VideoDebugPrint((1, "XgaSetMode: the mode being set is %d\n", ModeNum));
|
|
|
|
//
|
|
// Get the right mode table
|
|
//
|
|
|
|
if (hwDeviceExtension->BoardType & XGA_TYPE_1) {
|
|
|
|
modeTable = XgaModes[ModeNum].Xga1Mode;
|
|
|
|
} else {
|
|
|
|
if (hwDeviceExtension->BoardType & XGA_TYPE_2) {
|
|
|
|
modeTable = XgaModes[ModeNum].Xga2Mode;
|
|
|
|
} else {
|
|
|
|
VideoDebugPrint((0, "XGA: Internal mode flags are invalid"));
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Program the registers.
|
|
//
|
|
|
|
while (modeTable->Port != END_OF_SWITCH) {
|
|
|
|
switch (modeTable->Port) {
|
|
|
|
case INDEX_REG:
|
|
|
|
VideoPortWritePortUchar(indexRegister,
|
|
modeTable->IndexPort);
|
|
|
|
//
|
|
// For framebuffer mode, we must stretch scan lines to 1024.
|
|
// The Map wodth is the number of bytes divided by 8.
|
|
//
|
|
|
|
//
|
|
// NOTE *** !!!
|
|
// The bitmap width must be 1024 bytes wide for the VGA 256.
|
|
// This matches the change we put in the banking code.
|
|
//
|
|
|
|
if ( (framebufMode) &&
|
|
(modeTable->IndexPort == DISPLAY_PIXEL_MAP_WIDTH_LOW) ) {
|
|
|
|
VideoPortWritePortUchar(indexRegister + 1,
|
|
(UCHAR) (XgaModes[ModeNum].modeInformation.ScreenStride
|
|
/ 8));
|
|
|
|
} else {
|
|
|
|
VideoPortWritePortUchar(indexRegister + 1,
|
|
modeTable->Data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case INDEX_OR_REG:
|
|
|
|
VideoPortWritePortUchar(indexRegister,
|
|
modeTable->IndexPort);
|
|
|
|
input = VideoPortReadPortUchar((PUCHAR) hwDeviceExtension->IoRegBaseAddress +
|
|
DATA_IN_REG);
|
|
|
|
input |= modeTable->Data;
|
|
|
|
VideoPortWritePortUchar(indexRegister + 1, input);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
VideoPortWritePortUchar((PUCHAR) hwDeviceExtension->IoRegBaseAddress +
|
|
modeTable->Port,
|
|
modeTable->Data);
|
|
|
|
}
|
|
|
|
modeTable++;
|
|
|
|
}
|
|
|
|
//
|
|
// Save the current mode for future reference.
|
|
//
|
|
|
|
hwDeviceExtension->CurrentMode = (UCHAR) ModeNum;
|
|
|
|
return NO_ERROR;
|
|
|
|
} // end XgaSetMode();
|
|
|
|
|
|
VP_STATUS
|
|
XgaGetBankSelectCode(
|
|
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
|
PVIDEO_BANK_SELECT BankSelect,
|
|
ULONG BankSelectSize,
|
|
PULONG OutputSize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns information needed in order for caller to implement bank
|
|
management.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
|
|
|
BankSelect - Pointer to a VIDEO_BANK_SELECT structure in which the bank
|
|
select data will be returned (output buffer).
|
|
|
|
BankSelectSize - Length of the output buffer supplied by the user.
|
|
|
|
OutputSize - Pointer to a variable in which to return the actual size of
|
|
the data returned in the output buffer.
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR - information returned successfully
|
|
|
|
ERROR_MORE_DATA - output buffer not large enough to hold all info (but
|
|
Size is returned, so caller can tell how large a buffer to allocate)
|
|
|
|
ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
|
|
any useful data
|
|
|
|
ERROR_INVALID_PARAMETER - invalid video mode selection
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG codeSize;
|
|
PUCHAR pCodeDest;
|
|
PUCHAR pCodeBank;
|
|
|
|
//
|
|
// The minimum passed buffer size is a VIDEO_BANK_SELECT
|
|
// structure, so that we can return the required size; we can't do
|
|
// anything if we don't have at least that much buffer.
|
|
//
|
|
|
|
if (BankSelectSize < sizeof(VIDEO_BANK_SELECT)) {
|
|
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
}
|
|
|
|
//
|
|
// This serves an a ID for the version of the structure we're using.
|
|
//
|
|
|
|
BankSelect->Length = sizeof(VIDEO_BANK_SELECT);
|
|
|
|
//
|
|
// Determine the banking type, and set whether any banking is actually
|
|
// supported in this mode.
|
|
//
|
|
|
|
BankSelect->BankingFlags = 0;
|
|
BankSelect->BankingType = VideoBanked1RW;
|
|
BankSelect->Granularity = 0x10000;
|
|
|
|
//
|
|
// NOTE *** !!!
|
|
// The bitmap width must be 1024 bytes wide for the VGA 256.
|
|
// This matches the change we put in the mode initializatio code.
|
|
//
|
|
|
|
BankSelect->BitmapWidthInBytes =
|
|
XgaModes[HwDeviceExtension->CurrentMode].modeInformation.ScreenStride;
|
|
|
|
BankSelect->BitmapSize = HwDeviceExtension->FrameBufferLength;
|
|
|
|
pCodeBank = &BankSwitchStart;
|
|
codeSize = ((ULONG)&BankSwitchEnd) - ((ULONG)&BankSwitchStart);
|
|
|
|
//
|
|
// Size of complete banking info structure.
|
|
//
|
|
|
|
BankSelect->Size = sizeof(VIDEO_BANK_SELECT) + codeSize;
|
|
|
|
//
|
|
// If the buffer isn't big enough to hold all info, just return
|
|
// ERROR_MORE_DATA; Size is already set.
|
|
//
|
|
|
|
if (BankSelectSize < BankSelect->Size ) {
|
|
|
|
//
|
|
// We're returning only the VIDEO_BANK_SELECT structure.
|
|
//
|
|
|
|
*OutputSize = sizeof(VIDEO_BANK_SELECT);
|
|
return ERROR_MORE_DATA;
|
|
}
|
|
|
|
//
|
|
// Copy all banking code into the output buffer.
|
|
//
|
|
// Adjust the banking code first so we have the right IO port for
|
|
// the Aperture index register
|
|
//
|
|
//
|
|
|
|
*ApertureIndexRegister = HwDeviceExtension->PhysicalIoRegBaseAddress.LowPart
|
|
+ APP_INDEX_REG;
|
|
|
|
pCodeDest = (PUCHAR)BankSelect + sizeof(VIDEO_BANK_SELECT);
|
|
|
|
BankSelect->CodeOffset = sizeof(VIDEO_BANK_SELECT);
|
|
|
|
VideoPortMoveMemory(pCodeDest, pCodeBank, codeSize);
|
|
|
|
//
|
|
// Number of bytes we're returning is the full banking info size.
|
|
//
|
|
|
|
*OutputSize = BankSelect->Size;
|
|
|
|
return NO_ERROR;
|
|
|
|
} // end XgaGetBankSelectCode()
|
|
|
|
|
|
//
|
|
// Set of registers needed to reset the XGA in standart VGA mode.
|
|
//
|
|
|
|
INDEX_REGISTER_DATA_TABLE XgaResetToVga[] = {
|
|
{0x64, 0xff},
|
|
{0x50, 0x15},
|
|
{0x50, 0x14},
|
|
{0x51, 0x00},
|
|
{0x54, 0x04},
|
|
{0x70, 0x00},
|
|
{0x2A, 0x20},
|
|
{0xFF, 0x00}
|
|
};
|
|
|
|
BOOLEAN
|
|
XgaResetHW(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG Columns,
|
|
IN ULONG Rows
|
|
)
|
|
|
|
/*++
|
|
|
|
routine description:
|
|
|
|
This function is called to reset the XGA extended registers back to
|
|
VGA so we can do an int 10 back to VGA mode.
|
|
|
|
Arguments:
|
|
|
|
hwdeviceextension - pointer to the miniport driver's device extension.
|
|
Columns - Number of columns for text mode (not used).
|
|
Rows - Number of rows for text mode (not used).
|
|
|
|
Return value:
|
|
|
|
Always returns FALSE so that the Video Port driver will call Int 10 to
|
|
set the desired video mode.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
|
USHORT i;
|
|
|
|
XGAOUT(APP_CTL_REG, 0x00);
|
|
|
|
XGAOUT(INT_ENABLE_REG, 0x00);
|
|
|
|
XGAOUT(INT_STATUS_REG, 0xff);
|
|
|
|
// Now init all the index registers.
|
|
|
|
for (i = 0 ; XgaResetToVga[i].PortIndex != 0xff ; i++) {
|
|
|
|
XGAIDXOUT(0x0A,
|
|
XgaResetToVga[i].PortIndex,
|
|
XgaResetToVga[i].Data);
|
|
}
|
|
|
|
XGAOUT(OP_MODE_REG, 0x1);
|
|
|
|
VideoPortWritePortUchar(hwDeviceExtension->PassThroughPort, 0x01);
|
|
|
|
return FALSE;
|
|
}
|