Revert tree-restructure attempt: r66583, r66582, r66581, r66578, sauf ntdll changes...
[reactos.git] / reactos / win32ss / drivers / miniport / vga_new / vbe.c
diff --git a/reactos/win32ss/drivers/miniport/vga_new/vbe.c b/reactos/win32ss/drivers/miniport/vga_new/vbe.c
new file mode 100644 (file)
index 0000000..f7187ff
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * PROJECT:         ReactOS VGA Miniport Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            boot/drivers/video/miniport/vga/vbe.c
+ * PURPOSE:         Main VESA VBE 1.02+ SVGA Miniport Handling Code
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "vga.h"
+
+/* GLOBALS ********************************************************************/
+
+static const CHAR Nv11Board[] = "NV11 (GeForce2) Board";
+static const CHAR Nv11Chip[] = "Chip Rev B2";
+static const CHAR Nv11Vendor[] = "NVidia Corporation";
+static const CHAR IntelBrookdale[] = "Brookdale-G Graphics Controller";
+static const PCHAR BrokenVesaBiosList[] =
+{
+    "SiS 5597",
+    "MGA-G100",
+    "3Dfx Banshee",
+    "Voodoo3 2000 LC ",
+    "Voodoo3 3000 LC ",
+    "Voodoo4 4500 ",
+    "ArtX I",
+    "ATI S1-370TL"
+};
+
+BOOLEAN g_bIntelBrookdaleBIOS;
+
+/* FUNCTIONS ******************************************************************/
+
+BOOLEAN
+NTAPI
+IsVesaBiosOk(IN PVIDEO_PORT_INT10_INTERFACE Interface,
+             IN ULONG OemRevision,
+             IN PCHAR Vendor,
+             IN PCHAR Product,
+             IN PCHAR Revision)
+{
+    ULONG i;
+    CHAR Version[21];
+
+    /* If the broken VESA bios found, turn VESA off */
+    VideoDebugPrint((0, "Vendor: %s Product: %s Revision: %s (%lx)\n", Vendor, Product, Revision, OemRevision));
+    for (i = 0; i < (sizeof(BrokenVesaBiosList) / sizeof(PCHAR)); i++)
+    {
+        if (!strncmp(Product, BrokenVesaBiosList[i], strlen(BrokenVesaBiosList[i]))) return FALSE;
+    }
+
+    /* For Brookdale-G (Intel), special hack used */
+    g_bIntelBrookdaleBIOS = !strncmp(Product, IntelBrookdale, sizeof(IntelBrookdale) - 1);
+
+    /* For NVIDIA make sure */
+    if (!(strncmp(Vendor, Nv11Vendor, sizeof(Nv11Vendor) - 1)) &&
+        !(strncmp(Product, Nv11Board, sizeof(Nv11Board) - 1)) &&
+        !(strncmp(Revision, Nv11Chip, sizeof(Nv11Chip) - 1)) &&
+        (OemRevision == 0x311))
+    {
+        /* Read version */
+        if (Interface->Int10ReadMemory(Interface->Context,
+                                       0xC000,
+                                       345,
+                                       Version,
+                                       sizeof(Version))) return FALSE;
+        if (!strncmp(Version, "Version 3.11.01.24N16", sizeof(Version))) return FALSE;
+    }
+
+    /* VESA ok */
+    VideoDebugPrint((0, "Vesa ok\n"));
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+ValidateVbeInfo(IN PHW_DEVICE_EXTENSION VgaExtension,
+                IN PVBE_INFO VbeInfo)
+{
+    BOOLEAN VesaBiosOk;
+    PVOID Context;
+    CHAR ProductRevision[80];
+    CHAR OemString[80];
+    CHAR ProductName[80];
+    CHAR VendorName[80];
+    VP_STATUS Status;
+
+    /* Set default */
+    VesaBiosOk = FALSE;
+    Context = VgaExtension->Int10Interface.Context;
+
+    /* Check magic and version */
+    if (VbeInfo->Info.Signature != VESA_MAGIC) return VesaBiosOk;
+    if (VbeInfo->Info.Version < 0x102) return VesaBiosOk;
+
+    /* Read strings */
+    Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
+                                                          HIWORD(VbeInfo->Info.OemStringPtr),
+                                                          LOWORD(VbeInfo->Info.OemStringPtr),
+                                                          OemString,
+                                                          sizeof(OemString));
+    if (Status != NO_ERROR) return VesaBiosOk;
+    Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
+                                                          HIWORD(VbeInfo->Info.OemVendorNamePtr),
+                                                          LOWORD(VbeInfo->Info.OemVendorNamePtr),
+                                                          VendorName,
+                                                          sizeof(VendorName));
+    if (Status != NO_ERROR) return VesaBiosOk;
+    Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
+                                                          HIWORD(VbeInfo->Info.OemProductNamePtr),
+                                                          LOWORD(VbeInfo->Info.OemProductNamePtr),
+                                                          ProductName,
+                                                          sizeof(ProductName));
+    if (Status != NO_ERROR) return VesaBiosOk;
+    Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
+                                                          HIWORD(VbeInfo->Info.OemProductRevPtr),
+                                                          LOWORD(VbeInfo->Info.OemProductRevPtr),
+                                                          ProductRevision,
+                                                          sizeof(ProductRevision));
+    if (Status != NO_ERROR) return VesaBiosOk;
+
+    /* Null-terminate strings */
+    VendorName[sizeof(OemString) - 1] = ANSI_NULL;
+    ProductName[sizeof(OemString) - 1] = ANSI_NULL;
+    ProductRevision[sizeof(OemString) - 1] = ANSI_NULL;
+    OemString[sizeof(OemString) - 1] = ANSI_NULL;
+
+    /* Check for known bad BIOS */
+    VesaBiosOk = IsVesaBiosOk(&VgaExtension->Int10Interface,
+                              VbeInfo->Info.OemSoftwareRevision,
+                              VendorName,
+                              ProductName,
+                              ProductRevision);
+    VgaExtension->VesaBiosOk = VesaBiosOk;
+    return VesaBiosOk;
+}
+
+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;
+}
+
+/* EOF */