- Use the Video Port driver Int 10 services instead of using undocumented Ke386CallBios function.

- Power management functions implementation. Based on patch by Magnus Olsen <magnus@itkonsult-olsen.com>.
- First steps towards VBE 1.2 support. Based on patch by Magnus Olsen <magnus@itkonsult-olsen.com>.

svn path=/trunk/; revision=9894
This commit is contained in:
Filip Navara 2004-06-26 22:30:34 +00:00
parent 20ac14caf5
commit 0ce9ce5756
2 changed files with 418 additions and 305 deletions

View file

@ -1,8 +1,10 @@
/*
* ReactOS VBE miniport video driver
*
* Copyright (C) 2004 Filip Navara
*
* Power Management and VBE 1.2 support
* Copyright (C) 2004 Magnus Olsen
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@ -19,7 +21,8 @@
*
* TODO:
* - Check input parameters everywhere.
* - Implement power management support.
* - Call VideoPortVerifyAccessRanges to reserve the memory we're about
* to map.
*/
/* INCLUDES *******************************************************************/
@ -47,125 +50,13 @@ DriverEntry(IN PVOID Context1, IN PVOID Context2)
}
/*
* InitializeVideoAddressSpace
* VBEFindAdapter
*
* This function maps the BIOS memory into out virtual address space and
* setups real-mode interrupt table.
* Should detect a VBE compatible display adapter, but it's not possible
* to use video port Int 10 services at this time during initialization,
* so we always return NO_ERROR and do the real work in VBEInitialize.
*/
BOOL FASTCALL
InitializeVideoAddressSpace(VOID)
{
NTSTATUS Status;
PVOID BaseAddress;
PVOID NullAddress;
ULONG ViewSize;
CHAR IVT[1024];
CHAR BDA[256];
LARGE_INTEGER Offset;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING PhysMemName;
HANDLE PhysMemHandle;
/*
* Open the physical memory section
*/
RtlInitUnicodeString(&PhysMemName, L"\\Device\\PhysicalMemory");
InitializeObjectAttributes(&ObjectAttributes, &PhysMemName, 0, NULL, NULL);
Status = ZwOpenSection(&PhysMemHandle, SECTION_ALL_ACCESS, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT(("VBEMP: Couldn't open \\Device\\PhysicalMemory\n"));
return FALSE;
}
/*
* Map the BIOS and device registers into the address space
*/
Offset.QuadPart = 0xa0000;
ViewSize = 0x30000;
BaseAddress = (PVOID)0xa0000;
Status = NtMapViewOfSection(PhysMemHandle, NtCurrentProcess(), &BaseAddress,
0, 8192, &Offset, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT(("VBEMP: Couldn't map physical memory (%x)\n", Status));
NtClose(PhysMemHandle);
return FALSE;
}
NtClose(PhysMemHandle);
if (BaseAddress != (PVOID)0xa0000)
{
DPRINT(("VBEMP: Couldn't map physical memory at the right address "
"(was %x)\n", BaseAddress));
return FALSE;
}
/*
* Map some memory to use for the non-BIOS parts of the v86 mode address
* space
*/
BaseAddress = (PVOID)0x1;
ViewSize = 0x20000;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
&BaseAddress,
0,
&ViewSize,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT(("VBEMP: Failed to allocate virtual memory (Status %x)\n", Status));
return FALSE;
}
if (BaseAddress != (PVOID)0x0)
{
DPRINT(("VBEMP: Failed to allocate virtual memory at right address "
"(was %x)\n", BaseAddress));
return FALSE;
}
/*
* Get the real mode IVT from the kernel
*/
Status = NtVdmControl(0, IVT);
if (!NT_SUCCESS(Status))
{
DPRINT(("VBEMP: NtVdmControl failed (status %x)\n", Status));
return 0;
}
/*
* Copy the real mode IVT into the right place
*/
NullAddress = (PVOID)0x0; /* Workaround for GCC 3.4 */
VideoPortMoveMemory(NullAddress, IVT, 1024);
/*
* Get the BDA from the kernel
*/
Status = NtVdmControl(1, BDA);
if (!NT_SUCCESS(Status))
{
DPRINT(("VBEMP: NtVdmControl failed (status %x)\n", Status));
return FALSE;
}
/*
* Copy the BDA into the right place
*/
VideoPortMoveMemory((PVOID)0x400, BDA, 256);
return TRUE;
}
VP_STATUS STDCALL
VBEFindAdapter(
IN PVOID HwDeviceExtension,
@ -174,79 +65,7 @@ VBEFindAdapter(
IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,
OUT PUCHAR Again)
{
KV86M_REGISTERS BiosRegisters;
DWORD ViewSize;
NTSTATUS Status;
PVBE_INFO VbeInfo;
PVBE_DEVICE_EXTENSION VBEDeviceExtension =
(PVBE_DEVICE_EXTENSION)HwDeviceExtension;
/*
* Map the BIOS parts of memory into our memory space and intitalize
* the real mode interrupt table.
*/
InitializeVideoAddressSpace();
/*
* Allocate a bit of memory that will be later used for VBE transport
* buffer. This memory must be accessible from V86 mode so it must fit
* in the first megabyte of physical memory.
*/
VBEDeviceExtension->TrampolineMemory = (PVOID)0x20000;
ViewSize = 0x400;
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
(PVOID*)&VBEDeviceExtension->TrampolineMemory, 0, &ViewSize, MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT(("Failed to allocate virtual memory (Status %x)\n", Status));
return 0;
}
if (VBEDeviceExtension->TrampolineMemory > (PVOID)(0x100000 - 0x400))
{
DPRINT(("Failed to allocate virtual memory at right address "
"(was %x)\n", VBEDeviceExtension->TrampolineMemory));
return 0;
}
VBEDeviceExtension->PhysicalAddress.QuadPart =
(UINT_PTR)VBEDeviceExtension->TrampolineMemory;
/*
* Get the VBE general information.
*/
VbeInfo = (PVBE_INFO)VBEDeviceExtension->TrampolineMemory;
VideoPortMoveMemory(VbeInfo->Signature, "VBE2", 4);
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = 0x4F00;
BiosRegisters.Edi = VBEDeviceExtension->PhysicalAddress.QuadPart & 0xFF;
BiosRegisters.Es = VBEDeviceExtension->PhysicalAddress.QuadPart >> 4;
Ke386CallBios(0x10, &BiosRegisters);
if (BiosRegisters.Eax == 0x4F)
{
if (VbeInfo->Version >= 0x200)
{
DPRINT(("VBE BIOS Present (%d.%d, %8ld Kb)\n",
VbeInfo->Version / 0x100, VbeInfo->Version & 0xFF,
VbeInfo->TotalMemory * 16));
return NO_ERROR;
}
else
{
DPRINT(("VBE BIOS present, but incompatible version.\n"));
return ERROR_DEV_NOT_EXIST;
}
}
else
{
DPRINT(("No VBE BIOS found.\n"));
return ERROR_DEV_NOT_EXIST;
}
return NO_ERROR;
}
/*
@ -254,60 +73,154 @@ VBEFindAdapter(
*
* Performs the first initialization of the adapter, after the HAL has given
* up control of the video hardware to the video port driver.
*
* This function performs these steps:
* - Gets global VBE information and finds if VBE BIOS is present.
* - Builds the internal mode list using the list of modes provided by
* the VBE.
*/
BOOLEAN STDCALL
VBEInitialize(PVOID HwDeviceExtension)
{
INT10_BIOS_ARGUMENTS BiosRegisters;
VP_STATUS Status;
PVBE_DEVICE_EXTENSION VBEDeviceExtension =
(PVBE_DEVICE_EXTENSION)HwDeviceExtension;
ULONG Length;
ULONG ModeCount;
ULONG SuitableModeCount;
USHORT ModeTemp;
ULONG CurrentMode;
PVBE_MODEINFO VbeModeInfo;
VBE_MODEINFO TempVbeModeInfo;
WORD TempVbeModeNumber;
WORD DefaultMode;
/*
* Get the Int 10 interface that we will use for allocating real
* mode memory and calling the video BIOS.
*/
VBEDeviceExtension->Int10Interface.Version = VIDEO_PORT_INT10_INTERFACE_VERSION_1;
VBEDeviceExtension->Int10Interface.Size = sizeof(VIDEO_PORT_INT10_INTERFACE);
Status = VideoPortQueryServices(
HwDeviceExtension,
VideoPortServicesInt10,
(PINTERFACE)&VBEDeviceExtension->Int10Interface);
if (Status != NO_ERROR)
{
DPRINT(("Failed to get Int 10 service functions (Status %x)\n", Status));
return 0;
}
/*
* Allocate a bit of memory that will be later used for VBE transport
* buffer. This memory must be accessible from V86 mode so it must fit
* in the first megabyte of physical memory.
*/
Length = 0x400;
Status = VBEDeviceExtension->Int10Interface.Int10AllocateBuffer(
VBEDeviceExtension->Int10Interface.Context,
&VBEDeviceExtension->TrampolineMemorySegment,
&VBEDeviceExtension->TrampolineMemoryOffset,
&Length);
if (Status != NO_ERROR)
{
DPRINT(("Failed to allocate virtual memory (Status %x)\n", Status));
return 0;
}
/*
* Get the VBE general information.
*/
VBEDeviceExtension->Int10Interface.Int10WriteMemory(
VBEDeviceExtension->Int10Interface.Context,
VBEDeviceExtension->TrampolineMemorySegment,
VBEDeviceExtension->TrampolineMemoryOffset,
"VBE2",
4);
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = VBE_GET_CONTROLLER_INFORMATION;
BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset;
BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment;
VBEDeviceExtension->Int10Interface.Int10CallBios(
VBEDeviceExtension->Int10Interface.Context,
&BiosRegisters);
if (BiosRegisters.Eax == VBE_SUCCESS)
{
VBEDeviceExtension->Int10Interface.Int10ReadMemory(
VBEDeviceExtension->Int10Interface.Context,
VBEDeviceExtension->TrampolineMemorySegment,
VBEDeviceExtension->TrampolineMemoryOffset,
&VBEDeviceExtension->VbeInfo,
sizeof(VBEDeviceExtension->VbeInfo));
DPRINT(("VBE BIOS Present (%d.%d, %8ld Kb)\n",
VBEDeviceExtension->VbeInfo.Version / 0x100,
VBEDeviceExtension->VbeInfo.Version & 0xFF,
VBEDeviceExtension->VbeInfo.TotalMemory * 16));
#ifdef VBE12_SUPPORT
if (VBEDeviceExtension->VbeInfo.Version < 0x102)
#else
if (VBEDeviceExtension->VbeInfo.Version < 0x200)
#endif
{
DPRINT(("VBE BIOS present, but incompatible version.\n"));
return ERROR_DEV_NOT_EXIST;
}
}
else
{
DPRINT(("No VBE BIOS found.\n"));
return ERROR_DEV_NOT_EXIST;
}
#ifdef VBE12_SUPPORT
if (VBEDeviceExtension->VbeInfo.Version < 0x200)
{
/*
* FIXME: Build a mode list here based on the total memory
* available on the video card and the video mode tables
* from the VBE specification.
*/
return ERROR_NOT_SUPPORTED;
}
#endif
/*
* Build a mode list here that can be later used by
* IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
* calls.
*/
ULONG ModeCount;
ULONG CurrentMode;
KV86M_REGISTERS BiosRegisters;
PVBE_DEVICE_EXTENSION VBEDeviceExtension =
(PVBE_DEVICE_EXTENSION)HwDeviceExtension;
PVBE_INFO VbeInfo;
PVBE_MODEINFO VbeModeInfo;
VBE_MODEINFO TempVbeModeInfo;
WORD TempVbeModeNumber;
WORD *ModeList;
WORD DefaultMode;
InitializeVideoAddressSpace();
/*
* Get the VBE general information.
*/
VbeInfo = (PVBE_INFO)VBEDeviceExtension->TrampolineMemory;
VideoPortMoveMemory(VbeInfo->Signature, "VBE2", 4);
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = 0x4F00;
BiosRegisters.Edi = VBEDeviceExtension->PhysicalAddress.QuadPart & 0xFF;
BiosRegisters.Es = VBEDeviceExtension->PhysicalAddress.QuadPart >> 4;
Ke386CallBios(0x10, &BiosRegisters);
VBEDeviceExtension->VBEVersion = VbeInfo->Version;
VBEDeviceExtension->VGACompatible = !(VbeInfo->Capabilities & 2);
/*
* Get the number of supported video modes.
*
* No need to be map the memory. It's either in the video BIOS memory or
* in our trampoline memory. In either case the memory is already mapped.
*/
/*
* No need to be mapped, it's either in BIOS memory or in our trampoline
* memory. Both of them are already mapped.
*/
ModeList = (WORD *)((HIWORD(VbeInfo->VideoModePtr) << 4) + LOWORD(VbeInfo->VideoModePtr));
for (CurrentMode = 0, ModeCount = 0;
ModeList[CurrentMode] != 0xFFFF && ModeList[CurrentMode] != 0;
CurrentMode++)
for (ModeCount = 0; ; ModeCount++)
{
ModeCount++;
/* Read the VBE mode number. */
VBEDeviceExtension->Int10Interface.Int10ReadMemory(
VBEDeviceExtension->Int10Interface.Context,
HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr),
LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (ModeCount << 1),
&ModeTemp,
sizeof(ModeTemp));
/* End of list? */
if (ModeTemp == 0xFFFF || ModeTemp == 0)
break;
}
/*
@ -323,35 +236,61 @@ VBEInitialize(PVOID HwDeviceExtension)
* Get the actual mode infos.
*/
for (CurrentMode = 0, ModeCount = 0, DefaultMode = 0;
ModeList[CurrentMode] != 0xFFFF && ModeList[CurrentMode] != 0;
for (CurrentMode = 0, SuitableModeCount = 0, DefaultMode = 0;
CurrentMode < ModeCount;
CurrentMode++)
{
BiosRegisters.Eax = 0x4F01;
BiosRegisters.Ecx = ModeList[CurrentMode];
BiosRegisters.Edi = (VBEDeviceExtension->PhysicalAddress.QuadPart + 0x200) & 0xF;
BiosRegisters.Es = (VBEDeviceExtension->PhysicalAddress.QuadPart + 0x200) >> 4;
Ke386CallBios(0x10, &BiosRegisters);
VbeModeInfo = (PVBE_MODEINFO)(VBEDeviceExtension->TrampolineMemory + 0x200);
if (BiosRegisters.Eax == 0x4F &&
/* Read the VBE mode number. */
VBEDeviceExtension->Int10Interface.Int10ReadMemory(
VBEDeviceExtension->Int10Interface.Context,
HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr),
LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (CurrentMode << 1),
&ModeTemp,
sizeof(ModeTemp));
/* Call VBE BIOS to read the mode info. */
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = VBE_GET_MODE_INFORMATION;
BiosRegisters.Ecx = ModeTemp;
BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset + 0x200;
BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment;
VBEDeviceExtension->Int10Interface.Int10CallBios(
VBEDeviceExtension->Int10Interface.Context,
&BiosRegisters);
/* Read the VBE mode info. */
VBEDeviceExtension->Int10Interface.Int10ReadMemory(
VBEDeviceExtension->Int10Interface.Context,
VBEDeviceExtension->TrampolineMemorySegment,
VBEDeviceExtension->TrampolineMemoryOffset + 0x200,
VBEDeviceExtension->ModeInfo + SuitableModeCount,
sizeof(VBE_MODEINFO));
VbeModeInfo = VBEDeviceExtension->ModeInfo + SuitableModeCount;
/* Is this mode acceptable? */
if (BiosRegisters.Eax == VBE_SUCCESS &&
VbeModeInfo->XResolution >= 640 &&
VbeModeInfo->YResolution >= 480 &&
(VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR))
{
VideoPortMoveMemory(VBEDeviceExtension->ModeInfo + ModeCount,
VBEDeviceExtension->TrampolineMemory + 0x200,
sizeof(VBE_MODEINFO));
VBEDeviceExtension->ModeNumbers[ModeCount] = ModeList[CurrentMode] | 0x4000;
VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000;
if (VbeModeInfo->XResolution == 640 &&
VbeModeInfo->YResolution == 480 &&
VbeModeInfo->BitsPerPixel == 32)
{
DefaultMode = ModeCount;
DefaultMode = SuitableModeCount;
}
ModeCount++;
SuitableModeCount++;
}
}
if (SuitableModeCount == 0)
{
DPRINT(("VBEMP: No video modes supported\n"));
return FALSE;
}
/*
* Exchange the default mode so it's at the first place in list.
*/
@ -366,13 +305,7 @@ VBEInitialize(PVOID HwDeviceExtension)
VBEDeviceExtension->ModeNumbers[0] = VBEDeviceExtension->ModeNumbers[DefaultMode];
VBEDeviceExtension->ModeNumbers[DefaultMode] = TempVbeModeNumber;
if (ModeCount == 0)
{
DPRINT(("VBEMP: No video modes supported\n"));
return FALSE;
}
VBEDeviceExtension->ModeCount = ModeCount;
VBEDeviceExtension->ModeCount = SuitableModeCount;
/*
* Print the supported video modes when DBG is set.
@ -380,7 +313,7 @@ VBEInitialize(PVOID HwDeviceExtension)
#ifdef DBG
for (CurrentMode = 0;
CurrentMode < ModeCount;
CurrentMode < SuitableModeCount;
CurrentMode++)
{
DPRINT(("%dx%dx%d\n",
@ -443,8 +376,14 @@ VBEStartIO(
break;
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
{
RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
return TRUE;
}
Result = VBEUnmapVideoMemory(
(PVBE_DEVICE_EXTENSION)HwDeviceExtension,
(PVIDEO_MEMORY)RequestPacket->InputBuffer,
RequestPacket->StatusBlock);
break;
@ -538,7 +477,62 @@ VBEGetPowerState(
ULONG HwId,
PVIDEO_POWER_MANAGEMENT VideoPowerControl)
{
return ERROR_INVALID_FUNCTION;
INT10_BIOS_ARGUMENTS BiosRegisters;
PVBE_DEVICE_EXTENSION VBEDeviceExtension =
(PVBE_DEVICE_EXTENSION)HwDeviceExtension;
if (HwId != DISPLAY_ADAPTER_HW_ID ||
VideoPowerControl->Length < sizeof(VIDEO_POWER_MANAGEMENT))
return ERROR_INVALID_FUNCTION;
/*
* Get general power support information.
*/
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS;
BiosRegisters.Ebx = 0;
BiosRegisters.Edi = 0;
BiosRegisters.SegEs = 0;
VBEDeviceExtension->Int10Interface.Int10CallBios(
VBEDeviceExtension->Int10Interface.Context,
&BiosRegisters);
if (BiosRegisters.Eax == VBE_NOT_SUPPORTED)
return ERROR_NOT_SUPPORTED;
if (BiosRegisters.Eax != VBE_SUCCESS)
return ERROR_INVALID_FUNCTION;
/*
* Get current power state.
*/
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS;
BiosRegisters.Ebx = 0x2;
BiosRegisters.Edi = 0;
BiosRegisters.SegEs = 0;
VBEDeviceExtension->Int10Interface.Int10CallBios(
VBEDeviceExtension->Int10Interface.Context,
&BiosRegisters);
if (BiosRegisters.Eax == VBE_SUCCESS)
{
VideoPowerControl->DPMSVersion = BiosRegisters.Ebx & 0xFF;
switch (BiosRegisters.Ebx >> 8)
{
case 0: VideoPowerControl->PowerState = VideoPowerOn; break;
case 1: VideoPowerControl->PowerState = VideoPowerStandBy; break;
case 2: VideoPowerControl->PowerState = VideoPowerSuspend; break;
case 4: VideoPowerControl->PowerState = VideoPowerOff; break;
case 5: VideoPowerControl->PowerState = VideoPowerOn; break;
default: VideoPowerControl->PowerState = VideoPowerUnspecified;
}
return NO_ERROR;
}
return ERROR_NOT_SUPPORTED;
}
/*
@ -553,7 +547,45 @@ VBESetPowerState(
ULONG HwId,
PVIDEO_POWER_MANAGEMENT VideoPowerControl)
{
return ERROR_INVALID_FUNCTION;
INT10_BIOS_ARGUMENTS BiosRegisters;
PVBE_DEVICE_EXTENSION VBEDeviceExtension =
(PVBE_DEVICE_EXTENSION)HwDeviceExtension;
if (HwId != DISPLAY_ADAPTER_HW_ID ||
VideoPowerControl->Length < sizeof(VIDEO_POWER_MANAGEMENT) ||
VideoPowerControl->PowerState < VideoPowerOn ||
VideoPowerControl->PowerState > VideoPowerHibernate)
return ERROR_INVALID_FUNCTION;
if (VideoPowerControl->PowerState == VideoPowerHibernate)
return NO_ERROR;
/*
* Set current power state.
*/
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS;
BiosRegisters.Ebx = 1;
BiosRegisters.Edi = 0;
BiosRegisters.SegEs = 0;
switch (VideoPowerControl->PowerState)
{
case VideoPowerStandBy: BiosRegisters.Ebx |= 0x100; break;
case VideoPowerSuspend: BiosRegisters.Ebx |= 0x200; break;
case VideoPowerOff: BiosRegisters.Ebx |= 0x400; break;
}
VBEDeviceExtension->Int10Interface.Int10CallBios(
VBEDeviceExtension->Int10Interface.Context,
&BiosRegisters);
if (BiosRegisters.Eax == VBE_NOT_SUPPORTED)
return ERROR_NOT_SUPPORTED;
if (BiosRegisters.Eax != VBE_SUCCESS)
return ERROR_INVALID_FUNCTION;
return VBE_SUCCESS;
}
/*
@ -568,13 +600,21 @@ VBESetCurrentMode(
PVIDEO_MODE RequestedMode,
PSTATUS_BLOCK StatusBlock)
{
KV86M_REGISTERS BiosRegisters;
INT10_BIOS_ARGUMENTS BiosRegisters;
if (RequestedMode->RequestedMode >= DeviceExtension->ModeCount)
{
return ERROR_INVALID_PARAMETER;
}
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = 0x4F02;
BiosRegisters.Eax = VBE_SET_VBE_MODE;
BiosRegisters.Ebx = DeviceExtension->ModeNumbers[RequestedMode->RequestedMode];
Ke386CallBios(0x10, &BiosRegisters);
if (BiosRegisters.Eax == 0x4F)
DeviceExtension->Int10Interface.Int10CallBios(
DeviceExtension->Int10Interface.Context,
&BiosRegisters);
if (BiosRegisters.Eax == VBE_SUCCESS)
{
DeviceExtension->CurrentMode = RequestedMode->RequestedMode;
}
@ -583,7 +623,8 @@ VBESetCurrentMode(
DPRINT(("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters.Eax));
DeviceExtension->CurrentMode = -1;
}
return (BiosRegisters.Eax == 0x4F);
return BiosRegisters.Eax == VBE_SUCCESS;
}
/*
@ -598,14 +639,16 @@ VBEResetDevice(
PVBE_DEVICE_EXTENSION DeviceExtension,
PSTATUS_BLOCK StatusBlock)
{
KV86M_REGISTERS BiosRegisters;
INT10_BIOS_ARGUMENTS BiosRegisters;
InitializeVideoAddressSpace();
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = 0x4F02;
BiosRegisters.Eax = VBE_SET_VBE_MODE;
BiosRegisters.Ebx = 0x3;
Ke386CallBios(0x10, &BiosRegisters);
return TRUE;
DeviceExtension->Int10Interface.Int10CallBios(
DeviceExtension->Int10Interface.Context,
&BiosRegisters);
return BiosRegisters.Eax == VBE_SUCCESS;
}
/*
@ -623,16 +666,28 @@ VBEMapVideoMemory(
PSTATUS_BLOCK StatusBlock)
{
PHYSICAL_ADDRESS FrameBuffer;
ULONG inIoSpace = 0;
ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY;
StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION);
FrameBuffer.QuadPart =
DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].PhysBasePtr;
MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
MapInformation->VideoRamLength =
DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].BytesPerScanLine *
DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution;
if (DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].ModeAttributes &
VBE_MODEATTR_LINEAR)
{
FrameBuffer.QuadPart =
DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].PhysBasePtr;
MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
MapInformation->VideoRamLength =
DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].BytesPerScanLine *
DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution;
}
#ifdef VBE12_SUPPORT
else
{
FrameBuffer.QuadPart = 0xA0000;
MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
MapInformation->VideoRamLength = 0x10000;
}
#endif
VideoPortMapMemory(DeviceExtension, FrameBuffer,
&MapInformation->VideoRamLength, &inIoSpace,
@ -641,8 +696,6 @@ VBEMapVideoMemory(
MapInformation->FrameBufferBase = MapInformation->VideoRamBase;
MapInformation->FrameBufferLength = MapInformation->VideoRamLength;
DeviceExtension->FrameBufferMemory = MapInformation->VideoRamBase;
return TRUE;
}
@ -656,9 +709,10 @@ VBEMapVideoMemory(
BOOL FASTCALL
VBEUnmapVideoMemory(
PVBE_DEVICE_EXTENSION DeviceExtension,
PVIDEO_MEMORY VideoMemory,
PSTATUS_BLOCK StatusBlock)
{
VideoPortUnmapMemory(DeviceExtension, DeviceExtension->FrameBufferMemory,
VideoPortUnmapMemory(DeviceExtension, VideoMemory->RequestedVirtualAddress,
NULL);
return TRUE;
}
@ -709,7 +763,7 @@ VBEQueryMode(
VideoMode->YMillimeter = 0; /* FIXME */
if (VBEMode->BitsPerPixel > 8)
{
if (DeviceExtension->VBEVersion < 0x300)
if (DeviceExtension->VbeInfo.Version < 0x300)
{
VideoMode->NumberRedBits = VBEMode->RedMaskSize;
VideoMode->NumberGreenBits = VBEMode->GreenMaskSize;
@ -813,14 +867,19 @@ VBESetColorRegisters(
PVIDEO_CLUT ColorLookUpTable,
PSTATUS_BLOCK StatusBlock)
{
KV86M_REGISTERS BiosRegisters;
INT10_BIOS_ARGUMENTS BiosRegisters;
ULONG Entry;
PULONG OutputEntry;
ULONG OutputBuffer[256];
if (ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry > 256)
return FALSE;
if (DeviceExtension->VGACompatible)
/*
* For VGA compatible adapters program the color registers directly.
*/
if (!(DeviceExtension->VbeInfo.Capabilities & 2))
{
for (Entry = ColorLookUpTable->FirstEntry;
Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
@ -831,6 +890,7 @@ VBESetColorRegisters(
VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green);
VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
}
return TRUE;
}
else
@ -841,7 +901,7 @@ VBESetColorRegisters(
*/
for (Entry = ColorLookUpTable->FirstEntry,
OutputEntry = DeviceExtension->TrampolineMemory;
OutputEntry = OutputBuffer;
Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
Entry++, OutputEntry++)
{
@ -851,13 +911,24 @@ VBESetColorRegisters(
(ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
}
BiosRegisters.Eax = 0x4F09;
DeviceExtension->Int10Interface.Int10WriteMemory(
DeviceExtension->Int10Interface.Context,
DeviceExtension->TrampolineMemorySegment,
DeviceExtension->TrampolineMemoryOffset,
OutputBuffer,
(OutputEntry - OutputBuffer) * sizeof(ULONG));
VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
BiosRegisters.Eax = VBE_SET_GET_PALETTE_DATA;
BiosRegisters.Ebx = 0;
BiosRegisters.Ecx = ColorLookUpTable->NumEntries;
BiosRegisters.Edx = ColorLookUpTable->FirstEntry;
BiosRegisters.Edi = DeviceExtension->PhysicalAddress.QuadPart & 0xF;
BiosRegisters.Es = DeviceExtension->PhysicalAddress.QuadPart >> 4;
Ke386CallBios(0x10, &BiosRegisters);
return (BiosRegisters.Eax == 0x4F);
BiosRegisters.Edi = DeviceExtension->TrampolineMemoryOffset;
BiosRegisters.SegEs = DeviceExtension->TrampolineMemorySegment;
DeviceExtension->Int10Interface.Int10CallBios(
DeviceExtension->Int10Interface.Context,
&BiosRegisters);
return BiosRegisters.Eax == VBE_SUCCESS;
}
}

View file

@ -31,26 +31,67 @@
#include <ddk/ntddvdeo.h>
#include <ddk/ntapi.h>
/* For Ke386CallBios */
#include "internal/v86m.h"
/* FIXME: Missing define in w32api! */
#ifndef NtCurrentProcess
#define NtCurrentProcess() ((HANDLE)(LONG_PTR)-1)
#endif
#ifdef DBG
#define DPRINT(arg) DbgPrint arg;
#else
#define DPRINT(arg)
#endif
/*
* Compile-time define to get VBE 1.2 support. The implementation
* is far from complete now and so it's left undefined.
*/
/* #define VBE12_SUPPORT */
#include <pshpack1.h>
/*
* VBE specification defined structure for general adapter info
* returned by function 0x4F00.
* VBE Command Definitions
*/
#define VBE_GET_CONTROLLER_INFORMATION 0x4F00
#define VBE_GET_MODE_INFORMATION 0x4F01
#define VBE_SET_VBE_MODE 0x4F02
#define VBE_GET_CURRENT_VBE_MODE 0x4F03
#define VBE_SAVE_RESTORE_STATE 0x4F04
#define VBE_DISPLAY_WINDOW_CONTROL 0x4F05
#define VBE_SET_GET_LOGICAL_SCAN_LINE_LENGTH 0x4F06
#define VBE_SET_GET_DISPLAY_START 0x4F07
#define VBE_SET_GET_DAC_PALETTE_FORMAT 0x4F08
#define VBE_SET_GET_PALETTE_DATA 0x4F09
/* VBE 2.0+ */
#define VBE_RETURN_PROTECTED_MODE_INTERFACE 0x4F0A
#define VBE_GET_SET_PIXEL_CLOCK 0x4F0B
/* Extensions */
#define VBE_POWER_MANAGEMENT_EXTENSIONS 0x4F10
#define VBE_FLAT_PANEL_INTERFACE_EXTENSIONS 0x4F11
#define VBE_AUDIO_INTERFACE_EXTENSIONS 0x4F12
#define VBE_OEM_EXTENSIONS 0x4F13
#define VBE_DISPLAY_DATA_CHANNEL 0x4F14
/*
* VBE Video Mode Information Attributes
*/
#define VBE_MODEATTR_LINEAR 0x80
/*
* VBE Return Codes
*/
#define VBE_SUCCESS 0x4F
#define VBE_UNSUCCESSFUL 0x14F
#define VBE_NOT_SUPPORTED 0x24F
#define VBE_FUNCTION_INVALID 0x34F
/*
* VBE specification defined structure for general adapter info
* returned by function VBE_GET_CONTROLLER_INFORMATION command.
*/
typedef struct
{
CHAR Signature[4];
@ -69,9 +110,11 @@ typedef struct
/*
* VBE specification defined structure for specific video mode
* info returned by function 0x4F01.
* info returned by function VBE_GET_MODE_INFORMATION command.
*/
typedef struct {
typedef struct
{
/* Mandatory information for all VBE revisions */
WORD ModeAttributes;
BYTE WinAAttributes;
@ -129,21 +172,19 @@ typedef struct {
CHAR Reserved4[189];
} VBE_MODEINFO, *PVBE_MODEINFO;
#define VBE_MODEATTR_LINEAR 0x80
#include <poppack.h>
typedef struct {
/* Trampoline memory for communication with VBE real-mode interface. */
PHYSICAL_ADDRESS PhysicalAddress;
PVOID TrampolineMemory;
typedef struct
{
/* Interface to Int10 calls */
VIDEO_PORT_INT10_INTERFACE Int10Interface;
/* Pointer to mapped frame buffer memory */
PVOID FrameBufferMemory;
/* Trampoline memory for communication with VBE real-mode interface */
USHORT TrampolineMemorySegment;
USHORT TrampolineMemoryOffset;
/* General controller/BIOS information */
BOOL VGACompatible;
WORD VBEVersion;
VBE_INFO VbeInfo;
/* Saved information about video modes */
ULONG ModeCount;
@ -207,6 +248,7 @@ VBEMapVideoMemory(
BOOL FASTCALL
VBEUnmapVideoMemory(
PVBE_DEVICE_EXTENSION DeviceExtension,
PVIDEO_MEMORY VideoMemory,
PSTATUS_BLOCK StatusBlock);
BOOL FASTCALL