📄 vbemp.c
字号:
/*
* 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
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* TODO:
* - Check input parameters everywhere.
* - Call VideoPortVerifyAccessRanges to reserve the memory we're about
* to map.
*/
/* INCLUDES *******************************************************************/
#include "vbemp.h"
/* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
VP_STATUS STDCALL
DriverEntry(IN PVOID Context1, IN PVOID Context2)
{
VIDEO_HW_INITIALIZATION_DATA InitData;
VideoPortZeroMemory(&InitData, sizeof(InitData));
InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
InitData.HwFindAdapter = VBEFindAdapter;
InitData.HwInitialize = VBEInitialize;
InitData.HwStartIO = VBEStartIO;
InitData.HwResetHw = VBEResetHw;
InitData.HwGetPowerState = VBEGetPowerState;
InitData.HwSetPowerState = VBESetPowerState;
InitData.HwDeviceExtensionSize = sizeof(VBE_DEVICE_EXTENSION);
return VideoPortInitialize(Context1, Context2, &InitData, NULL);
}
/*
* VBEFindAdapter
*
* 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.
*/
VP_STATUS STDCALL
VBEFindAdapter(
IN PVOID HwDeviceExtension,
IN PVOID HwContext,
IN PWSTR ArgumentString,
IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,
OUT PUCHAR Again)
{
return NO_ERROR;
}
/*
* VBESortModesCallback
*
* Helper function for sorting video mode list.
*/
static int
VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA, PVBE_MODEINFO VbeModeInfoB)
{
VideoPortDebugPrint(Info, "VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
VbeModeInfoA->XResolution, VbeModeInfoA->YResolution,
VbeModeInfoA->BitsPerPixel,
VbeModeInfoB->XResolution, VbeModeInfoB->YResolution,
VbeModeInfoB->BitsPerPixel);
/*
* FIXME: Until some reasonable method for changing video modes will
* be available we favor more bits per pixel. It should be changed
* later.
*/
if (VbeModeInfoA->BitsPerPixel < VbeModeInfoB->BitsPerPixel) return -1;
if (VbeModeInfoA->BitsPerPixel > VbeModeInfoB->BitsPerPixel) return 1;
if (VbeModeInfoA->XResolution < VbeModeInfoB->XResolution) return -1;
if (VbeModeInfoA->XResolution > VbeModeInfoB->XResolution) return 1;
if (VbeModeInfoA->YResolution < VbeModeInfoB->YResolution) return -1;
if (VbeModeInfoA->YResolution > VbeModeInfoB->YResolution) return 1;
return 0;
}
/*
* VBESortModes
*
* Simple function for sorting the video mode list. Uses bubble sort.
*/
VOID FASTCALL
VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension)
{
BOOLEAN Finished = FALSE;
ULONG Pos;
int Result;
VBE_MODEINFO TempModeInfo;
USHORT TempModeNumber;
while (!Finished)
{
Finished = TRUE;
for (Pos = 0; Pos < DeviceExtension->ModeCount - 1; Pos++)
{
Result = VBESortModesCallback(
DeviceExtension->ModeInfo + Pos,
DeviceExtension->ModeInfo + Pos + 1);
if (Result > 0)
{
Finished = FALSE;
VideoPortMoveMemory(
&TempModeInfo,
DeviceExtension->ModeInfo + Pos,
sizeof(VBE_MODEINFO));
TempModeNumber = DeviceExtension->ModeNumbers[Pos];
VideoPortMoveMemory(
DeviceExtension->ModeInfo + Pos,
DeviceExtension->ModeInfo + Pos + 1,
sizeof(VBE_MODEINFO));
DeviceExtension->ModeNumbers[Pos] =
DeviceExtension->ModeNumbers[Pos + 1];
VideoPortMoveMemory(
DeviceExtension->ModeInfo + Pos + 1,
&TempModeInfo,
sizeof(VBE_MODEINFO));
DeviceExtension->ModeNumbers[Pos + 1] = TempModeNumber;
}
}
}
}
/*
* VBEInitialize
*
* 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;
/*
* 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)
{
VideoPortDebugPrint(Error, "Failed to get Int 10 service functions (Status %x)\n", Status);
return FALSE;
}
/*
* 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)
{
VideoPortDebugPrint(Error, "Failed to allocate virtual memory (Status %x)\n", Status);
return FALSE;
}
/*
* 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));
/* Verify the VBE signature. */
if (VideoPortCompareMemory(VBEDeviceExtension->VbeInfo.Signature, "VESA", 4) != 4)
{
VideoPortDebugPrint(Warn, "No VBE BIOS present\n");
return FALSE;
}
VideoPortDebugPrint(Trace, "VBE BIOS Present (%d.%d, %8ld Kb)\n",
VBEDeviceExtension->VbeInfo.Version / 0x100,
VBEDeviceExtension->VbeInfo.Version & 0xFF,
VBEDeviceExtension->VbeInfo.TotalMemory * 64);
#ifdef VBE12_SUPPORT
if (VBEDeviceExtension->VbeInfo.Version < 0x102)
#else
if (VBEDeviceExtension->VbeInfo.Version < 0x200)
#endif
{
VideoPortDebugPrint(Warn, "VBE BIOS present, but incompatible version.\n");
return FALSE;
}
}
else
{
VideoPortDebugPrint(Warn, "No VBE BIOS found.\n");
return FALSE;
}
/*
* Build a mode list here that can be later used by
* IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
* calls.
*/
/*
* 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.
*/
for (ModeCount = 0; ; 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;
}
/*
* Allocate space for video modes information.
*/
VBEDeviceExtension->ModeInfo =
VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(VBE_MODEINFO), TAG_VBE);
VBEDeviceExtension->ModeNumbers =
VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(USHORT), TAG_VBE);
/*
* Get the actual mode infos.
*/
for (CurrentMode = 0, SuitableModeCount = 0;
CurrentMode < ModeCount;
CurrentMode++)
{
/* 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->MemoryModel == VBE_MEMORYMODEL_PACKEDPIXEL ||
VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_DIRECTCOLOR) &&
VbeModeInfo->PhysBasePtr != 0)
{
if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR)
{
VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000;
SuitableModeCount++;
}
#ifdef VBE12_SUPPORT
else
{
VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp;
SuitableModeCount++;
}
#endif
}
}
if (SuitableModeCount == 0)
{
VideoPortDebugPrint(Warn, "VBEMP: No video modes supported\n");
return FALSE;
}
VBEDeviceExtension->ModeCount = SuitableModeCount;
/*
* Sort the video mode list according to resolution and bits per pixel.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -