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

vbemodes.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS VGA Miniport Driver
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            boot/drivers/video/miniport/vga/vbemodes.c
00005  * PURPOSE:         Mode Initialization and Mode Set for VBE-compatible cards
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 /* INCLUDES *******************************************************************/
00010 
00011 #include "vga.h"
00012 
00013 /* FUNCTIONS ******************************************************************/
00014 
00015 ULONG
00016 NTAPI
00017 RaiseToPower2Ulong(IN ULONG Value)
00018 {
00019     ULONG SquaredResult = Value;
00020     if ((Value - 1) & Value) for (SquaredResult = 1; (SquaredResult < Value) && (SquaredResult); SquaredResult *= 2);
00021     return SquaredResult;
00022 }
00023 
00024 ULONG
00025 NTAPI
00026 RaiseToPower2(IN USHORT Value)
00027 {
00028     ULONG SquaredResult = Value;
00029     if ((Value - 1) & Value) for (SquaredResult = 1; (SquaredResult < Value) && (SquaredResult); SquaredResult *= 2);
00030     return SquaredResult;
00031 }
00032 
00033 ULONG
00034 NTAPI
00035 VbeGetVideoMemoryBaseAddress(IN PHW_DEVICE_EXTENSION VgaExtension,
00036                              IN PVIDEOMODE VgaMode)
00037 {
00038     ULONG Length = 4 * 1024;
00039     USHORT TrampolineMemorySegment, TrampolineMemoryOffset;
00040     PVOID Context;
00041     INT10_BIOS_ARGUMENTS BiosArguments;
00042     PVBE_MODE_INFO VbeModeInfo;
00043     ULONG BaseAddress;
00044     VP_STATUS Status;
00045 
00046     /* Need linear and INT10 interface */
00047     if (!(VgaMode->fbType & VIDEO_MODE_BANKED)) return 0;
00048     if (VgaExtension->Int10Interface.Size) return 0;
00049 
00050     /* Allocate scratch area and context */
00051     VbeModeInfo = VideoPortAllocatePool(VgaExtension, 1, sizeof(VBE_MODE_INFO), ' agV');
00052     if (!VbeModeInfo) return 0;
00053     Context = VgaExtension->Int10Interface.Context;
00054     Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context,
00055                                                               &TrampolineMemorySegment,
00056                                                               &TrampolineMemoryOffset,
00057                                                               &Length);
00058     if (Status != NO_ERROR) return 0;
00059 
00060     /* Ask VBE BIOS for mode info */
00061     BiosArguments.Ecx = HIWORD(VgaMode->Mode);
00062     BiosArguments.Edi = TrampolineMemorySegment;
00063     BiosArguments.SegEs = TrampolineMemoryOffset;
00064     BiosArguments.Eax = VBE_GET_MODE_INFORMATION;
00065     Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments);
00066     if (Status != NO_ERROR) return 0;
00067     if (BiosArguments.Eax != VBE_SUCCESS) return 0;
00068     Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
00069                                                           TrampolineMemorySegment,
00070                                                           TrampolineMemoryOffset,
00071                                                           VbeModeInfo,
00072                                                           sizeof(VBE_MODE_INFO));
00073     if (Status != NO_ERROR) return 0;
00074 
00075     /* Return phys address and cleanup */
00076     BaseAddress = VbeModeInfo->PhysBasePtr;
00077     VgaExtension->Int10Interface.Int10FreeBuffer(Context,
00078                                                  TrampolineMemorySegment,
00079                                                  TrampolineMemoryOffset);
00080     VideoPortFreePool(VgaExtension, VbeModeInfo);
00081     return BaseAddress;
00082 }
00083 
00084 VP_STATUS
00085 NTAPI
00086 VbeSetMode(IN PHW_DEVICE_EXTENSION VgaDeviceExtension,
00087            IN PVIDEOMODE VgaMode,
00088            OUT PULONG PhysPtrChange)
00089 {
00090     VP_STATUS Status;
00091     VIDEO_X86_BIOS_ARGUMENTS BiosArguments;
00092     ULONG ModeIndex;
00093     ULONG BaseAddress;
00094 
00095     VideoPortZeroMemory(&BiosArguments, sizeof(BiosArguments));
00096     ModeIndex = VgaMode->Mode;
00097     BiosArguments.Eax = ModeIndex & 0x0000FFFF;
00098     BiosArguments.Ebx = ModeIndex >> 16;
00099     VideoPortDebugPrint(0, "Switching to %lx %lx\n", BiosArguments.Eax, BiosArguments.Ebx);
00100     Status = VideoPortInt10(VgaDeviceExtension, &BiosArguments);
00101     if (Status != NO_ERROR) return Status;
00102 
00103     /* Check for VESA mode */
00104     if (ModeIndex >> 16)
00105     {
00106         /* Mode set fail */
00107         if (BiosArguments.Eax != VBE_SUCCESS) return ERROR_INVALID_PARAMETER;
00108 
00109         /* Check current mode is desired mode */
00110         BiosArguments.Eax = VBE_GET_CURRENT_VBE_MODE;
00111         Status = VideoPortInt10(VgaDeviceExtension, &BiosArguments);
00112         if ((Status == NO_ERROR) &&
00113             (BiosArguments.Eax == VBE_SUCCESS) &&
00114             ((BiosArguments.Ebx ^ (ModeIndex >> 16)) & VBE_MODE_BITS))
00115         {
00116             return ERROR_INVALID_PARAMETER;
00117         }
00118 
00119         /* Set logical scanline width if different from physical */
00120         if (VgaMode->LogicalWidth != VgaMode->hres)
00121         {
00122             /* Check setting works after being set */
00123             BiosArguments.Eax = VBE_SET_GET_LOGICAL_SCAN_LINE_LENGTH;
00124             BiosArguments.Ecx = VgaMode->LogicalWidth;
00125             BiosArguments.Ebx = 0;
00126             Status = VideoPortInt10(VgaDeviceExtension, &BiosArguments);
00127             if ((Status != NO_ERROR) ||
00128                 (BiosArguments.Eax != VBE_SUCCESS) ||
00129                 (BiosArguments.Ecx != VgaMode->LogicalWidth))
00130             {
00131                 return ERROR_INVALID_PARAMETER;
00132             }
00133         }
00134     }
00135 
00136     /* Get VRAM address to update changes */
00137     BaseAddress = VbeGetVideoMemoryBaseAddress(VgaDeviceExtension, VgaMode);
00138     if ((BaseAddress) && (VgaMode->PhysBase != BaseAddress))
00139     {
00140         *PhysPtrChange = TRUE;
00141         VgaMode->PhysBase = BaseAddress;
00142     }
00143 
00144     return NO_ERROR;
00145 }
00146 
00147 VOID
00148 NTAPI
00149 InitializeModeTable(IN PHW_DEVICE_EXTENSION VgaExtension)
00150 {
00151     ULONG ModeCount = 0;
00152     ULONG Length = 4 * 1024;
00153     ULONG TotalMemory;
00154     VP_STATUS Status;
00155     INT10_BIOS_ARGUMENTS BiosArguments;
00156     PVBE_INFO VbeInfo;
00157     PVBE_MODE_INFO VbeModeInfo;
00158     PVOID Context;
00159     USHORT TrampolineMemorySegment;
00160     USHORT TrampolineMemoryOffset;
00161     ULONG VbeVersion;
00162     ULONG NewModes = 0;
00163     BOOLEAN FourBppModeFound = FALSE;
00164     USHORT ModeResult;
00165     USHORT Mode;
00166     PUSHORT ThisMode;
00167     BOOLEAN LinearAddressing;
00168     ULONG Size, ScreenSize;
00169     PVIDEOMODE VgaMode;
00170     PVOID BaseAddress;
00171     ULONG ScreenStride = 0;
00172     PHYSICAL_ADDRESS PhysicalAddress;
00173 
00174     /* Enable only default vga modes if no vesa */
00175     VgaModeList = ModesVGA;
00176     if (VideoPortIsNoVesa())
00177     {
00178         VgaExtension->Int10Interface.Size = 0;
00179         VgaExtension->Int10Interface.Version = 0;
00180         return;
00181     }
00182 
00183     /* Query INT10 interface */
00184     VgaExtension->Int10Interface.Version = VIDEO_PORT_INT10_INTERFACE_VERSION_1;
00185     VgaExtension->Int10Interface.Size = sizeof(VIDEO_PORT_INT10_INTERFACE);
00186     if (VideoPortQueryServices(VgaExtension,
00187                                VideoPortServicesInt10,
00188                                (PINTERFACE)&VgaExtension->Int10Interface))
00189     {
00190         VgaExtension->Int10Interface.Size = 0;
00191         VgaExtension->Int10Interface.Version = 0;
00192     }
00193 
00194     /* Add ref */
00195     //VideoPortDebugPrint(0, "have int10 iface\n");
00196     VgaExtension->Int10Interface.InterfaceReference(VgaExtension->Int10Interface.Context);
00197     Context = VgaExtension->Int10Interface.Context;
00198 
00199     /* Allocate scratch area and context */
00200     Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context,
00201                                                               &TrampolineMemorySegment,
00202                                                               &TrampolineMemoryOffset,
00203                                                               &Length);
00204     if (Status != NO_ERROR) return;
00205     VbeInfo = VideoPortAllocatePool(VgaExtension, 1, sizeof(VBE_INFO), ' agV');
00206     VbeModeInfo = &VbeInfo->Modes;
00207     if (!VbeInfo) return;
00208 
00209     /* Init VBE data and write to card buffer */
00210     //VideoPortDebugPrint(0, "have int10 data\n");
00211     VbeInfo->ModeArray[128] = 0xFFFF;
00212     VbeInfo->Info.Signature = VBE2_MAGIC;
00213     Status = VgaExtension->Int10Interface.Int10WriteMemory(Context,
00214                                                            TrampolineMemorySegment,
00215                                                            TrampolineMemoryOffset,
00216                                                            VbeInfo,
00217                                                            512);
00218     if (Status != NO_ERROR) return;
00219 
00220     /* Get controller info */
00221     BiosArguments.Edi = TrampolineMemoryOffset;
00222     BiosArguments.SegEs = TrampolineMemorySegment;
00223     BiosArguments.Eax = VBE_GET_CONTROLLER_INFORMATION;
00224     Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments);
00225     if (Status != NO_ERROR) return;
00226     if (BiosArguments.Eax != VBE_SUCCESS) return;
00227     Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
00228                                                           TrampolineMemorySegment,
00229                                                           TrampolineMemoryOffset,
00230                                                           VbeInfo,
00231                                                           512);
00232     if (Status != NO_ERROR) return;
00233 
00234     /* Check correct VBE BIOS */
00235     //VideoPortDebugPrint(0, "have vbe data\n");
00236     TotalMemory = VbeInfo->Info.TotalMemory << 16;
00237     VbeVersion = VbeInfo->Info.Version;
00238     VideoPortDebugPrint(0, "vbe version %lx memory %lx\n", VbeVersion, TotalMemory);
00239     if (!ValidateVbeInfo(VgaExtension, VbeInfo)) return;
00240 
00241     /* Read modes */
00242     //VideoPortDebugPrint(0, "read modes from %p\n", VbeInfo->Info.VideoModePtr);
00243     Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
00244                                                           HIWORD(VbeInfo->Info.VideoModePtr),
00245                                                           LOWORD(VbeInfo->Info.VideoModePtr),
00246                                                           VbeInfo->ModeArray,
00247                                                           128 * sizeof(USHORT));
00248     if (Status != NO_ERROR) return;
00249     //VideoPortDebugPrint(0, "Read modes at: %p\n", VbeInfo->ModeArray);
00250 
00251     /* Count modes, check for new 4bpp SVGA modes */
00252     ThisMode = VbeInfo->ModeArray;
00253     ModeResult = VbeInfo->ModeArray[0];
00254     while (ModeResult != 0xFFFF)
00255     {
00256         Mode = ModeResult & 0x1FF;
00257         //VideoPortDebugPrint(0, "Mode found: %lx\n", Mode);
00258         if ((Mode == 0x102) || (Mode == 0x6A)) FourBppModeFound = TRUE;
00259         ModeResult = *++ThisMode;
00260         NewModes++;
00261     }
00262 
00263     /* Remove the built-in mode if not supported by card and check max modes */
00264     if (!FourBppModeFound) --NumVideoModes;
00265     if ((NewModes >= 128) && (NumVideoModes > 8)) goto Cleanup;
00266 
00267     /* Switch to new SVGA mode list, copy VGA modes */
00268     VgaModeList = VideoPortAllocatePool(VgaExtension, 1, (NewModes + NumVideoModes) * sizeof(VIDEOMODE), ' agV');
00269     if (!VgaModeList) goto Cleanup;
00270     VideoPortMoveMemory(VgaModeList, ModesVGA, NumVideoModes * sizeof(VIDEOMODE));
00271 
00272     /* Apply fixup for Intel Brookdale */
00273     if (g_bIntelBrookdaleBIOS)
00274     {
00275         VideoPortDebugPrint(0, "Intel Brookdale-G Video BIOS Not Support!\n");
00276         while (TRUE);
00277     }
00278 
00279     /* Scan SVGA modes */
00280 //    VideoPortDebugPrint(0, "Static modes: %d\n", NumVideoModes);
00281     VgaMode = &VgaModeList[NumVideoModes];
00282     ThisMode = VbeInfo->ModeArray;
00283     //VideoPortDebugPrint(0, "new modes: %d\n", NewModes);
00284     while (NewModes--)
00285     {
00286         /* Get info on mode */
00287         BiosArguments.Eax = VBE_GET_MODE_INFORMATION;
00288         BiosArguments.Ecx = *ThisMode;
00289         BiosArguments.Edi = TrampolineMemoryOffset;
00290         BiosArguments.SegEs = TrampolineMemorySegment;
00291         Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments);
00292         if (Status != NO_ERROR) goto Next;
00293         if (BiosArguments.Eax != VBE_SUCCESS) goto Next;
00294         Status = VgaExtension->Int10Interface.Int10ReadMemory(Context,
00295                                                               TrampolineMemorySegment,
00296                                                               TrampolineMemoryOffset,
00297                                                               VbeModeInfo,
00298                                                               256);
00299         if (Status != NO_ERROR) goto Next;
00300 
00301         /* Parse graphics modes only if linear framebuffer support */
00302         //VideoPortDebugPrint(0, "attr: %lx\n", VbeModeInfo->ModeAttributes);
00303         if (!(VbeModeInfo->ModeAttributes & (VBE_MODEATTR_VALID |
00304                                              VBE_MODEATTR_GRAPHICS))) goto Next;
00305         LinearAddressing = ((VbeVersion >= 0x200) &&
00306                             (VbeModeInfo->PhysBasePtr) &&
00307                             (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR)) ?
00308                             TRUE : FALSE;
00309 
00310         /* Check SVGA modes if 8bpp or higher */
00311         //VideoPortDebugPrint(0, "PhysBase: %lx\n", VbeModeInfo->PhysBasePtr);
00312         if ((VbeModeInfo->XResolution >= 640) &&
00313             (VbeModeInfo->YResolution >= 480) &&
00314             (VbeModeInfo->NumberOfPlanes >= 1) &&
00315             (VbeModeInfo->BitsPerPixel >= 8))
00316         {
00317             /* Copy VGA mode info */
00318             VideoPortZeroMemory(VgaMode, sizeof(VIDEOMODE));
00319             VgaMode->numPlanes = VbeModeInfo->NumberOfPlanes;
00320             VgaMode->hres = VbeModeInfo->XResolution;
00321             VgaMode->vres = VbeModeInfo->YResolution;
00322             VgaMode->Frequency = 1;
00323             VgaMode->Mode = (*ThisMode << 16) | VBE_SET_VBE_MODE;
00324             VgaMode->Granularity = VbeModeInfo->WinGranularity << 10;
00325             //VideoPortDebugPrint(0, "Mode %lx (Granularity %d)\n", VgaMode->Mode, VgaMode->Granularity);
00326 
00327             /* Set flags */
00328             if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_COLOR) VgaMode->fbType |= VIDEO_MODE_COLOR;
00329             if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_GRAPHICS) VgaMode->fbType |= VIDEO_MODE_GRAPHICS;
00330             if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_NON_VGA) VgaMode->NonVgaMode = TRUE;
00331 
00332             /* If no char data, say 80x25 */
00333             VgaMode->col = VbeModeInfo->XCharSize ? VbeModeInfo->XResolution / VbeModeInfo->XCharSize : 80;
00334             VgaMode->row = VbeModeInfo->YCharSize ? VbeModeInfo->YResolution / VbeModeInfo->YCharSize : 25;
00335             //VideoPortDebugPrint(0, "%d by %d rows\n", VgaMode->Columns, VgaMode->Rows);
00336 
00337             /* Check RGB555 (15bpp only) */
00338             VgaMode->bitsPerPlane = VbeModeInfo->BitsPerPixel / VbeModeInfo->NumberOfPlanes;
00339             if ((VgaMode->bitsPerPlane == 16) && (VbeModeInfo->GreenMaskSize == 5)) VgaMode->bitsPerPlane = 15;
00340             //VideoPortDebugPrint(0, "BPP: %d\n", VgaMode->BitsPerPlane);
00341 
00342             /* Do linear or banked frame buffers */
00343             VgaMode->FrameBufferBase = 0;
00344             if (!LinearAddressing)
00345             {
00346                 /* Read the screen stride (scanline size) */
00347                 ScreenStride = RaiseToPower2(VbeModeInfo->BytesPerScanLine);
00348                 VgaMode->wbytes = ScreenStride;
00349                 //VideoPortDebugPrint(0, "ScanLines: %lx Stride: %lx\n", VbeModeInfo->BytesPerScanLine, VgaMode->Stride);
00350 
00351                 /* Size of frame buffer is Height X ScanLine, align to bank/page size */
00352                 ScreenSize = VgaMode->hres * ScreenStride;
00353                 //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize);
00354                 Size = (ScreenSize + ((64 * 1024) - 1)) & ((64 * 1024) - 1);
00355                 //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize);
00356                 if (Size > TotalMemory) Size = (Size + ((4 * 1024) - 1)) & ((4 * 1024) - 1);
00357                 //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize);
00358 
00359                 /* Banked VGA at 0xA0000 (64K) */
00360                 //VideoPortDebugPrint(0, "Final size: %lx\n", Size);
00361                 VgaMode->fbType |= VIDEO_MODE_BANKED;
00362                 VgaMode->sbytes = Size;
00363                 VgaMode->PhysSize = 64 * 1024;
00364                 VgaMode->FrameBufferSize = 64 * 1024;
00365                 VgaMode->NoBankSwitch = TRUE;
00366                 VgaMode->PhysBase = 0xA0000;
00367                 VgaMode->LogicalWidth = RaiseToPower2(VgaMode->hres);
00368             }
00369             else
00370             {
00371                 /* VBE 3.00+ has specific field, read legacy field if not */
00372                 //VideoPortDebugPrint(0, "LINEAR MODE!!!\n");
00373                 ScreenStride = (VbeVersion >= 0x300) ? VbeModeInfo->LinBytesPerScanLine : 0;
00374                 if (!ScreenStride) ScreenStride = VbeModeInfo->BytesPerScanLine;
00375                 VgaMode->wbytes = ScreenStride;
00376                 //VideoPortDebugPrint(0, "ScanLines: %lx Stride: %lx\n", VbeModeInfo->BytesPerScanLine, VgaMode->Stride);
00377 
00378                 /* Size of frame buffer is Height X ScanLine, align to page size */
00379                 ScreenSize = VgaMode->hres * LOWORD(VgaMode->wbytes);
00380                 //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize);
00381                 Size = RaiseToPower2Ulong(ScreenSize);
00382                 //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize);
00383                 if (Size > TotalMemory) Size = (Size + ((4 * 1024) - 1)) & ((4 * 1024) - 1);
00384                 //VideoPortDebugPrint(0, "Size: %lx\n", ScreenSize);
00385 
00386                 /* Linear VGA must read settings from VBE */
00387                 VgaMode->fbType |= VIDEO_MODE_LINEAR;
00388                 VgaMode->sbytes = Size;
00389                 VgaMode->PhysSize = Size;
00390                 VgaMode->FrameBufferSize = Size;
00391                 VgaMode->NoBankSwitch = FALSE;
00392                 VgaMode->PhysBase = VbeModeInfo->PhysBasePtr;
00393                 VgaMode->LogicalWidth = VgaMode->hres;
00394 
00395                 /* Make VBE_SET_VBE_MODE command use Linear Framebuffer Select */
00396                 VgaMode->Mode |= (VBE_MODE_LINEAR_FRAMEBUFFER << 16);
00397             }
00398 
00399             /* Override bank switch if not support by card */
00400             if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_NO_BANK_SWITCH) VgaMode->NoBankSwitch = TRUE;
00401 
00402             /* Next */
00403             if (ScreenSize <= TotalMemory)
00404             {
00405                 VgaMode++;
00406                 ModeCount++;
00407             }
00408         }
00409 Next:
00410         /* Next */
00411         ThisMode++;
00412     }
00413 
00414     /* Check if last mode was color to do test */
00415     VideoPortDebugPrint(0, "mode scan complete. Total modes: %d\n", ModeCount);
00416     if (--VgaMode->fbType & VIDEO_MODE_COLOR)
00417     {
00418         /* Try map physical buffer and free if worked */
00419         PhysicalAddress.QuadPart = VgaMode->PhysBase;
00420         BaseAddress = VideoPortGetDeviceBase(VgaExtension, PhysicalAddress, 4 * 1024, FALSE);
00421         if (BaseAddress)
00422         {
00423             VideoPortFreeDeviceBase(VgaExtension, BaseAddress);
00424         }
00425         else
00426         {
00427             /* Not work, so throw out VBE data */
00428             ModeCount = 0;
00429         }
00430     }
00431 
00432     /* Cleanup sucess path */
00433     VideoPortFreePool(VgaExtension, VbeInfo);
00434     VgaExtension->Int10Interface.Int10FreeBuffer(Context,
00435                                                  TrampolineMemorySegment,
00436                                                  TrampolineMemoryOffset);
00437     NumVideoModes += ModeCount;
00438     return;
00439 
00440 Cleanup:
00441     /* Cleanup failure path, reset standard VGA and free memory */
00442     VgaModeList = ModesVGA;
00443     VideoPortFreePool(VgaExtension, VbeInfo);
00444     VgaExtension->Int10Interface.Int10FreeBuffer(Context,
00445                                                  TrampolineMemorySegment,
00446                                                  TrampolineMemoryOffset);
00447 }
00448 
00449 /* EOF */

Generated on Sun May 27 2012 04:38:12 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.