Beispiel #1
0
VP_STATUS
NTAPI
VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension,
                  IN PVIDEO_CLUT ClutBuffer)
{
    PVBE_COLOR_REGISTER VesaClut;
    INT10_BIOS_ARGUMENTS BiosArguments;
    PVOID Context;
    ULONG Entries;
    ULONG BufferSize = 4 * 1024;
    USHORT TrampolineMemorySegment, TrampolineMemoryOffset;
    VP_STATUS Status;
    USHORT i;

    Entries = ClutBuffer->NumEntries;

    /* Allocate INT10 context/buffer */
    VesaClut = VideoPortAllocatePool(VgaExtension, 1, sizeof(ULONG) * Entries, 0x20616756u);
    if (!VesaClut) return ERROR_INVALID_PARAMETER;
    if (!VgaExtension->Int10Interface.Size) return ERROR_INVALID_PARAMETER;
    Context = VgaExtension->Int10Interface.Context;
    Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context,
                                                            &TrampolineMemorySegment,
                                                            &TrampolineMemoryOffset,
                                                            &BufferSize);
    if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;

    /* VESA has color registers backward! */
    for (i = 0; i < Entries; i++)
    {
        VesaClut[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue;
        VesaClut[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green;
        VesaClut[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red;
        VesaClut[i].Pad = 0;
    }
    Status = VgaExtension->Int10Interface.Int10WriteMemory(Context,
                                                         TrampolineMemorySegment,
                                                         TrampolineMemoryOffset,
                                                         VesaClut,
                                                         Entries * sizeof(ULONG));
    if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;

    /* Write new palette */
    BiosArguments.Ebx = 0;
    BiosArguments.Ecx = Entries;
    BiosArguments.Edx = ClutBuffer->FirstEntry;
    BiosArguments.Edi = TrampolineMemoryOffset;
    BiosArguments.SegEs = TrampolineMemorySegment;
    BiosArguments.Eax = VBE_SET_GET_PALETTE_DATA;
    Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments);
    if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;
    VideoPortFreePool(VgaExtension, VesaClut);
    VideoPortDebugPrint(Error, "VBE Status: %lx\n", BiosArguments.Eax);
    if (BiosArguments.Eax == VBE_SUCCESS) return NO_ERROR;
    return ERROR_INVALID_PARAMETER;
}
Beispiel #2
0
BOOLEAN NTAPI
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 (VBE_GETRETURNCODE(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(Error, "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(Error, "VBE BIOS present, but incompatible version %d.%d\n",
                             VBEDeviceExtension->VbeInfo.Version / 0x100,
                             VBEDeviceExtension->VbeInfo.Version & 0xFF);
         return FALSE;
      }
   }
   else
   {
      VideoPortDebugPrint(Error, "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 (VBE_GETRETURNCODE(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
         {
            VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp;
            SuitableModeCount++;
         }
#endif
      }
   }


   if (SuitableModeCount == 0)
   {

      VideoPortDebugPrint(Warn, "VBEMP: No video modes supported\n");
      return FALSE;
   }

   VBEDeviceExtension->ModeCount = SuitableModeCount;

   /*
    * Sort the video mode list according to resolution and bits per pixel.
    */

   VBESortModes(VBEDeviceExtension);

   /*
    * Print the supported video modes.
    */

   for (CurrentMode = 0;
        CurrentMode < SuitableModeCount;
        CurrentMode++)
   {
      VideoPortDebugPrint(Trace, "%dx%dx%d\n",
         VBEDeviceExtension->ModeInfo[CurrentMode].XResolution,
         VBEDeviceExtension->ModeInfo[CurrentMode].YResolution,
         VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel);
   }

   /*
    * Enumerate our children.
    */
   VideoPortEnumerateChildren(HwDeviceExtension, NULL);

   return TRUE;
}
Beispiel #3
0
VP_STATUS
NTAPI
VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension,
                  IN PVIDEO_CLUT ClutBuffer)
{
    PVBE_COLOR_REGISTER VesaClut;
    INT10_BIOS_ARGUMENTS BiosArguments;
    PVOID Context;
    ULONG Entries;
    ULONG BufferSize = 4 * 1024;
    USHORT TrampolineMemorySegment, TrampolineMemoryOffset;
    VP_STATUS Status;
    USHORT i;
    PVIDEOMODE CurrentMode = VgaExtension->CurrentMode;

    Entries = ClutBuffer->NumEntries;
    
    VideoDebugPrint((0, "Setting %lu entries.\n", Entries));
    
    /* 
     * For Vga compatible modes, write them directly.
     * Otherwise, the LGPL VGABIOS (used in bochs) fails!
     * It is also said that this way is faster.
     */
    if(!CurrentMode->NonVgaMode)
    {
        for (i=ClutBuffer->FirstEntry; i<ClutBuffer->FirstEntry + Entries; i++)
        {
            VideoPortWritePortUchar((PUCHAR)0x03c8, i);
            VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Red);
            VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Green);
            VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Blue);
        }
        return NO_ERROR;
    }

    /* Allocate INT10 context/buffer */
    VesaClut = VideoPortAllocatePool(VgaExtension, 1, sizeof(ULONG) * Entries, ' agV');
    if (!VesaClut) return ERROR_INVALID_PARAMETER;
    if (!VgaExtension->Int10Interface.Size) return ERROR_INVALID_PARAMETER;
    Context = VgaExtension->Int10Interface.Context;
    Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context,
                                                            &TrampolineMemorySegment,
                                                            &TrampolineMemoryOffset,
                                                            &BufferSize);
    if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;

    /* VESA has color registers backward! */
    for (i = 0; i < Entries; i++)
    {
        VesaClut[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue;
        VesaClut[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green;
        VesaClut[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red;
        VesaClut[i].Pad = 0;
    }
    Status = VgaExtension->Int10Interface.Int10WriteMemory(Context,
                                                         TrampolineMemorySegment,
                                                         TrampolineMemoryOffset,
                                                         VesaClut,
                                                         Entries * sizeof(ULONG));
    if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;

    /* Write the palette */
    VideoPortZeroMemory(&BiosArguments, sizeof(BiosArguments));
    BiosArguments.Ebx = 0;
    BiosArguments.Ecx = Entries;
    BiosArguments.Edx = ClutBuffer->FirstEntry;
    BiosArguments.Edi = TrampolineMemoryOffset;
    BiosArguments.SegEs = TrampolineMemorySegment;
    BiosArguments.Eax = VBE_SET_GET_PALETTE_DATA;
    Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments);
    if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;
    VideoPortFreePool(VgaExtension, VesaClut);
    VideoDebugPrint((Error, "VBE Status: %lx\n", BiosArguments.Eax));
    if (VBE_GETRETURNCODE(BiosArguments.Eax) == VBE_SUCCESS)
        return NO_ERROR;
    return ERROR_INVALID_PARAMETER;
}