diff --git a/reactos/drivers/video/miniport/vbe/vbemp.c b/reactos/drivers/video/miniport/vbe/vbemp.c index 960efcfd16f..07f881f5e11 100644 --- a/reactos/drivers/video/miniport/vbe/vbemp.c +++ b/reactos/drivers/video/miniport/vbe/vbemp.c @@ -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; } } diff --git a/reactos/drivers/video/miniport/vbe/vbemp.h b/reactos/drivers/video/miniport/vbe/vbemp.h index 58ceed90aa4..cae4716e10f 100644 --- a/reactos/drivers/video/miniport/vbe/vbemp.h +++ b/reactos/drivers/video/miniport/vbe/vbemp.h @@ -31,26 +31,67 @@ #include #include -/* 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 /* - * 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 -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