Detect Bad graphic Bios, Some graphice card report VBE 2.0 when the are VBE 1.2....
[reactos.git] / reactos / drivers / video / miniport / vbe / vbemp.c
index cf14e31..40fdf80 100644 (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
  *
  * TODO:
  * - Check input parameters everywhere.
- * - Implement power management support.
+ * - Call VideoPortVerifyAccessRanges to reserve the memory we're about
+ *   to map.
  */
 
 /* INCLUDES *******************************************************************/
 
 #include "vbemp.h"
 
+#define NDEBUG
+#include <debug.h>
+
 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
 
 VP_STATUS STDCALL
@@ -38,154 +44,155 @@ DriverEntry(IN PVOID Context1, IN PVOID Context2)
    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);
 }
 
 /*
- * 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)
+VP_STATUS STDCALL
+VBEFindAdapter(
+   IN PVOID HwDeviceExtension,
+   IN PVOID HwContext,
+   IN PWSTR ArgumentString,
+   IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,
+   OUT PUCHAR Again)
 {
-   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;
+   return NO_ERROR;
+}
 
-   /*
-    * Open the physical memory section
-    */
+/*
+ * VBESortModesCallback
+ *
+ * Helper function for sorting video mode list.
+ */
 
-   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;
-   }
+static int
+VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA, PVBE_MODEINFO VbeModeInfoB)
+{
+   DPRINT("VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
+      VbeModeInfoA->XResolution, VbeModeInfoA->YResolution,
+      VbeModeInfoA->BitsPerPixel,
+      VbeModeInfoB->XResolution, VbeModeInfoB->YResolution,
+      VbeModeInfoB->BitsPerPixel);
 
    /*
-    * Map the BIOS and device registers into the address space
+    * 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;
+}
 
-   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;
-   }
+/*
+ * VBESortModes
+ *
+ * Simple function for sorting the video mode list. Uses bubble sort.
+ */
 
-   /*
-    * Map some memory to use for the non-BIOS parts of the v86 mode address
-    * space
-    */
+VOID FASTCALL
+VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension)
+{
+   BOOLEAN Finished = FALSE;
+   ULONG Pos;
+   int Result;
+   VBE_MODEINFO TempModeInfo;
+   WORD TempModeNumber;
 
-   BaseAddress = (PVOID)0x1;
-   ViewSize = 0x20000;
-   Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
-                                   &BaseAddress,
-                                   0,
-                                   &ViewSize,
-                                   MEM_COMMIT,
-                                   PAGE_EXECUTE_READWRITE);
-   if (!NT_SUCCESS(Status))
+   while (!Finished)
    {
-      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;
+      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;
+         }
+      }
    }
+}
 
-   /*
-    * Get the real mode IVT from the kernel
-    */
+/*
+ * 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.
+ */
 
-   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
-    */
+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;
 
-   NullAddress = (PVOID)0x0; /* Workaround for GCC 3.4 */
-   VideoPortMoveMemory(NullAddress, IVT, 1024);
-   
    /*
-    * Get the BDA from the kernel
+    * Get the Int 10 interface that we will use for allocating real
+    * mode memory and calling the video BIOS.
     */
 
-   Status = NtVdmControl(1, BDA);
-   if (!NT_SUCCESS(Status))
+   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(("VBEMP: NtVdmControl failed (status %x)\n", Status));
+      DPRINT1("Failed to get Int 10 service functions (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,
-   IN PVOID HwContext,
-   IN PWSTR ArgumentString,
-   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
@@ -193,120 +200,101 @@ VBEFindAdapter(
     * 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))
+   Length = 0x400;
+   Status = VBEDeviceExtension->Int10Interface.Int10AllocateBuffer(
+      VBEDeviceExtension->Int10Interface.Context,
+      &VBEDeviceExtension->TrampolineMemorySegment,
+      &VBEDeviceExtension->TrampolineMemoryOffset,
+      &Length);
+
+   if (Status != NO_ERROR)
    {
-      DPRINT(("Failed to allocate virtual memory at right address "
-              "(was %x)\n", VBEDeviceExtension->TrampolineMemory));
-      return 0;
+      DPRINT1("Failed to allocate virtual memory (Status %x)\n", Status);
+      return FALSE;
    }
-   VBEDeviceExtension->PhysicalAddress.QuadPart = 
-      (UINT_PTR)VBEDeviceExtension->TrampolineMemory;
 
    /*
     * Get the VBE general information.
     */
-   
-   VbeInfo = (PVBE_INFO)VBEDeviceExtension->TrampolineMemory;
-   VideoPortMoveMemory(VbeInfo->Signature, "VBE2", 4);
+
+   VBEDeviceExtension->Int10Interface.Int10WriteMemory(
+      VBEDeviceExtension->Int10Interface.Context,
+      VBEDeviceExtension->TrampolineMemorySegment,
+      VBEDeviceExtension->TrampolineMemoryOffset,
+      "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)
+   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)
    {
-      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
+      VBEDeviceExtension->Int10Interface.Int10ReadMemory(
+         VBEDeviceExtension->Int10Interface.Context,
+         VBEDeviceExtension->TrampolineMemorySegment,
+         VBEDeviceExtension->TrampolineMemoryOffset,
+         &VBEDeviceExtension->VbeInfo,
+         sizeof(VBEDeviceExtension->VbeInfo));
+
+         /* Dectect Bad VBE BIOS some Graphice card report 0x200 when they are VBE 1.2 */
+         if (VBEDeviceExtension->VbeInfo.OemVendorNamePtr == 0 && VBEDeviceExtension->VbeInfo.Version == 0x200)
+         {
+         VBEDeviceExtension->VbeInfo.Version = 0x102;
+         }
+         
+      
+      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;
+         DPRINT("VBE BIOS present, but incompatible version.\n");
+         return FALSE;
       }
    }
    else
    {
-      DPRINT(("No VBE BIOS found.\n"));
-
-      return ERROR_DEV_NOT_EXIST;
+      DPRINT("No VBE BIOS found.\n");
+      return FALSE;
    }
-}
-
-/*
- * VBEInitialize
- *
- * Performs the first initialization of the adapter, after the HAL has given
- * up control of the video hardware to the video port driver.
- */
 
-BOOLEAN STDCALL
-VBEInitialize(PVOID HwDeviceExtension)
-{
    /*
     * 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;
    }
 
    /*
@@ -321,71 +309,88 @@ VBEInitialize(PVOID HwDeviceExtension)
    /*
     * Get the actual mode infos.
     */
-   
-   for (CurrentMode = 0, ModeCount = 0, DefaultMode = 0;
-        ModeList[CurrentMode] != 0xFFFF && CurrentMode < 0x400;
+
+   for (CurrentMode = 0, SuitableModeCount = 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))
+          (VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_PACKEDPIXEL ||
+           VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_DIRECTCOLOR))
       {
-         VideoPortMoveMemory(VBEDeviceExtension->ModeInfo + ModeCount, 
-                             VBEDeviceExtension->TrampolineMemory + 0x200,
-                             sizeof(VBE_MODEINFO));
-         VBEDeviceExtension->ModeNumbers[ModeCount] = ModeList[CurrentMode] | 0x4000;
-         if (VbeModeInfo->XResolution == 640 &&
-             VbeModeInfo->YResolution == 480 &&
-             VbeModeInfo->BitsPerPixel == 32)
+         if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR)
          {
-            DefaultMode = ModeCount;
+            VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000;
+            SuitableModeCount++;
          }
-         ModeCount++;
+#ifdef VBE12_SUPPORT
+         else
+         {
+            VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp;
+            SuitableModeCount++;
+         }
+#endif
       }
    }
 
-   /*
-    * Exchange the default mode so it's at the first place in list.
-    */
-
-   VideoPortMoveMemory(&TempVbeModeInfo, VBEDeviceExtension->ModeInfo,
-      sizeof(VBE_MODEINFO));
-   VideoPortMoveMemory(VBEDeviceExtension->ModeInfo, VBEDeviceExtension->ModeInfo + DefaultMode,
-      sizeof(VBE_MODEINFO));
-   VideoPortMoveMemory(VBEDeviceExtension->ModeInfo + DefaultMode, &TempVbeModeInfo,
-      sizeof(VBE_MODEINFO));
-   TempVbeModeNumber = VBEDeviceExtension->ModeNumbers[0];
-   VBEDeviceExtension->ModeNumbers[0] = VBEDeviceExtension->ModeNumbers[DefaultMode];
-   VBEDeviceExtension->ModeNumbers[DefaultMode] = TempVbeModeNumber;
-
-   if (ModeCount == 0)
+   if (SuitableModeCount == 0)
    {
-      DPRINT(("VBEMP: No video modes supported\n"));
+      DPRINT("VBEMP: No video modes supported\n");
       return FALSE;
    }
-   
-   VBEDeviceExtension->ModeCount = ModeCount;
+
+   VBEDeviceExtension->ModeCount = SuitableModeCount;
 
    /*
-    * Print the supported video modes when DBG is set.
+    * Sort the video mode list according to resolution and bits per pixel.
     */
 
-#ifdef DBG
+   VBESortModes(VBEDeviceExtension);
+
+   /*
+    * Print the supported video modes when NDEBUG is not set.
+    */
+
+#ifndef NDEBUG
    for (CurrentMode = 0;
-        CurrentMode < ModeCount;
+        CurrentMode < SuitableModeCount;
         CurrentMode++)
    {
-      DPRINT(("%dx%dx%d\n",
+      DPRINT("%dx%dx%d\n",
          VBEDeviceExtension->ModeInfo[CurrentMode].XResolution,
          VBEDeviceExtension->ModeInfo[CurrentMode].YResolution,
-         VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel));
+         VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel);
    }
 #endif
 
@@ -410,7 +415,7 @@ VBEStartIO(
    switch (RequestPacket->IoControlCode)
    {
       case IOCTL_VIDEO_SET_CURRENT_MODE:
-         if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) 
+         if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
          {
             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
             return TRUE;
@@ -429,7 +434,7 @@ VBEStartIO(
 
       case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
          if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) ||
-             RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) 
+             RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
          {
             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
             return TRUE;
@@ -442,13 +447,19 @@ 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;
 
       case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
-         if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES)) 
+         if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES))
          {
             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
             return TRUE;
@@ -461,7 +472,7 @@ VBEStartIO(
 
       case IOCTL_VIDEO_QUERY_AVAIL_MODES:
          if (RequestPacket->OutputBufferLength <
-             ((PVBE_DEVICE_EXTENSION)HwDeviceExtension)->ModeCount * sizeof(VIDEO_MODE_INFORMATION)) 
+             ((PVBE_DEVICE_EXTENSION)HwDeviceExtension)->ModeCount * sizeof(VIDEO_MODE_INFORMATION))
          {
             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
             return TRUE;
@@ -476,7 +487,7 @@ VBEStartIO(
          if (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) ||
              RequestPacket->InputBufferLength <
              (((PVIDEO_CLUT)RequestPacket->InputBuffer)->NumEntries * sizeof(ULONG)) +
-             sizeof(VIDEO_CLUT))
+             FIELD_OFFSET(VIDEO_CLUT, LookupTable))
          {
             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
             return TRUE;
@@ -488,7 +499,7 @@ VBEStartIO(
          break;
 
       case IOCTL_VIDEO_QUERY_CURRENT_MODE:
-         if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION)) 
+         if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
          {
             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
             return TRUE;
@@ -498,18 +509,82 @@ VBEStartIO(
             (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
             RequestPacket->StatusBlock);
          break;
-         
+
       default:
          RequestPacket->StatusBlock->Status = STATUS_NOT_IMPLEMENTED;
          return FALSE;
    }
-  
+
    if (Result)
       RequestPacket->StatusBlock->Status = STATUS_SUCCESS;
 
    return TRUE;
 }
 
+/*
+ * VBEResetHw
+ *
+ * This function is called to reset the hardware to a known state.
+ */
+
+BOOLEAN STDCALL
+VBEResetHw(
+   PVOID DeviceExtension,
+   ULONG Columns,
+   ULONG Rows)
+{
+   INT10_BIOS_ARGUMENTS BiosRegisters;
+   PVBE_DEVICE_EXTENSION VBEDeviceExtension =
+     (PVBE_DEVICE_EXTENSION)DeviceExtension;
+
+   if (!VBEResetDevice(DeviceExtension, NULL))
+      return FALSE;
+
+   /* Change number of columns/rows */
+   VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
+
+   if (Columns == 80 && Rows == 25)
+   {
+      /* Default text size, don't change anything. */
+      return TRUE;
+   }
+   else if (Columns == 80 && Rows == 28)
+   {
+      /* Use 9x14 font (80x28) */
+      BiosRegisters.Eax = 0x1111;
+   }
+   else if (Columns == 80 && Rows == 43)
+   {
+      /* Use 8x8 font in 350 scans mode (80x43) */
+      BiosRegisters.Eax = 0x1201;
+      BiosRegisters.Ebx = 0x30;
+      VBEDeviceExtension->Int10Interface.Int10CallBios(
+         VBEDeviceExtension->Int10Interface.Context,
+         &BiosRegisters);
+
+      BiosRegisters.Eax = 0x3;
+      BiosRegisters.Ebx = 0;
+      VBEDeviceExtension->Int10Interface.Int10CallBios(
+         VBEDeviceExtension->Int10Interface.Context,
+         &BiosRegisters);
+
+      BiosRegisters.Eax = 0x1112;
+   }
+   else if (Columns == 80 && Rows == 50)
+   {
+      /* Use 8x8 font (80x50) */
+      BiosRegisters.Eax = 0x1112;
+   }
+   else
+      return FALSE;
+
+   VBEDeviceExtension->Int10Interface.Int10CallBios(
+      VBEDeviceExtension->Int10Interface.Context,
+      &BiosRegisters);
+
+   return TRUE;
+}
+
 /*
  * VBEGetPowerState
  *
@@ -522,7 +597,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;
 }
 
 /*
@@ -537,7 +667,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;
 }
 
 /*
@@ -552,29 +720,38 @@ 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;
    }
    else
    {
-      DPRINT(("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters.Eax));
+      DPRINT1("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters.Eax);
       DeviceExtension->CurrentMode = -1;
    }
-   return (BiosRegisters.Eax == 0x4F);
+
+   return BiosRegisters.Eax == VBE_SUCCESS;
 }
 
 /*
  * VBEResetDevice
  *
  * Resets the video hardware to the default mode, to which it was initialized
- * at system boot. 
+ * at system boot.
  */
 
 BOOL FASTCALL
@@ -582,20 +759,23 @@ VBEResetDevice(
    PVBE_DEVICE_EXTENSION DeviceExtension,
    PSTATUS_BLOCK StatusBlock)
 {
-   VIDEO_X86_BIOS_ARGUMENTS BiosRegisters;
+   INT10_BIOS_ARGUMENTS BiosRegisters;
 
    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
-   BiosRegisters.Eax = 0x4F02;
+   BiosRegisters.Eax = VBE_SET_VBE_MODE;
    BiosRegisters.Ebx = 0x3;
-   VideoPortInt10(NULL, &BiosRegisters);
-   return TRUE;
+   DeviceExtension->Int10Interface.Int10CallBios(
+      DeviceExtension->Int10Interface.Context,
+      &BiosRegisters);
+
+   return BiosRegisters.Eax == VBE_SUCCESS;
 }
 
 /*
  * VBEMapVideoMemory
  *
  * Maps the video hardware frame buffer and video RAM into the virtual address
- * space of the requestor. 
+ * space of the requestor.
  */
 
 BOOL FASTCALL
@@ -606,16 +786,37 @@ 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;
+      if (DeviceExtension->VbeInfo.Version < 0x300)
+      {
+         MapInformation->VideoRamLength =
+            DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].BytesPerScanLine *
+            DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution;
+      }
+      else
+      {
+         MapInformation->VideoRamLength =
+            DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].LinBytesPerScanLine *
+            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,
@@ -624,8 +825,6 @@ VBEMapVideoMemory(
    MapInformation->FrameBufferBase = MapInformation->VideoRamBase;
    MapInformation->FrameBufferLength = MapInformation->VideoRamLength;
 
-   DeviceExtension->FrameBufferMemory = MapInformation->VideoRamBase;
-
    return TRUE;
 }
 
@@ -639,12 +838,13 @@ 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;
-}   
+}
 
 /*
  * VBEQueryNumAvailModes
@@ -672,7 +872,7 @@ VBEQueryNumAvailModes(
  * Returns information about one particular video mode.
  */
 
-VOID FASTCALL  
+VOID FASTCALL
 VBEQueryMode(
    PVBE_DEVICE_EXTENSION DeviceExtension,
    PVIDEO_MODE_INFORMATION VideoMode,
@@ -684,15 +884,26 @@ VBEQueryMode(
    VideoMode->ModeIndex = VideoModeId;
    VideoMode->VisScreenWidth = VBEMode->XResolution;
    VideoMode->VisScreenHeight = VBEMode->YResolution;
-   VideoMode->ScreenStride = VBEMode->BytesPerScanLine;
+   if (DeviceExtension->VbeInfo.Version < 0x300)
+      VideoMode->ScreenStride = VBEMode->BytesPerScanLine;
+   else
+      VideoMode->ScreenStride = VBEMode->LinBytesPerScanLine;
    VideoMode->NumberOfPlanes = VBEMode->NumberOfPlanes;
    VideoMode->BitsPerPlane = VBEMode->BitsPerPixel / VBEMode->NumberOfPlanes;
-   VideoMode->Frequency = 0; /* FIXME */
+   VideoMode->Frequency = 1;
    VideoMode->XMillimeter = 0; /* FIXME */
    VideoMode->YMillimeter = 0; /* FIXME */
    if (VBEMode->BitsPerPixel > 8)
    {
-      if (DeviceExtension->VBEVersion < 0x300)
+      /*
+       * Always report 16bpp modes and not 15bpp mode...
+       */
+      if (VBEMode->BitsPerPixel == 15 && VBEMode->NumberOfPlanes == 1)
+      {
+         VideoMode->BitsPerPlane = 16;
+      }
+
+      if (DeviceExtension->VbeInfo.Version < 0x300)
       {
          VideoMode->NumberRedBits = VBEMode->RedMaskSize;
          VideoMode->NumberGreenBits = VBEMode->GreenMaskSize;
@@ -713,11 +924,11 @@ VBEQueryMode(
    }
    else
    {
-      VideoMode->NumberRedBits = 
-      VideoMode->NumberGreenBits = 
+      VideoMode->NumberRedBits =
+      VideoMode->NumberGreenBits =
       VideoMode->NumberBlueBits = 6;
-      VideoMode->RedMask = 
-      VideoMode->GreenMask = 
+      VideoMode->RedMask =
+      VideoMode->GreenMask =
       VideoMode->BlueMask = 0;
    }
    VideoMode->VideoMemoryBitmapWidth = VBEMode->XResolution;
@@ -765,7 +976,7 @@ VBEQueryAvailModes(
  * Returns information about current video mode.
  */
 
-BOOL FASTCALL  
+BOOL FASTCALL
 VBEQueryCurrentMode(
    PVBE_DEVICE_EXTENSION DeviceExtension,
    PVIDEO_MODE_INFORMATION VideoModeInfo,
@@ -796,14 +1007,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;
@@ -814,17 +1030,18 @@ VBESetColorRegisters(
          VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green);
          VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
       }
+
       return TRUE;
    }
    else
    {
       /*
-       * We can't just copy the values, because we need to swap the Red 
+       * We can't just copy the values, because we need to swap the Red
        * and Blue values.
        */
 
       for (Entry = ColorLookUpTable->FirstEntry,
-           OutputEntry = DeviceExtension->TrampolineMemory;
+           OutputEntry = OutputBuffer;
            Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
            Entry++, OutputEntry++)
       {
@@ -834,13 +1051,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;
    }
 }