⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vbemp.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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.HwGetVideoChildDescriptor = VBEGetVideoChildDescriptor;
   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)
         {
            /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */
             // if (ModeTemp & 0x4000)
             //{
                VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000;
                SuitableModeCount++;
             //}
         }
#ifdef VBE12_SUPPORT
         else
         {   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -