Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvbemodes.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
1.7.6.1
|