ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

vbemp.c
Go to the documentation of this file.
00001 /*
00002  * ReactOS VBE miniport video driver
00003  * Copyright (C) 2004 Filip Navara
00004  *
00005  * Power Management and VBE 1.2 support
00006  * Copyright (C) 2004 Magnus Olsen
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License along
00019  * with this program; if not, write to the Free Software Foundation, Inc.,
00020  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021  *
00022  * TODO:
00023  * - Check input parameters everywhere.
00024  * - Call VideoPortVerifyAccessRanges to reserve the memory we're about
00025  *   to map.
00026  */
00027 
00028 /* INCLUDES *******************************************************************/
00029 
00030 #include "vbemp.h"
00031 
00032 #undef LOWORD
00033 #undef HIWORD
00034 #define LOWORD(l)   ((USHORT)((ULONG_PTR)(l)))
00035 #define HIWORD(l)   ((USHORT)(((ULONG_PTR)(l)>>16)&0xFFFF))
00036 
00037 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
00038 
00039 ULONG NTAPI
00040 DriverEntry(IN PVOID Context1, IN PVOID Context2)
00041 {
00042    VIDEO_HW_INITIALIZATION_DATA InitData;
00043 
00044    VideoPortZeroMemory(&InitData, sizeof(InitData));
00045    InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
00046    InitData.HwFindAdapter = VBEFindAdapter;
00047    InitData.HwInitialize = VBEInitialize;
00048    InitData.HwStartIO = VBEStartIO;
00049    InitData.HwResetHw = VBEResetHw;
00050    InitData.HwGetPowerState = VBEGetPowerState;
00051    InitData.HwSetPowerState = VBESetPowerState;
00052    InitData.HwGetVideoChildDescriptor = VBEGetVideoChildDescriptor;
00053    InitData.HwDeviceExtensionSize = sizeof(VBE_DEVICE_EXTENSION);
00054 
00055    return VideoPortInitialize(Context1, Context2, &InitData, NULL);
00056 }
00057 
00058 /*
00059  * VBEFindAdapter
00060  *
00061  * Should detect a VBE compatible display adapter, but it's not possible
00062  * to use video port Int 10 services at this time during initialization,
00063  * so we always return NO_ERROR and do the real work in VBEInitialize.
00064  */
00065 
00066 VP_STATUS NTAPI
00067 VBEFindAdapter(
00068    IN PVOID HwDeviceExtension,
00069    IN PVOID HwContext,
00070    IN PWSTR ArgumentString,
00071    IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo,
00072    OUT PUCHAR Again)
00073 {
00074    if (VideoPortIsNoVesa())
00075        return ERROR_DEV_NOT_EXIST;
00076 
00077    return NO_ERROR;
00078 }
00079 
00080 /*
00081  * VBESortModesCallback
00082  *
00083  * Helper function for sorting video mode list.
00084  */
00085 
00086 static int
00087 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA, PVBE_MODEINFO VbeModeInfoB)
00088 {
00089    VideoPortDebugPrint(Info, "VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
00090       VbeModeInfoA->XResolution, VbeModeInfoA->YResolution,
00091       VbeModeInfoA->BitsPerPixel,
00092       VbeModeInfoB->XResolution, VbeModeInfoB->YResolution,
00093       VbeModeInfoB->BitsPerPixel);
00094 
00095    /*
00096     * FIXME: Until some reasonable method for changing video modes will
00097     * be available we favor more bits per pixel. It should be changed
00098     * later.
00099     */
00100    if (VbeModeInfoA->BitsPerPixel < VbeModeInfoB->BitsPerPixel) return -1;
00101    if (VbeModeInfoA->BitsPerPixel > VbeModeInfoB->BitsPerPixel) return 1;
00102    if (VbeModeInfoA->XResolution < VbeModeInfoB->XResolution) return -1;
00103    if (VbeModeInfoA->XResolution > VbeModeInfoB->XResolution) return 1;
00104    if (VbeModeInfoA->YResolution < VbeModeInfoB->YResolution) return -1;
00105    if (VbeModeInfoA->YResolution > VbeModeInfoB->YResolution) return 1;
00106    return 0;
00107 }
00108 
00109 /*
00110  * VBESortModes
00111  *
00112  * Simple function for sorting the video mode list. Uses bubble sort.
00113  */
00114 
00115 VOID FASTCALL
00116 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension)
00117 {
00118    BOOLEAN Finished = FALSE;
00119    ULONG Pos;
00120    int Result;
00121    VBE_MODEINFO TempModeInfo;
00122    USHORT TempModeNumber;
00123 
00124    while (!Finished)
00125    {
00126       Finished = TRUE;
00127       for (Pos = 0; Pos < DeviceExtension->ModeCount - 1; Pos++)
00128       {
00129          Result = VBESortModesCallback(
00130             DeviceExtension->ModeInfo + Pos,
00131             DeviceExtension->ModeInfo + Pos + 1);
00132          if (Result > 0)
00133          {
00134             Finished = FALSE;
00135 
00136             VideoPortMoveMemory(
00137                &TempModeInfo,
00138                DeviceExtension->ModeInfo + Pos,
00139                sizeof(VBE_MODEINFO));
00140             TempModeNumber = DeviceExtension->ModeNumbers[Pos];
00141 
00142             VideoPortMoveMemory(
00143                DeviceExtension->ModeInfo + Pos,
00144                DeviceExtension->ModeInfo + Pos + 1,
00145                sizeof(VBE_MODEINFO));
00146             DeviceExtension->ModeNumbers[Pos] =
00147                DeviceExtension->ModeNumbers[Pos + 1];
00148 
00149             VideoPortMoveMemory(
00150                DeviceExtension->ModeInfo + Pos + 1,
00151                &TempModeInfo,
00152                sizeof(VBE_MODEINFO));
00153             DeviceExtension->ModeNumbers[Pos + 1] = TempModeNumber;
00154          }
00155       }
00156    }
00157 }
00158 
00159 /*
00160  * VBEInitialize
00161  *
00162  * Performs the first initialization of the adapter, after the HAL has given
00163  * up control of the video hardware to the video port driver.
00164  *
00165  * This function performs these steps:
00166  * - Gets global VBE information and finds if VBE BIOS is present.
00167  * - Builds the internal mode list using the list of modes provided by
00168  *   the VBE.
00169  */
00170 
00171 BOOLEAN NTAPI
00172 VBEInitialize(PVOID HwDeviceExtension)
00173 {
00174    INT10_BIOS_ARGUMENTS BiosRegisters;
00175    VP_STATUS Status;
00176    PVBE_DEVICE_EXTENSION VBEDeviceExtension =
00177      (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
00178    ULONG Length;
00179    ULONG ModeCount;
00180    ULONG SuitableModeCount;
00181    USHORT ModeTemp;
00182    ULONG CurrentMode;
00183    PVBE_MODEINFO VbeModeInfo;
00184 
00185    /*
00186     * Get the Int 10 interface that we will use for allocating real
00187     * mode memory and calling the video BIOS.
00188     */
00189 
00190    VBEDeviceExtension->Int10Interface.Version = VIDEO_PORT_INT10_INTERFACE_VERSION_1;
00191    VBEDeviceExtension->Int10Interface.Size = sizeof(VIDEO_PORT_INT10_INTERFACE);
00192    Status = VideoPortQueryServices(
00193       HwDeviceExtension,
00194       VideoPortServicesInt10,
00195       (PINTERFACE)&VBEDeviceExtension->Int10Interface);
00196 
00197    if (Status != NO_ERROR)
00198    {
00199       VideoPortDebugPrint(Error, "Failed to get Int 10 service functions (Status %x)\n", Status);
00200       return FALSE;
00201    }
00202 
00203    /*
00204     * Allocate a bit of memory that will be later used for VBE transport
00205     * buffer. This memory must be accessible from V86 mode so it must fit
00206     * in the first megabyte of physical memory.
00207     */
00208 
00209    Length = 0x400;
00210    Status = VBEDeviceExtension->Int10Interface.Int10AllocateBuffer(
00211       VBEDeviceExtension->Int10Interface.Context,
00212       &VBEDeviceExtension->TrampolineMemorySegment,
00213       &VBEDeviceExtension->TrampolineMemoryOffset,
00214       &Length);
00215 
00216    if (Status != NO_ERROR)
00217    {
00218       VideoPortDebugPrint(Error, "Failed to allocate virtual memory (Status %x)\n", Status);
00219       return FALSE;
00220    }
00221 
00222    /*
00223     * Get the VBE general information.
00224     */
00225 
00226    VBEDeviceExtension->Int10Interface.Int10WriteMemory(
00227       VBEDeviceExtension->Int10Interface.Context,
00228       VBEDeviceExtension->TrampolineMemorySegment,
00229       VBEDeviceExtension->TrampolineMemoryOffset,
00230       "VBE2",
00231       4);
00232 
00233    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
00234    BiosRegisters.Eax = VBE_GET_CONTROLLER_INFORMATION;
00235    BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset;
00236    BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment;
00237    VBEDeviceExtension->Int10Interface.Int10CallBios(
00238       VBEDeviceExtension->Int10Interface.Context,
00239       &BiosRegisters);
00240 
00241    if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS)
00242    {
00243       VBEDeviceExtension->Int10Interface.Int10ReadMemory(
00244          VBEDeviceExtension->Int10Interface.Context,
00245          VBEDeviceExtension->TrampolineMemorySegment,
00246          VBEDeviceExtension->TrampolineMemoryOffset,
00247          &VBEDeviceExtension->VbeInfo,
00248          sizeof(VBEDeviceExtension->VbeInfo));
00249 
00250       /* Verify the VBE signature. */
00251       if (VideoPortCompareMemory(VBEDeviceExtension->VbeInfo.Signature, "VESA", 4) != 4)
00252       {
00253          VideoPortDebugPrint(Error, "No VBE BIOS present\n");
00254          return FALSE;
00255       }
00256 
00257       VideoPortDebugPrint(Trace, "VBE BIOS Present (%d.%d, %8ld Kb)\n",
00258          VBEDeviceExtension->VbeInfo.Version / 0x100,
00259          VBEDeviceExtension->VbeInfo.Version & 0xFF,
00260          VBEDeviceExtension->VbeInfo.TotalMemory * 64);
00261 
00262 #ifdef VBE12_SUPPORT
00263       if (VBEDeviceExtension->VbeInfo.Version < 0x102)
00264 #else
00265       if (VBEDeviceExtension->VbeInfo.Version < 0x200)
00266 #endif
00267       {
00268          VideoPortDebugPrint(Error, "VBE BIOS present, but incompatible version %d.%d\n",
00269                              VBEDeviceExtension->VbeInfo.Version / 0x100,
00270                              VBEDeviceExtension->VbeInfo.Version & 0xFF);
00271          return FALSE;
00272       }
00273    }
00274    else
00275    {
00276       VideoPortDebugPrint(Error, "No VBE BIOS found.\n");
00277       return FALSE;
00278    }
00279 
00280    /*
00281     * Build a mode list here that can be later used by
00282     * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
00283     * calls.
00284     */
00285 
00286    /*
00287     * Get the number of supported video modes.
00288     *
00289     * No need to be map the memory. It's either in the video BIOS memory or
00290     * in our trampoline memory. In either case the memory is already mapped.
00291     */
00292 
00293    for (ModeCount = 0; ; ModeCount++)
00294    {
00295       /* Read the VBE mode number. */
00296       VBEDeviceExtension->Int10Interface.Int10ReadMemory(
00297          VBEDeviceExtension->Int10Interface.Context,
00298          HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr),
00299          LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (ModeCount << 1),
00300          &ModeTemp,
00301          sizeof(ModeTemp));
00302 
00303       /* End of list? */
00304       if (ModeTemp == 0xFFFF || ModeTemp == 0)
00305          break;
00306    }
00307 
00308    /*
00309     * Allocate space for video modes information.
00310     */
00311 
00312    VBEDeviceExtension->ModeInfo =
00313       VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(VBE_MODEINFO), TAG_VBE);
00314    VBEDeviceExtension->ModeNumbers =
00315       VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(USHORT), TAG_VBE);
00316 
00317    /*
00318     * Get the actual mode infos.
00319     */
00320 
00321    for (CurrentMode = 0, SuitableModeCount = 0;
00322         CurrentMode < ModeCount;
00323         CurrentMode++)
00324    {
00325       /* Read the VBE mode number. */
00326       VBEDeviceExtension->Int10Interface.Int10ReadMemory(
00327          VBEDeviceExtension->Int10Interface.Context,
00328          HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr),
00329          LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (CurrentMode << 1),
00330          &ModeTemp,
00331          sizeof(ModeTemp));
00332 
00333       /* Call VBE BIOS to read the mode info. */
00334       VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
00335       BiosRegisters.Eax = VBE_GET_MODE_INFORMATION;
00336       BiosRegisters.Ecx = ModeTemp;
00337       BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset + 0x200;
00338       BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment;
00339       VBEDeviceExtension->Int10Interface.Int10CallBios(
00340          VBEDeviceExtension->Int10Interface.Context,
00341          &BiosRegisters);
00342 
00343       /* Read the VBE mode info. */
00344       VBEDeviceExtension->Int10Interface.Int10ReadMemory(
00345          VBEDeviceExtension->Int10Interface.Context,
00346          VBEDeviceExtension->TrampolineMemorySegment,
00347          VBEDeviceExtension->TrampolineMemoryOffset + 0x200,
00348          VBEDeviceExtension->ModeInfo + SuitableModeCount,
00349          sizeof(VBE_MODEINFO));
00350 
00351       VbeModeInfo = VBEDeviceExtension->ModeInfo + SuitableModeCount;
00352 
00353       /* Is this mode acceptable? */
00354       if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS &&
00355           VbeModeInfo->XResolution >= 640 &&
00356           VbeModeInfo->YResolution >= 480 &&
00357           (VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_PACKEDPIXEL ||
00358            VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_DIRECTCOLOR) &&
00359           VbeModeInfo->PhysBasePtr != 0)
00360       {
00361          if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR)
00362          {
00363             /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */
00364              // if (ModeTemp & 0x4000)
00365              //{
00366                 VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000;
00367                 SuitableModeCount++;
00368              //}
00369          }
00370 #ifdef VBE12_SUPPORT
00371          else
00372          {
00373             VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp;
00374             SuitableModeCount++;
00375          }
00376 #endif
00377       }
00378    }
00379 
00380 
00381    if (SuitableModeCount == 0)
00382    {
00383 
00384       VideoPortDebugPrint(Warn, "VBEMP: No video modes supported\n");
00385       return FALSE;
00386    }
00387 
00388    VBEDeviceExtension->ModeCount = SuitableModeCount;
00389 
00390    /*
00391     * Sort the video mode list according to resolution and bits per pixel.
00392     */
00393 
00394    VBESortModes(VBEDeviceExtension);
00395 
00396    /*
00397     * Print the supported video modes.
00398     */
00399 
00400    for (CurrentMode = 0;
00401         CurrentMode < SuitableModeCount;
00402         CurrentMode++)
00403    {
00404       VideoPortDebugPrint(Trace, "%dx%dx%d\n",
00405          VBEDeviceExtension->ModeInfo[CurrentMode].XResolution,
00406          VBEDeviceExtension->ModeInfo[CurrentMode].YResolution,
00407          VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel);
00408    }
00409 
00410    /*
00411     * Enumerate our children.
00412     */
00413    VideoPortEnumerateChildren(HwDeviceExtension, NULL);
00414 
00415    return TRUE;
00416 }
00417 
00418 /*
00419  * VBEStartIO
00420  *
00421  * Processes the specified Video Request Packet.
00422  */
00423 
00424 BOOLEAN NTAPI
00425 VBEStartIO(
00426    PVOID HwDeviceExtension,
00427    PVIDEO_REQUEST_PACKET RequestPacket)
00428 {
00429    BOOLEAN Result;
00430 
00431    RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
00432 
00433    switch (RequestPacket->IoControlCode)
00434    {
00435       case IOCTL_VIDEO_SET_CURRENT_MODE:
00436          if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE))
00437          {
00438             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
00439             return TRUE;
00440          }
00441          Result = VBESetCurrentMode(
00442             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00443             (PVIDEO_MODE)RequestPacket->InputBuffer,
00444             RequestPacket->StatusBlock);
00445          break;
00446 
00447       case IOCTL_VIDEO_RESET_DEVICE:
00448          Result = VBEResetDevice(
00449             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00450             RequestPacket->StatusBlock);
00451          break;
00452 
00453       case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
00454          if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) ||
00455              RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
00456          {
00457             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
00458             return TRUE;
00459          }
00460          Result = VBEMapVideoMemory(
00461             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00462             (PVIDEO_MEMORY)RequestPacket->InputBuffer,
00463             (PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer,
00464             RequestPacket->StatusBlock);
00465          break;
00466 
00467       case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
00468          if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
00469          {
00470             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
00471             return TRUE;
00472          }
00473          Result = VBEUnmapVideoMemory(
00474             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00475             (PVIDEO_MEMORY)RequestPacket->InputBuffer,
00476             RequestPacket->StatusBlock);
00477          break;
00478 
00479       case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
00480          if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES))
00481          {
00482             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
00483             return TRUE;
00484          }
00485          Result = VBEQueryNumAvailModes(
00486             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00487             (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer,
00488             RequestPacket->StatusBlock);
00489          break;
00490 
00491       case IOCTL_VIDEO_QUERY_AVAIL_MODES:
00492          if (RequestPacket->OutputBufferLength <
00493              ((PVBE_DEVICE_EXTENSION)HwDeviceExtension)->ModeCount * sizeof(VIDEO_MODE_INFORMATION))
00494          {
00495             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
00496             return TRUE;
00497          }
00498          Result = VBEQueryAvailModes(
00499             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00500             (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
00501             RequestPacket->StatusBlock);
00502          break;
00503 
00504       case IOCTL_VIDEO_SET_COLOR_REGISTERS:
00505          if (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) ||
00506              RequestPacket->InputBufferLength <
00507              (((PVIDEO_CLUT)RequestPacket->InputBuffer)->NumEntries * sizeof(ULONG)) +
00508              FIELD_OFFSET(VIDEO_CLUT, LookupTable))
00509          {
00510             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
00511             return TRUE;
00512          }
00513          Result = VBESetColorRegisters(
00514             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00515             (PVIDEO_CLUT)RequestPacket->InputBuffer,
00516             RequestPacket->StatusBlock);
00517          break;
00518 
00519       case IOCTL_VIDEO_QUERY_CURRENT_MODE:
00520          if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION))
00521          {
00522             RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
00523             return TRUE;
00524          }
00525          Result = VBEQueryCurrentMode(
00526             (PVBE_DEVICE_EXTENSION)HwDeviceExtension,
00527             (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer,
00528             RequestPacket->StatusBlock);
00529          break;
00530 
00531       default:
00532          RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
00533          return FALSE;
00534    }
00535 
00536    if (Result)
00537       RequestPacket->StatusBlock->Status = NO_ERROR;
00538 
00539    return TRUE;
00540 }
00541 
00542 /*
00543  * VBEResetHw
00544  *
00545  * This function is called to reset the hardware to a known state.
00546  */
00547 
00548 BOOLEAN NTAPI
00549 VBEResetHw(
00550    PVOID DeviceExtension,
00551    ULONG Columns,
00552    ULONG Rows)
00553 {
00554    /* Return FALSE to let HAL reset the display with INT10 */
00555    return FALSE;
00556 }
00557 
00558 /*
00559  * VBEGetPowerState
00560  *
00561  * Queries whether the device can support the requested power state.
00562  */
00563 
00564 VP_STATUS NTAPI
00565 VBEGetPowerState(
00566    PVOID HwDeviceExtension,
00567    ULONG HwId,
00568    PVIDEO_POWER_MANAGEMENT VideoPowerControl)
00569 {
00570    INT10_BIOS_ARGUMENTS BiosRegisters;
00571    PVBE_DEVICE_EXTENSION VBEDeviceExtension =
00572      (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
00573 
00574    if (HwId != DISPLAY_ADAPTER_HW_ID ||
00575        VideoPowerControl->Length < sizeof(VIDEO_POWER_MANAGEMENT))
00576       return ERROR_INVALID_FUNCTION;
00577 
00578    /*
00579     * Get general power support information.
00580     */
00581 
00582    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
00583    BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS;
00584    BiosRegisters.Ebx = 0;
00585    BiosRegisters.Edi = 0;
00586    BiosRegisters.SegEs = 0;
00587    VBEDeviceExtension->Int10Interface.Int10CallBios(
00588       VBEDeviceExtension->Int10Interface.Context,
00589       &BiosRegisters);
00590 
00591    if ( VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_NOT_SUPPORTED)
00592       return ERROR_DEV_NOT_EXIST;
00593    if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS)
00594       return ERROR_INVALID_FUNCTION;
00595 
00596    /*
00597     * Get current power state.
00598     */
00599 
00600    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
00601    BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS;
00602    BiosRegisters.Ebx = 0x2;
00603    BiosRegisters.Edi = 0;
00604    BiosRegisters.SegEs = 0;
00605    VBEDeviceExtension->Int10Interface.Int10CallBios(
00606       VBEDeviceExtension->Int10Interface.Context,
00607       &BiosRegisters);
00608 
00609    if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS)
00610    {
00611       VideoPowerControl->DPMSVersion = BiosRegisters.Ebx & 0xFF;
00612       switch (BiosRegisters.Ebx >> 8)
00613       {
00614          case 0: VideoPowerControl->PowerState = VideoPowerOn; break;
00615          case 1: VideoPowerControl->PowerState = VideoPowerStandBy; break;
00616          case 2: VideoPowerControl->PowerState = VideoPowerSuspend; break;
00617          case 4: VideoPowerControl->PowerState = VideoPowerOff; break;
00618          case 5: VideoPowerControl->PowerState = VideoPowerOn; break;
00619          default: VideoPowerControl->PowerState = VideoPowerUnspecified;
00620       }
00621 
00622       return NO_ERROR;
00623    }
00624 
00625    return ERROR_DEV_NOT_EXIST;
00626 }
00627 
00628 /*
00629  * VBESetPowerState
00630  *
00631  * Sets the power state of the specified device
00632  */
00633 
00634 VP_STATUS NTAPI
00635 VBESetPowerState(
00636    PVOID HwDeviceExtension,
00637    ULONG HwId,
00638    PVIDEO_POWER_MANAGEMENT VideoPowerControl)
00639 {
00640    INT10_BIOS_ARGUMENTS BiosRegisters;
00641    PVBE_DEVICE_EXTENSION VBEDeviceExtension =
00642      (PVBE_DEVICE_EXTENSION)HwDeviceExtension;
00643 
00644    if (HwId != DISPLAY_ADAPTER_HW_ID ||
00645        VideoPowerControl->Length < sizeof(VIDEO_POWER_MANAGEMENT) ||
00646        VideoPowerControl->PowerState < VideoPowerOn ||
00647        VideoPowerControl->PowerState > VideoPowerHibernate)
00648       return ERROR_INVALID_FUNCTION;
00649 
00650    if (VideoPowerControl->PowerState == VideoPowerHibernate)
00651       return NO_ERROR;
00652 
00653    /*
00654     * Set current power state.
00655     */
00656 
00657    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
00658    BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS;
00659    BiosRegisters.Ebx = 1;
00660    BiosRegisters.Edi = 0;
00661    BiosRegisters.SegEs = 0;
00662    switch (VideoPowerControl->PowerState)
00663    {
00664       case VideoPowerStandBy: BiosRegisters.Ebx |= 0x100; break;
00665       case VideoPowerSuspend: BiosRegisters.Ebx |= 0x200; break;
00666       case VideoPowerOff: BiosRegisters.Ebx |= 0x400; break;
00667    }
00668 
00669    VBEDeviceExtension->Int10Interface.Int10CallBios(
00670       VBEDeviceExtension->Int10Interface.Context,
00671       &BiosRegisters);
00672 
00673    if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_NOT_SUPPORTED)
00674       return ERROR_DEV_NOT_EXIST;
00675    if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS)
00676       return ERROR_INVALID_FUNCTION;
00677 
00678    return VBE_SUCCESS;
00679 }
00680 
00681 /*
00682  * VBESetCurrentMode
00683  *
00684  * Sets the adapter to the specified operating mode.
00685  */
00686 
00687 BOOLEAN FASTCALL
00688 VBESetCurrentMode(
00689    PVBE_DEVICE_EXTENSION DeviceExtension,
00690    PVIDEO_MODE RequestedMode,
00691    PSTATUS_BLOCK StatusBlock)
00692 {
00693    INT10_BIOS_ARGUMENTS BiosRegisters;
00694 
00695    if (RequestedMode->RequestedMode >= DeviceExtension->ModeCount)
00696    {
00697       return ERROR_INVALID_PARAMETER;
00698    }
00699 
00700    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
00701    BiosRegisters.Eax = VBE_SET_VBE_MODE;
00702    BiosRegisters.Ebx = DeviceExtension->ModeNumbers[RequestedMode->RequestedMode];
00703    DeviceExtension->Int10Interface.Int10CallBios(
00704       DeviceExtension->Int10Interface.Context,
00705       &BiosRegisters);
00706 
00707    if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS)
00708    {
00709       DeviceExtension->CurrentMode = RequestedMode->RequestedMode;
00710    }
00711    else
00712    {
00713       VideoPortDebugPrint(Error, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters.Eax);
00714       DeviceExtension->CurrentMode = -1;
00715    }
00716 
00717    return VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS;
00718 }
00719 
00720 /*
00721  * VBEResetDevice
00722  *
00723  * Resets the video hardware to the default mode, to which it was initialized
00724  * at system boot.
00725  */
00726 
00727 BOOLEAN FASTCALL
00728 VBEResetDevice(
00729    PVBE_DEVICE_EXTENSION DeviceExtension,
00730    PSTATUS_BLOCK StatusBlock)
00731 {
00732    INT10_BIOS_ARGUMENTS BiosRegisters;
00733 
00734    VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
00735    BiosRegisters.Eax = VBE_SET_VBE_MODE;
00736    BiosRegisters.Ebx = 0x3;
00737    DeviceExtension->Int10Interface.Int10CallBios(
00738       DeviceExtension->Int10Interface.Context,
00739       &BiosRegisters);
00740 
00741    return VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS;
00742 }
00743 
00744 /*
00745  * VBEMapVideoMemory
00746  *
00747  * Maps the video hardware frame buffer and video RAM into the virtual address
00748  * space of the requestor.
00749  */
00750 
00751 BOOLEAN FASTCALL
00752 VBEMapVideoMemory(
00753    PVBE_DEVICE_EXTENSION DeviceExtension,
00754    PVIDEO_MEMORY RequestedAddress,
00755    PVIDEO_MEMORY_INFORMATION MapInformation,
00756    PSTATUS_BLOCK StatusBlock)
00757 {
00758    PHYSICAL_ADDRESS FrameBuffer;
00759    ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY;
00760 
00761    StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION);
00762 
00763    if (DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].ModeAttributes &
00764        VBE_MODEATTR_LINEAR)
00765    {
00766       FrameBuffer.QuadPart =
00767          DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].PhysBasePtr;
00768       MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
00769       if (DeviceExtension->VbeInfo.Version < 0x300)
00770       {
00771          MapInformation->VideoRamLength =
00772             DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].BytesPerScanLine *
00773             DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution;
00774       }
00775       else
00776       {
00777          MapInformation->VideoRamLength =
00778             DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].LinBytesPerScanLine *
00779             DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution;
00780       }
00781    }
00782 #ifdef VBE12_SUPPORT
00783    else
00784    {
00785       FrameBuffer.QuadPart = 0xA0000;
00786       MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress;
00787       MapInformation->VideoRamLength = 0x10000;
00788    }
00789 #endif
00790 
00791    VideoPortMapMemory(DeviceExtension, FrameBuffer,
00792       &MapInformation->VideoRamLength, &inIoSpace,
00793       &MapInformation->VideoRamBase);
00794 
00795    MapInformation->FrameBufferBase = MapInformation->VideoRamBase;
00796    MapInformation->FrameBufferLength = MapInformation->VideoRamLength;
00797 
00798    return TRUE;
00799 }
00800 
00801 /*
00802  * VBEUnmapVideoMemory
00803  *
00804  * Releases a mapping between the virtual address space and the adapter's
00805  * frame buffer and video RAM.
00806  */
00807 
00808 BOOLEAN FASTCALL
00809 VBEUnmapVideoMemory(
00810    PVBE_DEVICE_EXTENSION DeviceExtension,
00811    PVIDEO_MEMORY VideoMemory,
00812    PSTATUS_BLOCK StatusBlock)
00813 {
00814    VideoPortUnmapMemory(DeviceExtension, VideoMemory->RequestedVirtualAddress,
00815       NULL);
00816    return TRUE;
00817 }
00818 
00819 /*
00820  * VBEQueryNumAvailModes
00821  *
00822  * Returns the number of video modes supported by the adapter and the size
00823  * in bytes of the video mode information, which can be used to allocate a
00824  * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
00825  */
00826 
00827 BOOLEAN FASTCALL
00828 VBEQueryNumAvailModes(
00829    PVBE_DEVICE_EXTENSION DeviceExtension,
00830    PVIDEO_NUM_MODES Modes,
00831    PSTATUS_BLOCK StatusBlock)
00832 {
00833    Modes->NumModes = DeviceExtension->ModeCount;
00834    Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
00835    StatusBlock->Information = sizeof(VIDEO_NUM_MODES);
00836    return TRUE;
00837 }
00838 
00839 /*
00840  * VBEQueryMode
00841  *
00842  * Returns information about one particular video mode.
00843  */
00844 
00845 VOID FASTCALL
00846 VBEQueryMode(
00847    PVBE_DEVICE_EXTENSION DeviceExtension,
00848    PVIDEO_MODE_INFORMATION VideoMode,
00849    ULONG VideoModeId)
00850 {
00851    PVBE_MODEINFO VBEMode = &DeviceExtension->ModeInfo[VideoModeId];
00852    ULONG dpi;
00853 
00854    VideoMode->Length = sizeof(VIDEO_MODE_INFORMATION);
00855    VideoMode->ModeIndex = VideoModeId;
00856    VideoMode->VisScreenWidth = VBEMode->XResolution;
00857    VideoMode->VisScreenHeight = VBEMode->YResolution;
00858    if (DeviceExtension->VbeInfo.Version < 0x300)
00859       VideoMode->ScreenStride = VBEMode->BytesPerScanLine;
00860    else
00861       VideoMode->ScreenStride = VBEMode->LinBytesPerScanLine;
00862    VideoMode->NumberOfPlanes = VBEMode->NumberOfPlanes;
00863    VideoMode->BitsPerPlane = VBEMode->BitsPerPixel / VBEMode->NumberOfPlanes;
00864    VideoMode->Frequency = 1;
00865 
00866    /* Assume 96DPI and 25.4 millimeters per inch, round to nearest */
00867    dpi = 96;
00868    VideoMode->XMillimeter = ((ULONGLONG)VBEMode->XResolution * 254 + (dpi * 5)) / (dpi * 10);
00869    VideoMode->YMillimeter = ((ULONGLONG)VBEMode->YResolution * 254 + (dpi * 5)) / (dpi * 10);
00870 
00871    if (VBEMode->BitsPerPixel > 8)
00872    {
00873       /*
00874        * Always report 16bpp modes and not 15bpp mode...
00875        */
00876       if (VBEMode->BitsPerPixel == 15 && VBEMode->NumberOfPlanes == 1)
00877       {
00878          VideoMode->BitsPerPlane = 16;
00879       }
00880 
00881       if (DeviceExtension->VbeInfo.Version < 0x300)
00882       {
00883          VideoMode->NumberRedBits = VBEMode->RedMaskSize;
00884          VideoMode->NumberGreenBits = VBEMode->GreenMaskSize;
00885          VideoMode->NumberBlueBits = VBEMode->BlueMaskSize;
00886          VideoMode->RedMask = ((1 << VBEMode->RedMaskSize) - 1) << VBEMode->RedFieldPosition;
00887          VideoMode->GreenMask = ((1 << VBEMode->GreenMaskSize) - 1) << VBEMode->GreenFieldPosition;
00888          VideoMode->BlueMask = ((1 << VBEMode->BlueMaskSize) - 1) << VBEMode->BlueFieldPosition;
00889       }
00890       else
00891       {
00892          VideoMode->NumberRedBits = VBEMode->LinRedMaskSize;
00893          VideoMode->NumberGreenBits = VBEMode->LinGreenMaskSize;
00894          VideoMode->NumberBlueBits = VBEMode->LinBlueMaskSize;
00895          VideoMode->RedMask = ((1 << VBEMode->LinRedMaskSize) - 1) << VBEMode->LinRedFieldPosition;
00896          VideoMode->GreenMask = ((1 << VBEMode->LinGreenMaskSize) - 1) << VBEMode->LinGreenFieldPosition;
00897          VideoMode->BlueMask = ((1 << VBEMode->LinBlueMaskSize) - 1) << VBEMode->LinBlueFieldPosition;
00898       }
00899    }
00900    else
00901    {
00902       VideoMode->NumberRedBits =
00903       VideoMode->NumberGreenBits =
00904       VideoMode->NumberBlueBits = 6;
00905       VideoMode->RedMask =
00906       VideoMode->GreenMask =
00907       VideoMode->BlueMask = 0;
00908    }
00909    VideoMode->VideoMemoryBitmapWidth = VBEMode->XResolution;
00910    VideoMode->VideoMemoryBitmapHeight = VBEMode->YResolution;
00911    VideoMode->AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR |
00912       VIDEO_MODE_NO_OFF_SCREEN;
00913    if (VideoMode->BitsPerPlane <= 8)
00914       VideoMode->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN;
00915    VideoMode->DriverSpecificAttributeFlags = 0;
00916 }
00917 
00918 /*
00919  * VBEQueryAvailModes
00920  *
00921  * Returns information about each video mode supported by the adapter.
00922  */
00923 
00924 BOOLEAN FASTCALL
00925 VBEQueryAvailModes(
00926    PVBE_DEVICE_EXTENSION DeviceExtension,
00927    PVIDEO_MODE_INFORMATION ReturnedModes,
00928    PSTATUS_BLOCK StatusBlock)
00929 {
00930    ULONG CurrentModeId;
00931    PVIDEO_MODE_INFORMATION CurrentMode;
00932    PVBE_MODEINFO CurrentVBEMode;
00933 
00934    for (CurrentModeId = 0, CurrentMode = ReturnedModes,
00935         CurrentVBEMode = DeviceExtension->ModeInfo;
00936         CurrentModeId < DeviceExtension->ModeCount;
00937         CurrentModeId++, CurrentMode++, CurrentVBEMode++)
00938    {
00939       VBEQueryMode(DeviceExtension, CurrentMode, CurrentModeId);
00940    }
00941 
00942    StatusBlock->Information =
00943       sizeof(VIDEO_MODE_INFORMATION) * DeviceExtension->ModeCount;
00944 
00945    return TRUE;
00946 }
00947 
00948 /*
00949  * VBEQueryCurrentMode
00950  *
00951  * Returns information about current video mode.
00952  */
00953 
00954 BOOLEAN FASTCALL
00955 VBEQueryCurrentMode(
00956    PVBE_DEVICE_EXTENSION DeviceExtension,
00957    PVIDEO_MODE_INFORMATION VideoModeInfo,
00958    PSTATUS_BLOCK StatusBlock)
00959 {
00960    StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION);
00961 
00962    VBEQueryMode(
00963       DeviceExtension,
00964       VideoModeInfo,
00965       DeviceExtension->CurrentMode);
00966 
00967    return TRUE;
00968 }
00969 
00970 /*
00971  * VBESetColorRegisters
00972  *
00973  * Sets the adapter's color registers to the specified RGB values. There
00974  * are code paths in this function, one generic and one for VGA compatible
00975  * controllers. The latter is needed for Bochs, where the generic one isn't
00976  * yet implemented.
00977  */
00978 
00979 BOOLEAN FASTCALL
00980 VBESetColorRegisters(
00981    PVBE_DEVICE_EXTENSION DeviceExtension,
00982    PVIDEO_CLUT ColorLookUpTable,
00983    PSTATUS_BLOCK StatusBlock)
00984 {
00985    INT10_BIOS_ARGUMENTS BiosRegisters;
00986    ULONG Entry;
00987    PULONG OutputEntry;
00988    ULONG OutputBuffer[256];
00989 
00990    if (ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry > 256)
00991       return FALSE;
00992 
00993    /*
00994     * For VGA compatible adapters program the color registers directly.
00995     */
00996 
00997    if (!(DeviceExtension->VbeInfo.Capabilities & 2))
00998    {
00999       for (Entry = ColorLookUpTable->FirstEntry;
01000            Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
01001            Entry++)
01002       {
01003          VideoPortWritePortUchar((PUCHAR)0x03c8, Entry);
01004          VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Red);
01005          VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green);
01006          VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
01007       }
01008 
01009       return TRUE;
01010    }
01011    else
01012    {
01013       /*
01014        * We can't just copy the values, because we need to swap the Red
01015        * and Blue values.
01016        */
01017 
01018       for (Entry = ColorLookUpTable->FirstEntry,
01019            OutputEntry = OutputBuffer;
01020            Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry;
01021            Entry++, OutputEntry++)
01022       {
01023          *OutputEntry =
01024             (ColorLookUpTable->LookupTable[Entry].RgbArray.Red << 16) |
01025             (ColorLookUpTable->LookupTable[Entry].RgbArray.Green << 8) |
01026             (ColorLookUpTable->LookupTable[Entry].RgbArray.Blue);
01027       }
01028 
01029       DeviceExtension->Int10Interface.Int10WriteMemory(
01030          DeviceExtension->Int10Interface.Context,
01031          DeviceExtension->TrampolineMemorySegment,
01032          DeviceExtension->TrampolineMemoryOffset,
01033          OutputBuffer,
01034          (OutputEntry - OutputBuffer) * sizeof(ULONG));
01035 
01036       VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters));
01037       BiosRegisters.Eax = VBE_SET_GET_PALETTE_DATA;
01038       BiosRegisters.Ebx = 0;
01039       BiosRegisters.Ecx = ColorLookUpTable->NumEntries;
01040       BiosRegisters.Edx = ColorLookUpTable->FirstEntry;
01041       BiosRegisters.Edi = DeviceExtension->TrampolineMemoryOffset;
01042       BiosRegisters.SegEs = DeviceExtension->TrampolineMemorySegment;
01043       DeviceExtension->Int10Interface.Int10CallBios(
01044          DeviceExtension->Int10Interface.Context,
01045          &BiosRegisters);
01046 
01047       return VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS;
01048    }
01049 }

Generated on Sun May 27 2012 04:38:11 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.