mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 18:24:02 +00:00
1556 lines
44 KiB
C
1556 lines
44 KiB
C
/*
|
||
* PROJECT: ReactOS VGA Miniport Driver
|
||
* LICENSE: Microsoft NT4 DDK Sample Code License
|
||
* FILE: boot/drivers/video/miniport/vga/vga.c
|
||
* PURPOSE: Main Standard VGA-compatible Minport Handling Code
|
||
* PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation
|
||
* ReactOS Portable Systems Group
|
||
*/
|
||
|
||
//---------------------------------------------------------------------------
|
||
|
||
#include "vga.h"
|
||
|
||
//---------------------------------------------------------------------------
|
||
//
|
||
// Function declarations
|
||
//
|
||
// Functions that start with 'VGA' are entry points for the OS port driver.
|
||
//
|
||
|
||
VP_STATUS
|
||
VgaFindAdapter(
|
||
PVOID HwDeviceExtension,
|
||
PVOID HwContext,
|
||
PWSTR ArgumentString,
|
||
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
|
||
PUCHAR Again
|
||
);
|
||
|
||
BOOLEAN
|
||
VgaInitialize(
|
||
PVOID HwDeviceExtension
|
||
);
|
||
|
||
BOOLEAN
|
||
VgaStartIO(
|
||
PVOID HwDeviceExtension,
|
||
PVIDEO_REQUEST_PACKET RequestPacket
|
||
);
|
||
|
||
//
|
||
// Private function prototypes.
|
||
//
|
||
|
||
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
|
||
);
|
||
|
||
VP_STATUS
|
||
VgaSetMode(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
||
PVIDEO_MODE Mode,
|
||
ULONG ModeSize,
|
||
// eVb: 1.1 [SET MODE] - Add new output parameter for framebuffer update functionality
|
||
PULONG PhysPtrChange
|
||
// eVb: 1.1 [END]
|
||
);
|
||
|
||
BOOLEAN
|
||
VgaIsPresent(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
);
|
||
|
||
VOID
|
||
VgaInterpretCmdStream(
|
||
PVOID HwDeviceExtension,
|
||
PUSHORT pusCmdStream
|
||
);
|
||
|
||
VP_STATUS
|
||
VgaSetPaletteReg(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
||
PVIDEO_PALETTE_DATA PaletteBuffer,
|
||
ULONG PaletteBufferSize
|
||
);
|
||
|
||
VP_STATUS
|
||
VgaSetColorLookup(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
||
PVIDEO_CLUT ClutBuffer,
|
||
ULONG ClutBufferSize
|
||
);
|
||
|
||
VP_STATUS
|
||
GetDeviceDataCallback(
|
||
PVOID HwDeviceExtension,
|
||
PVOID Context,
|
||
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
|
||
PVOID Identifier,
|
||
ULONG IdentifierLength,
|
||
PVOID ConfigurationData,
|
||
ULONG ConfigurationDataLength,
|
||
PVOID ComponentInformation,
|
||
ULONG ComponentInformationLength
|
||
);
|
||
|
||
// eVb: 1.2 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
|
||
VP_STATUS
|
||
VgaAcquireResources(
|
||
PHW_DEVICE_EXTENSION DeviceExtension
|
||
);
|
||
// eVb: 1.2 [END]
|
||
|
||
#if defined(ALLOC_PRAGMA)
|
||
#pragma alloc_text(PAGE,DriverEntry)
|
||
#pragma alloc_text(PAGE,VgaFindAdapter)
|
||
#pragma alloc_text(PAGE,VgaInitialize)
|
||
#pragma alloc_text(PAGE,VgaStartIO)
|
||
#pragma alloc_text(PAGE,VgaIsPresent)
|
||
#pragma alloc_text(PAGE,VgaSetColorLookup)
|
||
#endif
|
||
|
||
|
||
//---------------------------------------------------------------------------
|
||
ULONG
|
||
// eVb: 1.3 [GCC] - Add NTAPI for GCC support
|
||
NTAPI
|
||
// eVb: 1.3 [END]
|
||
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 3VideoPortInitialize().
|
||
|
||
Return Value:
|
||
|
||
Status from VideoPortInitialize()
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
VIDEO_HW_INITIALIZATION_DATA hwInitData;
|
||
ULONG status;
|
||
ULONG initializationStatus = (ULONG) -1;
|
||
|
||
//
|
||
// 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 = VgaFindAdapter;
|
||
hwInitData.HwInitialize = VgaInitialize;
|
||
hwInitData.HwInterrupt = NULL;
|
||
hwInitData.HwStartIO = VgaStartIO;
|
||
|
||
//
|
||
// Determine the size we require for the device extension.
|
||
//
|
||
|
||
hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
|
||
|
||
//
|
||
// Always start with parameters for device0 in this case.
|
||
// We can leave it like this since we know we will only ever find one
|
||
// VGA type adapter in a machine.
|
||
//
|
||
|
||
// hwInitData.StartingDeviceNumber = 0;
|
||
|
||
//
|
||
// Once all the relevant information has been stored, call the video
|
||
// port driver to do the initialization.
|
||
// For this device we will repeat this call three times, for ISA, EISA
|
||
// and PCI.
|
||
// We will return the minimum of all return values.
|
||
//
|
||
|
||
//
|
||
// We will try the PCI bus first so that our ISA detection does'nt claim
|
||
// PCI cards (since it is impossible to differentiate between the two
|
||
// by looking at the registers).
|
||
//
|
||
|
||
//
|
||
// NOTE: since this driver only supports one adapter, we will return
|
||
// as soon as we find a device, without going on to the following buses.
|
||
// Normally one would call for each bus type and return the smallest
|
||
// value.
|
||
//
|
||
|
||
#if !defined(_ALPHA_)
|
||
|
||
//
|
||
// Before we can enable this on ALPHA we need to find a way to map a
|
||
// sparse view of a 4MB region successfully.
|
||
//
|
||
|
||
hwInitData.AdapterInterfaceType = PCIBus;
|
||
|
||
initializationStatus = VideoPortInitialize(Context1,
|
||
Context2,
|
||
&hwInitData,
|
||
NULL);
|
||
|
||
if (initializationStatus == NO_ERROR)
|
||
{
|
||
return initializationStatus;
|
||
}
|
||
|
||
#endif
|
||
|
||
hwInitData.AdapterInterfaceType = MicroChannel;
|
||
|
||
initializationStatus = VideoPortInitialize(Context1,
|
||
Context2,
|
||
&hwInitData,
|
||
NULL);
|
||
|
||
//
|
||
// Return immediately instead of checkin for smallest return code.
|
||
//
|
||
|
||
if (initializationStatus == NO_ERROR)
|
||
{
|
||
return initializationStatus;
|
||
}
|
||
|
||
|
||
hwInitData.AdapterInterfaceType = Internal;
|
||
|
||
initializationStatus = VideoPortInitialize(Context1,
|
||
Context2,
|
||
&hwInitData,
|
||
NULL);
|
||
|
||
if (initializationStatus == NO_ERROR)
|
||
{
|
||
return initializationStatus;
|
||
}
|
||
|
||
|
||
hwInitData.AdapterInterfaceType = Isa;
|
||
|
||
initializationStatus = VideoPortInitialize(Context1,
|
||
Context2,
|
||
&hwInitData,
|
||
NULL);
|
||
|
||
if (initializationStatus == NO_ERROR)
|
||
{
|
||
return initializationStatus;
|
||
}
|
||
|
||
|
||
|
||
hwInitData.AdapterInterfaceType = Eisa;
|
||
|
||
status = VideoPortInitialize(Context1,
|
||
Context2,
|
||
&hwInitData,
|
||
NULL);
|
||
|
||
if (initializationStatus > status) {
|
||
initializationStatus = status;
|
||
}
|
||
|
||
return initializationStatus;
|
||
|
||
} // end DriverEntry()
|
||
|
||
//---------------------------------------------------------------------------
|
||
VP_STATUS
|
||
VgaFindAdapter(
|
||
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 - Supplies 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 known 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.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
||
|
||
//
|
||
// 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;
|
||
|
||
}
|
||
// eVb: 1.4 [CIRRUS] - Remove CIRRUS-specific support
|
||
//
|
||
// Check internal VGA (MIPS and ARM systems)
|
||
//
|
||
|
||
if ((ConfigInfo->AdapterInterfaceType == Internal) &&
|
||
(VideoPortGetDeviceData(HwDeviceExtension,
|
||
VpControllerData,
|
||
&GetDeviceDataCallback,
|
||
VgaAccessRange) != NO_ERROR))
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
// eVb: 1.4 [END]
|
||
//
|
||
// No interrupt information is necessary.
|
||
//
|
||
|
||
//
|
||
// Check to see if there is a hardware resource conflict.
|
||
//
|
||
// eVb: 1.5 [RESOURCE] - Use new function for acquiring VGA resources (I/O, memory)
|
||
if (VgaAcquireResources(hwDeviceExtension) != NO_ERROR) return ERROR_INVALID_PARAMETER;
|
||
// eVb: 1.5 [END]
|
||
//
|
||
// Get logical IO port addresses.
|
||
//
|
||
|
||
if ((hwDeviceExtension->IOAddress =
|
||
VideoPortGetDeviceBase(hwDeviceExtension,
|
||
VgaAccessRange->RangeStart,
|
||
VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1,
|
||
VgaAccessRange->RangeInIoSpace)) == NULL)
|
||
{
|
||
VideoDebugPrint((0, "VgaFindAdapter - Fail to get io address\n"));
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Determine whether a VGA is present.
|
||
//
|
||
|
||
if (!VgaIsPresent(hwDeviceExtension)) {
|
||
|
||
VideoDebugPrint((0, "VgaFindAdapter - VGA Failed\n"));
|
||
return ERROR_DEV_NOT_EXIST;
|
||
}
|
||
|
||
//
|
||
// Minimum size of the buffer required to store the hardware state
|
||
// information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
|
||
//
|
||
|
||
ConfigInfo->HardwareStateSize = VGA_TOTAL_STATE_SIZE;
|
||
|
||
//
|
||
// Pass a pointer to the emulator range we are using.
|
||
//
|
||
// eVb: 1.6 [VDM] - Disable VDM for now
|
||
ConfigInfo->NumEmulatorAccessEntries = 0;
|
||
ConfigInfo->EmulatorAccessEntries = NULL;
|
||
ConfigInfo->EmulatorAccessEntriesContext = 0;
|
||
// eVb: 1.6 [END]
|
||
//
|
||
// BUGBUG
|
||
//
|
||
// There is really no reason to have the frame buffer mapped. On an
|
||
// x86 we use if for save/restore (supposedly) but even then we
|
||
// would only need to map a 64K window, not all 16 Meg!
|
||
//
|
||
|
||
#ifdef _X86_
|
||
|
||
//
|
||
// Map the video memory into the system virtual address space so we can
|
||
// clear it out and use it for save and restore.
|
||
//
|
||
|
||
if ( (hwDeviceExtension->VideoMemoryAddress =
|
||
VideoPortGetDeviceBase(hwDeviceExtension,
|
||
VgaAccessRange[2].RangeStart,
|
||
VgaAccessRange[2].RangeLength,
|
||
FALSE)) == NULL)
|
||
{
|
||
VideoDebugPrint((0, "VgaFindAdapter - Fail to get memory address\n"));
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
VideoPortDebugPrint(0, "vga mapped at %x\n", hwDeviceExtension->VideoMemoryAddress);
|
||
#endif
|
||
// eVb: 1.7 [VDM] - Disable VDM for now
|
||
ConfigInfo->VdmPhysicalVideoMemoryAddress.QuadPart = 0;
|
||
ConfigInfo->VdmPhysicalVideoMemoryLength = 0;
|
||
// eVb: 1.7 [END]
|
||
//
|
||
// Indicate we do not wish to be called again for another initialization.
|
||
//
|
||
|
||
*Again = 0;
|
||
|
||
//
|
||
// Indicate a successful completion status.
|
||
//
|
||
|
||
return NO_ERROR;
|
||
|
||
|
||
} // VgaFindAdapter()
|
||
|
||
//---------------------------------------------------------------------------
|
||
BOOLEAN
|
||
VgaInitialize(
|
||
PVOID HwDeviceExtension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine does one time initialization of the device.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
||
|
||
//
|
||
// set up the default cursor position and type.
|
||
//
|
||
|
||
hwDeviceExtension->CursorPosition.Column = 0;
|
||
hwDeviceExtension->CursorPosition.Row = 0;
|
||
hwDeviceExtension->CursorTopScanLine = 0;
|
||
hwDeviceExtension->CursorBottomScanLine = 31;
|
||
hwDeviceExtension->CursorEnable = TRUE;
|
||
|
||
// eVb: 1.8 [VBE] - Initialize VBE modes
|
||
InitializeModeTable(hwDeviceExtension);
|
||
// eVb: 1.8 [END]
|
||
return TRUE;
|
||
|
||
} // VgaInitialize()
|
||
|
||
//---------------------------------------------------------------------------
|
||
BOOLEAN
|
||
VgaStartIO(
|
||
PVOID HwDeviceExtension,
|
||
PVIDEO_REQUEST_PACKET RequestPacket
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the main execution routine for the miniport driver. It
|
||
accepts a Video Request Packet, performs the request, and then returns
|
||
with the appropriate status.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's adapter information.
|
||
|
||
RequestPacket - Pointer to the video request packet. This structure
|
||
contains all the parameters passed to the VideoIoControl function.
|
||
|
||
Return Value:
|
||
|
||
This routine will return error codes from the various support routines
|
||
and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
|
||
buffers and ERROR_INVALID_FUNCTION for unsupported functions.
|
||
|
||
--*/
|
||
|
||
{
|
||
PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
|
||
VP_STATUS status;
|
||
VIDEO_MODE videoMode;
|
||
PVIDEO_MEMORY_INFORMATION memoryInformation;
|
||
ULONG inIoSpace;
|
||
ULONG Result;
|
||
|
||
//
|
||
// Switch on the IoContolCode in the RequestPacket. It indicates which
|
||
// function must be performed by the driver.
|
||
//
|
||
// eVb: 1.9 [IOCTL] - Remove IOCTLs not needed yet
|
||
switch (RequestPacket->IoControlCode)
|
||
{
|
||
case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - 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;
|
||
|
||
//
|
||
// We reserved 16 meg for the frame buffer, however, it makes
|
||
// no sense to map more memory than there is on the card. So
|
||
// only map the amount of memory we have on the card.
|
||
//
|
||
// eVb: 1.10 [CIRRUS] - On VGA, we have VRAM size since boot, use it
|
||
memoryInformation->VideoRamLength =
|
||
hwDeviceExtension->PhysicalVideoMemoryLength;
|
||
// eVb: 1.10 [END]
|
||
//
|
||
// If you change to using a dense space frame buffer, make this
|
||
// value a 4 for the ALPHA.
|
||
//
|
||
|
||
inIoSpace = 0;
|
||
|
||
status = VideoPortMapMemory(hwDeviceExtension,
|
||
hwDeviceExtension->PhysicalVideoMemoryBase,
|
||
// eVb: 1.11 [CIRRUS] - On VGA, we have VRAM size since boot, use it
|
||
&memoryInformation->VideoRamLength,
|
||
// eVb: 1.11 [END]
|
||
&inIoSpace,
|
||
&(memoryInformation->VideoRamBase));
|
||
|
||
if (status != NO_ERROR) {
|
||
VideoDebugPrint((0, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status));
|
||
}
|
||
|
||
memoryInformation->FrameBufferBase =
|
||
((PUCHAR) (memoryInformation->VideoRamBase)) +
|
||
hwDeviceExtension->PhysicalFrameOffset.LowPart;
|
||
|
||
memoryInformation->FrameBufferLength =
|
||
hwDeviceExtension->PhysicalFrameLength ?
|
||
hwDeviceExtension->PhysicalFrameLength :
|
||
memoryInformation->VideoRamLength;
|
||
|
||
|
||
VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension->PhysicalVideoMemoryBase));
|
||
VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension->PhysicalVideoMemoryLength));
|
||
VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation->VideoRamBase));
|
||
VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation->VideoRamLength));
|
||
|
||
VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension->PhysicalFrameOffset.LowPart));
|
||
VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation->FrameBufferBase));
|
||
VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension->PhysicalFrameLength));
|
||
VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation->FrameBufferLength));
|
||
|
||
break;
|
||
|
||
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_QUERY_AVAIL_MODES:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
|
||
|
||
status = VgaQueryAvailableModes(HwDeviceExtension,
|
||
(PVIDEO_MODE_INFORMATION)
|
||
RequestPacket->OutputBuffer,
|
||
RequestPacket->OutputBufferLength,
|
||
&RequestPacket->StatusBlock->Information);
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
|
||
|
||
status = VgaQueryNumberOfAvailableModes(HwDeviceExtension,
|
||
(PVIDEO_NUM_MODES)
|
||
RequestPacket->OutputBuffer,
|
||
RequestPacket->OutputBufferLength,
|
||
&RequestPacket->StatusBlock->Information);
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_QUERY_CURRENT_MODE:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
|
||
|
||
status = VgaQueryCurrentMode(HwDeviceExtension,
|
||
(PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer,
|
||
RequestPacket->OutputBufferLength,
|
||
&RequestPacket->StatusBlock->Information);
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_SET_CURRENT_MODE:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
|
||
|
||
status = VgaSetMode(HwDeviceExtension,
|
||
(PVIDEO_MODE) RequestPacket->InputBuffer,
|
||
RequestPacket->InputBufferLength,
|
||
// eVb: 1.12 [SET MODE] - Use new output parameter for framebuffer update functionality
|
||
&Result);
|
||
// eVb: 1.12 [END]
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_RESET_DEVICE:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
|
||
|
||
videoMode.RequestedMode = 0;
|
||
|
||
VgaSetMode(HwDeviceExtension,
|
||
(PVIDEO_MODE) &videoMode,
|
||
sizeof(videoMode),
|
||
// eVb: 1.13 [SET MODE] - Use new output parameter for framebuffer update functionality
|
||
&Result);
|
||
// eVb: 1.13 [END]
|
||
|
||
//
|
||
// Always return succcess since settings the text mode will fail on
|
||
// non-x86.
|
||
//
|
||
// Also, failiure to set the text mode is not fatal in any way, since
|
||
// this operation must be followed by another set mode operation.
|
||
//
|
||
|
||
status = NO_ERROR;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_LOAD_AND_SET_FONT:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_SET_CURSOR_POSITION:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_SET_CURSOR_ATTR:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
|
||
|
||
status = VgaSetPaletteReg(HwDeviceExtension,
|
||
(PVIDEO_PALETTE_DATA) RequestPacket->InputBuffer,
|
||
RequestPacket->InputBufferLength);
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_SET_COLOR_REGISTERS:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
|
||
|
||
status = VgaSetColorLookup(HwDeviceExtension,
|
||
(PVIDEO_CLUT) RequestPacket->InputBuffer,
|
||
RequestPacket->InputBufferLength);
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_ENABLE_VDM:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
|
||
case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
break;
|
||
|
||
case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
|
||
{
|
||
VideoDebugPrint((2, "VgaStartIO - Query Public Address Ranges\n"));
|
||
|
||
PVIDEO_PUBLIC_ACCESS_RANGES portAccess;
|
||
ULONG physicalPortLength;
|
||
|
||
if (RequestPacket->OutputBufferLength <
|
||
sizeof(VIDEO_PUBLIC_ACCESS_RANGES))
|
||
{
|
||
status = ERROR_INSUFFICIENT_BUFFER;
|
||
break;
|
||
}
|
||
|
||
RequestPacket->StatusBlock->Information =
|
||
sizeof(VIDEO_PUBLIC_ACCESS_RANGES);
|
||
|
||
portAccess = RequestPacket->OutputBuffer;
|
||
|
||
//
|
||
// The first public access range is the IO ports.
|
||
//
|
||
|
||
portAccess->VirtualAddress = (PVOID) NULL;
|
||
portAccess->InIoSpace = TRUE;
|
||
portAccess->MappedInIoSpace = portAccess->InIoSpace;
|
||
physicalPortLength = VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1;
|
||
|
||
status = VideoPortMapMemory(hwDeviceExtension,
|
||
VgaAccessRange->RangeStart,
|
||
&physicalPortLength,
|
||
&(portAccess->MappedInIoSpace),
|
||
&(portAccess->VirtualAddress));
|
||
// eVb: 1.17 [GCG] - Fix lvalue error
|
||
portAccess->VirtualAddress = (PVOID)((ULONG_PTR)portAccess->VirtualAddress - VGA_BASE_IO_PORT);
|
||
// eVb: 1.17 [END]
|
||
VideoDebugPrint((2, "VgaStartIO - mapping ports to (%x)\n", portAccess->VirtualAddress));
|
||
}
|
||
|
||
break;
|
||
|
||
case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
|
||
|
||
VideoDebugPrint((2, "VgaStartIO - Free Public Access Ranges\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
break;
|
||
|
||
//
|
||
// if we get here, an invalid IoControlCode was specified.
|
||
//
|
||
|
||
default:
|
||
|
||
VideoDebugPrint((0, "Fell through vga startIO routine - invalid command\n"));
|
||
|
||
status = ERROR_INVALID_FUNCTION;
|
||
|
||
break;
|
||
|
||
}
|
||
// eVb: 1.9 [END]
|
||
RequestPacket->StatusBlock->Status = status;
|
||
|
||
return TRUE;
|
||
|
||
} // VgaStartIO()
|
||
|
||
|
||
//---------------------------------------------------------------------------
|
||
//
|
||
// private routines
|
||
//
|
||
|
||
|
||
//---------------------------------------------------------------------------
|
||
BOOLEAN
|
||
VgaIsPresent(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine returns TRUE if a VGA is present. Determining whether a VGA
|
||
is present is a two-step process. First, this routine walks bits through
|
||
the Bit Mask register, to establish that there are readable indexed
|
||
registers (EGAs normally don't have readable registers, and other adapters
|
||
are unlikely to have indexed registers). This test is done first because
|
||
it's a non-destructive EGA rejection test (correctly rejects EGAs, but
|
||
doesn't potentially mess up the screen or the accessibility of display
|
||
memory). Normally, this would be an adequate test, but some EGAs have
|
||
readable registers, so next, we check for the existence of the Chain4 bit
|
||
in the Memory Mode register; this bit doesn't exist in EGAs. It's
|
||
conceivable that there are EGAs with readable registers and a register bit
|
||
where Chain4 is stored, although I don't know of any; if a better test yet
|
||
is needed, memory could be written to in Chain4 mode, and then examined
|
||
plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
|
||
supposed to do. However, the current test should be adequate to eliminate
|
||
just about all EGAs, and 100% of everything else.
|
||
|
||
If this function fails to find a VGA, it attempts to undo any damage it
|
||
may have inadvertently done while testing. The underlying assumption for
|
||
the damage control is that if there's any non-VGA adapter at the tested
|
||
ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
|
||
other adapters that use 3C4/5 or 3CE/F, and b), if there are other
|
||
adapters, I certainly don't know how to restore their original states. So
|
||
all error recovery is oriented toward putting an EGA back in a writable
|
||
state, so that error messages are visible. The EGA's state on entry is
|
||
assumed to be text mode, so the Memory Mode register is restored to the
|
||
default state for text mode.
|
||
|
||
If a VGA is found, the VGA is returned to its original state after
|
||
testing is finished.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
TRUE if a VGA is present, FALSE if not.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR originalGCAddr;
|
||
UCHAR originalSCAddr;
|
||
UCHAR originalBitMask;
|
||
UCHAR originalReadMap;
|
||
UCHAR originalMemoryMode;
|
||
UCHAR testMask;
|
||
BOOLEAN returnStatus;
|
||
|
||
//
|
||
// Remember the original state of the Graphics Controller Address register.
|
||
//
|
||
|
||
originalGCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT);
|
||
|
||
//
|
||
// Write the Read Map register with a known state so we can verify
|
||
// that it isn't changed after we fool with the Bit Mask. This ensures
|
||
// that we're dealing with indexed registers, since both the Read Map and
|
||
// the Bit Mask are addressed at GRAPH_DATA_PORT.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, IND_READ_MAP);
|
||
|
||
//
|
||
// If we can't read back the Graphics Address register setting we just
|
||
// performed, it's not readable and this isn't a VGA.
|
||
//
|
||
|
||
if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Set the Read Map register to a known state.
|
||
//
|
||
|
||
originalReadMap = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, READ_MAP_TEST_SETTING);
|
||
|
||
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
|
||
|
||
//
|
||
// The Read Map setting we just performed can't be read back; not a
|
||
// VGA. Restore the default Read Map state.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, READ_MAP_DEFAULT);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Remember the original setting of the Bit Mask register.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, IND_BIT_MASK);
|
||
if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) {
|
||
|
||
//
|
||
// The Graphics Address register setting we just made can't be read
|
||
// back; not a VGA. Restore the default Read Map state.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, IND_READ_MAP);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, READ_MAP_DEFAULT);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
originalBitMask = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT);
|
||
|
||
//
|
||
// Set up the initial test mask we'll write to and read from the Bit Mask.
|
||
//
|
||
|
||
testMask = 0xBB;
|
||
|
||
do {
|
||
|
||
//
|
||
// Write the test mask to the Bit Mask.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, testMask);
|
||
|
||
//
|
||
// Make sure the Bit Mask remembered the value.
|
||
//
|
||
|
||
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT) != testMask) {
|
||
|
||
//
|
||
// The Bit Mask is not properly writable and readable; not a VGA.
|
||
// Restore the Bit Mask and Read Map to their default states.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, IND_READ_MAP);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, READ_MAP_DEFAULT);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Cycle the mask for next time.
|
||
//
|
||
|
||
testMask >>= 1;
|
||
|
||
} while (testMask != 0);
|
||
|
||
//
|
||
// There's something readable at GRAPH_DATA_PORT; now switch back and
|
||
// make sure that the Read Map register hasn't changed, to verify that
|
||
// we're dealing with indexed registers.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, IND_READ_MAP);
|
||
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
|
||
|
||
//
|
||
// The Read Map is not properly writable and readable; not a VGA.
|
||
// Restore the Bit Mask and Read Map to their default states, in case
|
||
// this is an EGA, so subsequent writes to the screen aren't garbled.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, READ_MAP_DEFAULT);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, IND_BIT_MASK);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// We've pretty surely verified the existence of the Bit Mask register.
|
||
// Put the Graphics Controller back to the original state.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, originalReadMap);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, IND_BIT_MASK);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_DATA_PORT, originalBitMask);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
GRAPH_ADDRESS_PORT, originalGCAddr);
|
||
|
||
//
|
||
// Now, check for the existence of the Chain4 bit.
|
||
//
|
||
|
||
//
|
||
// Remember the original states of the Sequencer Address and Memory Mode
|
||
// registers.
|
||
//
|
||
|
||
originalSCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
|
||
if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) {
|
||
|
||
//
|
||
// Couldn't read back the Sequencer Address register setting we just
|
||
// performed.
|
||
//
|
||
|
||
return FALSE;
|
||
}
|
||
originalMemoryMode = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_DATA_PORT);
|
||
|
||
//
|
||
// Toggle the Chain4 bit and read back the result. This must be done during
|
||
// sync reset, since we're changing the chaining state.
|
||
//
|
||
|
||
//
|
||
// Begin sync reset.
|
||
//
|
||
|
||
VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT),
|
||
(IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
|
||
|
||
//
|
||
// Toggle the Chain4 bit.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK));
|
||
|
||
if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) {
|
||
|
||
//
|
||
// Chain4 bit not there; not a VGA.
|
||
// Set text mode default for Memory Mode register.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT);
|
||
//
|
||
// End sync reset.
|
||
//
|
||
|
||
VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT),
|
||
(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
|
||
|
||
returnStatus = FALSE;
|
||
|
||
} else {
|
||
|
||
//
|
||
// It's a VGA.
|
||
//
|
||
|
||
//
|
||
// Restore the original Memory Mode setting.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_DATA_PORT, originalMemoryMode);
|
||
|
||
//
|
||
// End sync reset.
|
||
//
|
||
|
||
VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT),
|
||
(USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
|
||
|
||
//
|
||
// Restore the original Sequencer Address setting.
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
SEQ_ADDRESS_PORT, originalSCAddr);
|
||
|
||
returnStatus = TRUE;
|
||
}
|
||
|
||
return returnStatus;
|
||
|
||
} // VgaIsPresent()
|
||
|
||
|
||
//---------------------------------------------------------------------------
|
||
VP_STATUS
|
||
VgaSetPaletteReg(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
||
PVIDEO_PALETTE_DATA PaletteBuffer,
|
||
ULONG PaletteBufferSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets a specified portion of the EGA (not DAC) palette
|
||
registers.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
||
PaletteBuffer - Pointer to the structure containing the palette data.
|
||
|
||
PaletteBufferSize - Length of the input buffer supplied by the user.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR - information returned successfully
|
||
|
||
ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
|
||
|
||
ERROR_INVALID_PARAMETER - invalid palette size.
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT i;
|
||
|
||
//
|
||
// Check if the size of the data in the input buffer is large enough.
|
||
//
|
||
|
||
if ((PaletteBufferSize) < (sizeof(VIDEO_PALETTE_DATA)) ||
|
||
(PaletteBufferSize < (sizeof(VIDEO_PALETTE_DATA) +
|
||
(sizeof(USHORT) * (PaletteBuffer->NumEntries -1)) ))) {
|
||
|
||
return ERROR_INSUFFICIENT_BUFFER;
|
||
|
||
}
|
||
|
||
//
|
||
// Check to see if the parameters are valid.
|
||
//
|
||
|
||
if ( (PaletteBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER ) ||
|
||
(PaletteBuffer->NumEntries == 0) ||
|
||
(PaletteBuffer->FirstEntry + PaletteBuffer->NumEntries >
|
||
VIDEO_MAX_PALETTE_REGISTER + 1 ) ) {
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
|
||
}
|
||
|
||
//
|
||
// Reset ATC to index mode
|
||
//
|
||
|
||
VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
|
||
ATT_INITIALIZE_PORT_COLOR);
|
||
|
||
//
|
||
// Blast out our palette values.
|
||
//
|
||
|
||
for (i = 0; i < PaletteBuffer->NumEntries; i++) {
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
|
||
(UCHAR)(i+PaletteBuffer->FirstEntry));
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
ATT_DATA_WRITE_PORT,
|
||
(UCHAR)PaletteBuffer->Colors[i]);
|
||
}
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
|
||
VIDEO_ENABLE);
|
||
|
||
return NO_ERROR;
|
||
|
||
} // end VgaSetPaletteReg()
|
||
|
||
|
||
//---------------------------------------------------------------------------
|
||
VP_STATUS
|
||
VgaSetColorLookup(
|
||
PHW_DEVICE_EXTENSION HwDeviceExtension,
|
||
PVIDEO_CLUT ClutBuffer,
|
||
ULONG ClutBufferSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets a specified portion of the DAC color lookup table
|
||
settings.
|
||
|
||
Arguments:
|
||
|
||
HwDeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
||
ClutBufferSize - Length of the input buffer supplied by the user.
|
||
|
||
ClutBuffer - Pointer to the structure containing the color lookup table.
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR - information returned successfully
|
||
|
||
ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
|
||
|
||
ERROR_INVALID_PARAMETER - invalid clut size.
|
||
|
||
--*/
|
||
|
||
{
|
||
PVIDEOMODE CurrentMode = HwDeviceExtension->CurrentMode;
|
||
USHORT i;
|
||
|
||
//
|
||
// Check if the size of the data in the input buffer is large enough.
|
||
//
|
||
|
||
if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
|
||
(ClutBufferSize < sizeof(VIDEO_CLUT) +
|
||
(sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) ) {
|
||
|
||
return ERROR_INSUFFICIENT_BUFFER;
|
||
|
||
}
|
||
|
||
//
|
||
// Check to see if the parameters are valid.
|
||
//
|
||
|
||
if ( (ClutBuffer->NumEntries == 0) ||
|
||
(ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
|
||
(ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
|
||
VIDEO_MAX_COLOR_REGISTER + 1) ) {
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
|
||
}
|
||
// eVb: 1.14 [VBE] - Add VBE color support
|
||
//
|
||
// Check SVGA mode
|
||
//
|
||
|
||
if (CurrentMode->bitsPerPlane >= 8) return VbeSetColorLookup(HwDeviceExtension, ClutBuffer);
|
||
// eVb: 1.14 [END]
|
||
//
|
||
// Path for VGA mode
|
||
//
|
||
// eVb: 1.15 [VBE] - Add VBE support for non-VGA-compatible detected modes
|
||
if (!CurrentMode->NonVgaMode)
|
||
{
|
||
// eVb: 1.15 [END]
|
||
//
|
||
// Set CLUT registers directly on the hardware
|
||
//
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_ADDRESS_WRITE_PORT, (UCHAR) ClutBuffer->FirstEntry);
|
||
|
||
for (i = 0; i < ClutBuffer->NumEntries; i++) {
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_ADDRESS_WRITE_PORT,
|
||
(UCHAR)(i + ClutBuffer->FirstEntry));
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_DATA_REG_PORT,
|
||
ClutBuffer->LookupTable[i].RgbArray.Red);
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_DATA_REG_PORT,
|
||
ClutBuffer->LookupTable[i].RgbArray.Green);
|
||
|
||
VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
|
||
DAC_DATA_REG_PORT,
|
||
ClutBuffer->LookupTable[i].RgbArray.Blue);
|
||
}
|
||
return NO_ERROR;
|
||
}
|
||
|
||
return ERROR_INVALID_PARAMETER;
|
||
|
||
} // end VgaSetColorLookup()
|
||
|
||
VP_STATUS
|
||
GetDeviceDataCallback(
|
||
PVOID HwDeviceExtension,
|
||
PVOID Context,
|
||
VIDEO_DEVICE_DATA_TYPE DeviceDataType,
|
||
PVOID Identifier,
|
||
ULONG IdentifierLength,
|
||
PVOID ConfigurationData,
|
||
ULONG ConfigurationDataLength,
|
||
PVOID ComponentInformation,
|
||
ULONG ComponentInformationLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Callback routine for the VideoPortGetDeviceData function.
|
||
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
VideoPortDebugPrint(Error, "Detected internal VGA chip on embedded board, todo\n");
|
||
while (TRUE);
|
||
return NO_ERROR;
|
||
|
||
} //end GetDeviceDataCallback()
|
||
|
||
// eVb: 1.16 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
|
||
VP_STATUS
|
||
VgaAcquireResources(
|
||
PHW_DEVICE_EXTENSION DeviceExtension
|
||
)
|
||
{
|
||
VP_STATUS Status = NO_ERROR;
|
||
ULONG Ranges, i;
|
||
|
||
//
|
||
// Try exclusive ranges (vga + ati)
|
||
//
|
||
|
||
Ranges = NUM_VGA_ACCESS_RANGES;
|
||
for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = FALSE;
|
||
if (VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange) != NO_ERROR)
|
||
{
|
||
//
|
||
// Not worked, try vga only
|
||
//
|
||
|
||
Ranges = 3;
|
||
if (VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange) != NO_ERROR)
|
||
{
|
||
//
|
||
// Still not, try shared ranges
|
||
//
|
||
|
||
for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = TRUE;
|
||
Status = VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange);
|
||
if (Status == NO_ERROR)
|
||
{
|
||
//
|
||
// It did work
|
||
//
|
||
|
||
VideoPortVerifyAccessRanges(DeviceExtension, 0, 0);
|
||
Status = NO_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (Status == NO_ERROR)
|
||
{
|
||
//
|
||
// Worked with exclusive, also try shared
|
||
//
|
||
|
||
for (i = 0; i < Ranges; i++) VgaAccessRange[i].RangeShareable = TRUE;
|
||
Status = VideoPortVerifyAccessRanges(DeviceExtension, Ranges, VgaAccessRange);
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
// eVb: 1.16 [END]
|