xref: /reactos/win32ss/drivers/miniport/vga_new/vbe.c (revision 84ccccab)
1 /*
2  * PROJECT:         ReactOS VGA Miniport Driver
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            win32ss/drivers/miniport/vga_new/vbe.c
5  * PURPOSE:         Main VESA VBE 1.02+ SVGA Miniport Handling Code
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "vga.h"
12 
13 /* GLOBALS ********************************************************************/
14 
15 static const CHAR Nv11Board[] = "NV11 (GeForce2) Board";
16 static const CHAR Nv11Chip[] = "Chip Rev B2";
17 static const CHAR Nv11Vendor[] = "NVidia Corporation";
18 static const CHAR IntelBrookdale[] = "Brookdale-G Graphics Controller";
19 static const PCHAR BrokenVesaBiosList[] =
20 {
21     "SiS 5597",
22     "MGA-G100",
23     "3Dfx Banshee",
24     "Voodoo3 2000 LC ",
25     "Voodoo3 3000 LC ",
26     "Voodoo4 4500 ",
27     "ArtX I",
28     "ATI S1-370TL"
29 };
30 
31 BOOLEAN g_bIntelBrookdaleBIOS;
32 
33 /* FUNCTIONS ******************************************************************/
34 
35 BOOLEAN
36 NTAPI
37 IsVesaBiosOk(IN PVIDEO_PORT_INT10_INTERFACE Interface,
38              IN ULONG OemRevision,
39              IN PCHAR Vendor,
40              IN PCHAR Product,
41              IN PCHAR Revision)
42 {
43     ULONG i;
44     CHAR Version[21];
45 
46     /* If the broken VESA bios found, turn VESA off */
47     VideoDebugPrint((0, "Vendor: %s Product: %s Revision: %s (%lx)\n", Vendor, Product, Revision, OemRevision));
48     for (i = 0; i < (sizeof(BrokenVesaBiosList) / sizeof(PCHAR)); i++)
49     {
50         if (!strncmp(Product, BrokenVesaBiosList[i], strlen(BrokenVesaBiosList[i]))) return FALSE;
51     }
52 
53     /* For Brookdale-G (Intel), special hack used */
54     g_bIntelBrookdaleBIOS = !strncmp(Product, IntelBrookdale, sizeof(IntelBrookdale) - 1);
55 
56     /* For NVIDIA make sure */
57     if (!(strncmp(Vendor, Nv11Vendor, sizeof(Nv11Vendor) - 1)) &&
58         !(strncmp(Product, Nv11Board, sizeof(Nv11Board) - 1)) &&
59         !(strncmp(Revision, Nv11Chip, sizeof(Nv11Chip) - 1)) &&
60         (OemRevision == 0x311))
61     {
62         /* Read version */
63         if (Interface->Int10ReadMemory(Interface->Context,
64                                        0xC000,
65                                        345,
66                                        Version,
67                                        sizeof(Version))) return FALSE;
68         if (!strncmp(Version, "Version 3.11.01.24N16", sizeof(Version))) return FALSE;
69     }
70 
71     /* VESA ok */
72     VideoDebugPrint((0, "Vesa ok\n"));
73     return TRUE;
74 }
75 
76 BOOLEAN
77 NTAPI
78 ValidateVbeInfo(IN PHW_DEVICE_EXTENSION VgaExtension,
79                 IN PVBE_INFO VbeInfo)
80 {
81     BOOLEAN VesaBiosOk;
82     PVOID Context;
83     CHAR ProductRevision[80];
84     CHAR OemString[80];
85     CHAR ProductName[80];
86     CHAR VendorName[80];
87     VP_STATUS Status;
88 
89     /* Set default */
90     VesaBiosOk = FALSE;
91     Context = VgaExtension->Int10Interface.Context;
92 
93     /* Check magic and version */
94     if (VbeInfo->Info.Signature != VESA_MAGIC) return VesaBiosOk;
95     if (VbeInfo->Info.Version < 0x102) return VesaBiosOk;
96 
97     /* Read strings */
98     Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
99                                                           HIWORD(VbeInfo->Info.OemStringPtr),
100                                                           LOWORD(VbeInfo->Info.OemStringPtr),
101                                                           OemString,
102                                                           sizeof(OemString));
103     if (Status != NO_ERROR) return VesaBiosOk;
104     Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
105                                                           HIWORD(VbeInfo->Info.OemVendorNamePtr),
106                                                           LOWORD(VbeInfo->Info.OemVendorNamePtr),
107                                                           VendorName,
108                                                           sizeof(VendorName));
109     if (Status != NO_ERROR) return VesaBiosOk;
110     Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
111                                                           HIWORD(VbeInfo->Info.OemProductNamePtr),
112                                                           LOWORD(VbeInfo->Info.OemProductNamePtr),
113                                                           ProductName,
114                                                           sizeof(ProductName));
115     if (Status != NO_ERROR) return VesaBiosOk;
116     Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
117                                                           HIWORD(VbeInfo->Info.OemProductRevPtr),
118                                                           LOWORD(VbeInfo->Info.OemProductRevPtr),
119                                                           ProductRevision,
120                                                           sizeof(ProductRevision));
121     if (Status != NO_ERROR) return VesaBiosOk;
122 
123     /* Null-terminate strings */
124     VendorName[sizeof(OemString) - 1] = ANSI_NULL;
125     ProductName[sizeof(OemString) - 1] = ANSI_NULL;
126     ProductRevision[sizeof(OemString) - 1] = ANSI_NULL;
127     OemString[sizeof(OemString) - 1] = ANSI_NULL;
128 
129     /* Check for known bad BIOS */
130     VesaBiosOk = IsVesaBiosOk(&VgaExtension->Int10Interface,
131                               VbeInfo->Info.OemSoftwareRevision,
132                               VendorName,
133                               ProductName,
134                               ProductRevision);
135     VgaExtension->VesaBiosOk = VesaBiosOk;
136     return VesaBiosOk;
137 }
138 
139 VP_STATUS
140 NTAPI
141 VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension,
142                   IN PVIDEO_CLUT ClutBuffer)
143 {
144     PVBE_COLOR_REGISTER VesaClut;
145     INT10_BIOS_ARGUMENTS BiosArguments;
146     PVOID Context;
147     ULONG Entries;
148     ULONG BufferSize = 4 * 1024;
149     USHORT TrampolineMemorySegment, TrampolineMemoryOffset;
150     VP_STATUS Status;
151     USHORT i;
152     PVIDEOMODE CurrentMode = VgaExtension->CurrentMode;
153 
154     Entries = ClutBuffer->NumEntries;
155 
156     VideoDebugPrint((0, "Setting %lu entries.\n", Entries));
157 
158     /*
159      * For Vga compatible modes, write them directly.
160      * Otherwise, the LGPL VGABIOS (used in bochs) fails!
161      * It is also said that this way is faster.
162      */
163     if(!CurrentMode->NonVgaMode)
164     {
165         for (i=ClutBuffer->FirstEntry; i<ClutBuffer->FirstEntry + Entries; i++)
166         {
167             VideoPortWritePortUchar((PUCHAR)0x03c8, i);
168             VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Red);
169             VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Green);
170             VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Blue);
171         }
172         return NO_ERROR;
173     }
174 
175     /* Allocate INT10 context/buffer */
176     VesaClut = VideoPortAllocatePool(VgaExtension, 1, sizeof(ULONG) * Entries, ' agV');
177     if (!VesaClut) return ERROR_INVALID_PARAMETER;
178     if (!VgaExtension->Int10Interface.Size) return ERROR_INVALID_PARAMETER;
179     Context = VgaExtension->Int10Interface.Context;
180     Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context,
181                                                             &TrampolineMemorySegment,
182                                                             &TrampolineMemoryOffset,
183                                                             &BufferSize);
184     if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;
185 
186     /* VESA has color registers backward! */
187     for (i = 0; i < Entries; i++)
188     {
189         VesaClut[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue;
190         VesaClut[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green;
191         VesaClut[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red;
192         VesaClut[i].Pad = 0;
193     }
194     Status = VgaExtension->Int10Interface.Int10WriteMemory(Context,
195                                                          TrampolineMemorySegment,
196                                                          TrampolineMemoryOffset,
197                                                          VesaClut,
198                                                          Entries * sizeof(ULONG));
199     if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;
200 
201     /* Write the palette */
202     VideoPortZeroMemory(&BiosArguments, sizeof(BiosArguments));
203     BiosArguments.Ebx = 0;
204     BiosArguments.Ecx = Entries;
205     BiosArguments.Edx = ClutBuffer->FirstEntry;
206     BiosArguments.Edi = TrampolineMemoryOffset;
207     BiosArguments.SegEs = TrampolineMemorySegment;
208     BiosArguments.Eax = VBE_SET_GET_PALETTE_DATA;
209     Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments);
210     if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER;
211     VideoPortFreePool(VgaExtension, VesaClut);
212     VideoDebugPrint((Error, "VBE Status: %lx\n", BiosArguments.Eax));
213     if (VBE_GETRETURNCODE(BiosArguments.Eax) == VBE_SUCCESS)
214         return NO_ERROR;
215     return ERROR_INVALID_PARAMETER;
216 }
217 
218 /* EOF */
219