Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenvbemp.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS VBE miniport video driver 00003 * Copyright (C) 2004 Filip Navara 00004 * 00005 * Power Management and VBE 1.2 support 00006 * Copyright (C) 2004 Magnus Olsen 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License 00010 * as published by the Free Software Foundation; either version 2 00011 * of the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License along 00019 * with this program; if not, write to the Free Software Foundation, Inc., 00020 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00021 * 00022 * TODO: 00023 * - Check input parameters everywhere. 00024 * - Call VideoPortVerifyAccessRanges to reserve the memory we're about 00025 * to map. 00026 */ 00027 00028 /* INCLUDES *******************************************************************/ 00029 00030 #include "vbemp.h" 00031 00032 #undef LOWORD 00033 #undef HIWORD 00034 #define LOWORD(l) ((USHORT)((ULONG_PTR)(l))) 00035 #define HIWORD(l) ((USHORT)(((ULONG_PTR)(l)>>16)&0xFFFF)) 00036 00037 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/ 00038 00039 ULONG NTAPI 00040 DriverEntry(IN PVOID Context1, IN PVOID Context2) 00041 { 00042 VIDEO_HW_INITIALIZATION_DATA InitData; 00043 00044 VideoPortZeroMemory(&InitData, sizeof(InitData)); 00045 InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); 00046 InitData.HwFindAdapter = VBEFindAdapter; 00047 InitData.HwInitialize = VBEInitialize; 00048 InitData.HwStartIO = VBEStartIO; 00049 InitData.HwResetHw = VBEResetHw; 00050 InitData.HwGetPowerState = VBEGetPowerState; 00051 InitData.HwSetPowerState = VBESetPowerState; 00052 InitData.HwGetVideoChildDescriptor = VBEGetVideoChildDescriptor; 00053 InitData.HwDeviceExtensionSize = sizeof(VBE_DEVICE_EXTENSION); 00054 00055 return VideoPortInitialize(Context1, Context2, &InitData, NULL); 00056 } 00057 00058 /* 00059 * VBEFindAdapter 00060 * 00061 * Should detect a VBE compatible display adapter, but it's not possible 00062 * to use video port Int 10 services at this time during initialization, 00063 * so we always return NO_ERROR and do the real work in VBEInitialize. 00064 */ 00065 00066 VP_STATUS NTAPI 00067 VBEFindAdapter( 00068 IN PVOID HwDeviceExtension, 00069 IN PVOID HwContext, 00070 IN PWSTR ArgumentString, 00071 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, 00072 OUT PUCHAR Again) 00073 { 00074 if (VideoPortIsNoVesa()) 00075 return ERROR_DEV_NOT_EXIST; 00076 00077 return NO_ERROR; 00078 } 00079 00080 /* 00081 * VBESortModesCallback 00082 * 00083 * Helper function for sorting video mode list. 00084 */ 00085 00086 static int 00087 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA, PVBE_MODEINFO VbeModeInfoB) 00088 { 00089 VideoPortDebugPrint(Info, "VBESortModesCallback: %dx%dx%d / %dx%dx%d\n", 00090 VbeModeInfoA->XResolution, VbeModeInfoA->YResolution, 00091 VbeModeInfoA->BitsPerPixel, 00092 VbeModeInfoB->XResolution, VbeModeInfoB->YResolution, 00093 VbeModeInfoB->BitsPerPixel); 00094 00095 /* 00096 * FIXME: Until some reasonable method for changing video modes will 00097 * be available we favor more bits per pixel. It should be changed 00098 * later. 00099 */ 00100 if (VbeModeInfoA->BitsPerPixel < VbeModeInfoB->BitsPerPixel) return -1; 00101 if (VbeModeInfoA->BitsPerPixel > VbeModeInfoB->BitsPerPixel) return 1; 00102 if (VbeModeInfoA->XResolution < VbeModeInfoB->XResolution) return -1; 00103 if (VbeModeInfoA->XResolution > VbeModeInfoB->XResolution) return 1; 00104 if (VbeModeInfoA->YResolution < VbeModeInfoB->YResolution) return -1; 00105 if (VbeModeInfoA->YResolution > VbeModeInfoB->YResolution) return 1; 00106 return 0; 00107 } 00108 00109 /* 00110 * VBESortModes 00111 * 00112 * Simple function for sorting the video mode list. Uses bubble sort. 00113 */ 00114 00115 VOID FASTCALL 00116 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension) 00117 { 00118 BOOLEAN Finished = FALSE; 00119 ULONG Pos; 00120 int Result; 00121 VBE_MODEINFO TempModeInfo; 00122 USHORT TempModeNumber; 00123 00124 while (!Finished) 00125 { 00126 Finished = TRUE; 00127 for (Pos = 0; Pos < DeviceExtension->ModeCount - 1; Pos++) 00128 { 00129 Result = VBESortModesCallback( 00130 DeviceExtension->ModeInfo + Pos, 00131 DeviceExtension->ModeInfo + Pos + 1); 00132 if (Result > 0) 00133 { 00134 Finished = FALSE; 00135 00136 VideoPortMoveMemory( 00137 &TempModeInfo, 00138 DeviceExtension->ModeInfo + Pos, 00139 sizeof(VBE_MODEINFO)); 00140 TempModeNumber = DeviceExtension->ModeNumbers[Pos]; 00141 00142 VideoPortMoveMemory( 00143 DeviceExtension->ModeInfo + Pos, 00144 DeviceExtension->ModeInfo + Pos + 1, 00145 sizeof(VBE_MODEINFO)); 00146 DeviceExtension->ModeNumbers[Pos] = 00147 DeviceExtension->ModeNumbers[Pos + 1]; 00148 00149 VideoPortMoveMemory( 00150 DeviceExtension->ModeInfo + Pos + 1, 00151 &TempModeInfo, 00152 sizeof(VBE_MODEINFO)); 00153 DeviceExtension->ModeNumbers[Pos + 1] = TempModeNumber; 00154 } 00155 } 00156 } 00157 } 00158 00159 /* 00160 * VBEInitialize 00161 * 00162 * Performs the first initialization of the adapter, after the HAL has given 00163 * up control of the video hardware to the video port driver. 00164 * 00165 * This function performs these steps: 00166 * - Gets global VBE information and finds if VBE BIOS is present. 00167 * - Builds the internal mode list using the list of modes provided by 00168 * the VBE. 00169 */ 00170 00171 BOOLEAN NTAPI 00172 VBEInitialize(PVOID HwDeviceExtension) 00173 { 00174 INT10_BIOS_ARGUMENTS BiosRegisters; 00175 VP_STATUS Status; 00176 PVBE_DEVICE_EXTENSION VBEDeviceExtension = 00177 (PVBE_DEVICE_EXTENSION)HwDeviceExtension; 00178 ULONG Length; 00179 ULONG ModeCount; 00180 ULONG SuitableModeCount; 00181 USHORT ModeTemp; 00182 ULONG CurrentMode; 00183 PVBE_MODEINFO VbeModeInfo; 00184 00185 /* 00186 * Get the Int 10 interface that we will use for allocating real 00187 * mode memory and calling the video BIOS. 00188 */ 00189 00190 VBEDeviceExtension->Int10Interface.Version = VIDEO_PORT_INT10_INTERFACE_VERSION_1; 00191 VBEDeviceExtension->Int10Interface.Size = sizeof(VIDEO_PORT_INT10_INTERFACE); 00192 Status = VideoPortQueryServices( 00193 HwDeviceExtension, 00194 VideoPortServicesInt10, 00195 (PINTERFACE)&VBEDeviceExtension->Int10Interface); 00196 00197 if (Status != NO_ERROR) 00198 { 00199 VideoPortDebugPrint(Error, "Failed to get Int 10 service functions (Status %x)\n", Status); 00200 return FALSE; 00201 } 00202 00203 /* 00204 * Allocate a bit of memory that will be later used for VBE transport 00205 * buffer. This memory must be accessible from V86 mode so it must fit 00206 * in the first megabyte of physical memory. 00207 */ 00208 00209 Length = 0x400; 00210 Status = VBEDeviceExtension->Int10Interface.Int10AllocateBuffer( 00211 VBEDeviceExtension->Int10Interface.Context, 00212 &VBEDeviceExtension->TrampolineMemorySegment, 00213 &VBEDeviceExtension->TrampolineMemoryOffset, 00214 &Length); 00215 00216 if (Status != NO_ERROR) 00217 { 00218 VideoPortDebugPrint(Error, "Failed to allocate virtual memory (Status %x)\n", Status); 00219 return FALSE; 00220 } 00221 00222 /* 00223 * Get the VBE general information. 00224 */ 00225 00226 VBEDeviceExtension->Int10Interface.Int10WriteMemory( 00227 VBEDeviceExtension->Int10Interface.Context, 00228 VBEDeviceExtension->TrampolineMemorySegment, 00229 VBEDeviceExtension->TrampolineMemoryOffset, 00230 "VBE2", 00231 4); 00232 00233 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 00234 BiosRegisters.Eax = VBE_GET_CONTROLLER_INFORMATION; 00235 BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset; 00236 BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment; 00237 VBEDeviceExtension->Int10Interface.Int10CallBios( 00238 VBEDeviceExtension->Int10Interface.Context, 00239 &BiosRegisters); 00240 00241 if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS) 00242 { 00243 VBEDeviceExtension->Int10Interface.Int10ReadMemory( 00244 VBEDeviceExtension->Int10Interface.Context, 00245 VBEDeviceExtension->TrampolineMemorySegment, 00246 VBEDeviceExtension->TrampolineMemoryOffset, 00247 &VBEDeviceExtension->VbeInfo, 00248 sizeof(VBEDeviceExtension->VbeInfo)); 00249 00250 /* Verify the VBE signature. */ 00251 if (VideoPortCompareMemory(VBEDeviceExtension->VbeInfo.Signature, "VESA", 4) != 4) 00252 { 00253 VideoPortDebugPrint(Error, "No VBE BIOS present\n"); 00254 return FALSE; 00255 } 00256 00257 VideoPortDebugPrint(Trace, "VBE BIOS Present (%d.%d, %8ld Kb)\n", 00258 VBEDeviceExtension->VbeInfo.Version / 0x100, 00259 VBEDeviceExtension->VbeInfo.Version & 0xFF, 00260 VBEDeviceExtension->VbeInfo.TotalMemory * 64); 00261 00262 #ifdef VBE12_SUPPORT 00263 if (VBEDeviceExtension->VbeInfo.Version < 0x102) 00264 #else 00265 if (VBEDeviceExtension->VbeInfo.Version < 0x200) 00266 #endif 00267 { 00268 VideoPortDebugPrint(Error, "VBE BIOS present, but incompatible version %d.%d\n", 00269 VBEDeviceExtension->VbeInfo.Version / 0x100, 00270 VBEDeviceExtension->VbeInfo.Version & 0xFF); 00271 return FALSE; 00272 } 00273 } 00274 else 00275 { 00276 VideoPortDebugPrint(Error, "No VBE BIOS found.\n"); 00277 return FALSE; 00278 } 00279 00280 /* 00281 * Build a mode list here that can be later used by 00282 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES 00283 * calls. 00284 */ 00285 00286 /* 00287 * Get the number of supported video modes. 00288 * 00289 * No need to be map the memory. It's either in the video BIOS memory or 00290 * in our trampoline memory. In either case the memory is already mapped. 00291 */ 00292 00293 for (ModeCount = 0; ; ModeCount++) 00294 { 00295 /* Read the VBE mode number. */ 00296 VBEDeviceExtension->Int10Interface.Int10ReadMemory( 00297 VBEDeviceExtension->Int10Interface.Context, 00298 HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr), 00299 LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (ModeCount << 1), 00300 &ModeTemp, 00301 sizeof(ModeTemp)); 00302 00303 /* End of list? */ 00304 if (ModeTemp == 0xFFFF || ModeTemp == 0) 00305 break; 00306 } 00307 00308 /* 00309 * Allocate space for video modes information. 00310 */ 00311 00312 VBEDeviceExtension->ModeInfo = 00313 VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(VBE_MODEINFO), TAG_VBE); 00314 VBEDeviceExtension->ModeNumbers = 00315 VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(USHORT), TAG_VBE); 00316 00317 /* 00318 * Get the actual mode infos. 00319 */ 00320 00321 for (CurrentMode = 0, SuitableModeCount = 0; 00322 CurrentMode < ModeCount; 00323 CurrentMode++) 00324 { 00325 /* Read the VBE mode number. */ 00326 VBEDeviceExtension->Int10Interface.Int10ReadMemory( 00327 VBEDeviceExtension->Int10Interface.Context, 00328 HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr), 00329 LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (CurrentMode << 1), 00330 &ModeTemp, 00331 sizeof(ModeTemp)); 00332 00333 /* Call VBE BIOS to read the mode info. */ 00334 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 00335 BiosRegisters.Eax = VBE_GET_MODE_INFORMATION; 00336 BiosRegisters.Ecx = ModeTemp; 00337 BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset + 0x200; 00338 BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment; 00339 VBEDeviceExtension->Int10Interface.Int10CallBios( 00340 VBEDeviceExtension->Int10Interface.Context, 00341 &BiosRegisters); 00342 00343 /* Read the VBE mode info. */ 00344 VBEDeviceExtension->Int10Interface.Int10ReadMemory( 00345 VBEDeviceExtension->Int10Interface.Context, 00346 VBEDeviceExtension->TrampolineMemorySegment, 00347 VBEDeviceExtension->TrampolineMemoryOffset + 0x200, 00348 VBEDeviceExtension->ModeInfo + SuitableModeCount, 00349 sizeof(VBE_MODEINFO)); 00350 00351 VbeModeInfo = VBEDeviceExtension->ModeInfo + SuitableModeCount; 00352 00353 /* Is this mode acceptable? */ 00354 if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS && 00355 VbeModeInfo->XResolution >= 640 && 00356 VbeModeInfo->YResolution >= 480 && 00357 (VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_PACKEDPIXEL || 00358 VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_DIRECTCOLOR) && 00359 VbeModeInfo->PhysBasePtr != 0) 00360 { 00361 if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR) 00362 { 00363 /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */ 00364 // if (ModeTemp & 0x4000) 00365 //{ 00366 VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000; 00367 SuitableModeCount++; 00368 //} 00369 } 00370 #ifdef VBE12_SUPPORT 00371 else 00372 { 00373 VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp; 00374 SuitableModeCount++; 00375 } 00376 #endif 00377 } 00378 } 00379 00380 00381 if (SuitableModeCount == 0) 00382 { 00383 00384 VideoPortDebugPrint(Warn, "VBEMP: No video modes supported\n"); 00385 return FALSE; 00386 } 00387 00388 VBEDeviceExtension->ModeCount = SuitableModeCount; 00389 00390 /* 00391 * Sort the video mode list according to resolution and bits per pixel. 00392 */ 00393 00394 VBESortModes(VBEDeviceExtension); 00395 00396 /* 00397 * Print the supported video modes. 00398 */ 00399 00400 for (CurrentMode = 0; 00401 CurrentMode < SuitableModeCount; 00402 CurrentMode++) 00403 { 00404 VideoPortDebugPrint(Trace, "%dx%dx%d\n", 00405 VBEDeviceExtension->ModeInfo[CurrentMode].XResolution, 00406 VBEDeviceExtension->ModeInfo[CurrentMode].YResolution, 00407 VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel); 00408 } 00409 00410 /* 00411 * Enumerate our children. 00412 */ 00413 VideoPortEnumerateChildren(HwDeviceExtension, NULL); 00414 00415 return TRUE; 00416 } 00417 00418 /* 00419 * VBEStartIO 00420 * 00421 * Processes the specified Video Request Packet. 00422 */ 00423 00424 BOOLEAN NTAPI 00425 VBEStartIO( 00426 PVOID HwDeviceExtension, 00427 PVIDEO_REQUEST_PACKET RequestPacket) 00428 { 00429 BOOLEAN Result; 00430 00431 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION; 00432 00433 switch (RequestPacket->IoControlCode) 00434 { 00435 case IOCTL_VIDEO_SET_CURRENT_MODE: 00436 if (RequestPacket->InputBufferLength < sizeof(VIDEO_MODE)) 00437 { 00438 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 00439 return TRUE; 00440 } 00441 Result = VBESetCurrentMode( 00442 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00443 (PVIDEO_MODE)RequestPacket->InputBuffer, 00444 RequestPacket->StatusBlock); 00445 break; 00446 00447 case IOCTL_VIDEO_RESET_DEVICE: 00448 Result = VBEResetDevice( 00449 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00450 RequestPacket->StatusBlock); 00451 break; 00452 00453 case IOCTL_VIDEO_MAP_VIDEO_MEMORY: 00454 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION) || 00455 RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) 00456 { 00457 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 00458 return TRUE; 00459 } 00460 Result = VBEMapVideoMemory( 00461 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00462 (PVIDEO_MEMORY)RequestPacket->InputBuffer, 00463 (PVIDEO_MEMORY_INFORMATION)RequestPacket->OutputBuffer, 00464 RequestPacket->StatusBlock); 00465 break; 00466 00467 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: 00468 if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) 00469 { 00470 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 00471 return TRUE; 00472 } 00473 Result = VBEUnmapVideoMemory( 00474 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00475 (PVIDEO_MEMORY)RequestPacket->InputBuffer, 00476 RequestPacket->StatusBlock); 00477 break; 00478 00479 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: 00480 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES)) 00481 { 00482 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 00483 return TRUE; 00484 } 00485 Result = VBEQueryNumAvailModes( 00486 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00487 (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer, 00488 RequestPacket->StatusBlock); 00489 break; 00490 00491 case IOCTL_VIDEO_QUERY_AVAIL_MODES: 00492 if (RequestPacket->OutputBufferLength < 00493 ((PVBE_DEVICE_EXTENSION)HwDeviceExtension)->ModeCount * sizeof(VIDEO_MODE_INFORMATION)) 00494 { 00495 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 00496 return TRUE; 00497 } 00498 Result = VBEQueryAvailModes( 00499 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00500 (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer, 00501 RequestPacket->StatusBlock); 00502 break; 00503 00504 case IOCTL_VIDEO_SET_COLOR_REGISTERS: 00505 if (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) || 00506 RequestPacket->InputBufferLength < 00507 (((PVIDEO_CLUT)RequestPacket->InputBuffer)->NumEntries * sizeof(ULONG)) + 00508 FIELD_OFFSET(VIDEO_CLUT, LookupTable)) 00509 { 00510 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 00511 return TRUE; 00512 } 00513 Result = VBESetColorRegisters( 00514 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00515 (PVIDEO_CLUT)RequestPacket->InputBuffer, 00516 RequestPacket->StatusBlock); 00517 break; 00518 00519 case IOCTL_VIDEO_QUERY_CURRENT_MODE: 00520 if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION)) 00521 { 00522 RequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER; 00523 return TRUE; 00524 } 00525 Result = VBEQueryCurrentMode( 00526 (PVBE_DEVICE_EXTENSION)HwDeviceExtension, 00527 (PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer, 00528 RequestPacket->StatusBlock); 00529 break; 00530 00531 default: 00532 RequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION; 00533 return FALSE; 00534 } 00535 00536 if (Result) 00537 RequestPacket->StatusBlock->Status = NO_ERROR; 00538 00539 return TRUE; 00540 } 00541 00542 /* 00543 * VBEResetHw 00544 * 00545 * This function is called to reset the hardware to a known state. 00546 */ 00547 00548 BOOLEAN NTAPI 00549 VBEResetHw( 00550 PVOID DeviceExtension, 00551 ULONG Columns, 00552 ULONG Rows) 00553 { 00554 /* Return FALSE to let HAL reset the display with INT10 */ 00555 return FALSE; 00556 } 00557 00558 /* 00559 * VBEGetPowerState 00560 * 00561 * Queries whether the device can support the requested power state. 00562 */ 00563 00564 VP_STATUS NTAPI 00565 VBEGetPowerState( 00566 PVOID HwDeviceExtension, 00567 ULONG HwId, 00568 PVIDEO_POWER_MANAGEMENT VideoPowerControl) 00569 { 00570 INT10_BIOS_ARGUMENTS BiosRegisters; 00571 PVBE_DEVICE_EXTENSION VBEDeviceExtension = 00572 (PVBE_DEVICE_EXTENSION)HwDeviceExtension; 00573 00574 if (HwId != DISPLAY_ADAPTER_HW_ID || 00575 VideoPowerControl->Length < sizeof(VIDEO_POWER_MANAGEMENT)) 00576 return ERROR_INVALID_FUNCTION; 00577 00578 /* 00579 * Get general power support information. 00580 */ 00581 00582 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 00583 BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS; 00584 BiosRegisters.Ebx = 0; 00585 BiosRegisters.Edi = 0; 00586 BiosRegisters.SegEs = 0; 00587 VBEDeviceExtension->Int10Interface.Int10CallBios( 00588 VBEDeviceExtension->Int10Interface.Context, 00589 &BiosRegisters); 00590 00591 if ( VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_NOT_SUPPORTED) 00592 return ERROR_DEV_NOT_EXIST; 00593 if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS) 00594 return ERROR_INVALID_FUNCTION; 00595 00596 /* 00597 * Get current power state. 00598 */ 00599 00600 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 00601 BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS; 00602 BiosRegisters.Ebx = 0x2; 00603 BiosRegisters.Edi = 0; 00604 BiosRegisters.SegEs = 0; 00605 VBEDeviceExtension->Int10Interface.Int10CallBios( 00606 VBEDeviceExtension->Int10Interface.Context, 00607 &BiosRegisters); 00608 00609 if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS) 00610 { 00611 VideoPowerControl->DPMSVersion = BiosRegisters.Ebx & 0xFF; 00612 switch (BiosRegisters.Ebx >> 8) 00613 { 00614 case 0: VideoPowerControl->PowerState = VideoPowerOn; break; 00615 case 1: VideoPowerControl->PowerState = VideoPowerStandBy; break; 00616 case 2: VideoPowerControl->PowerState = VideoPowerSuspend; break; 00617 case 4: VideoPowerControl->PowerState = VideoPowerOff; break; 00618 case 5: VideoPowerControl->PowerState = VideoPowerOn; break; 00619 default: VideoPowerControl->PowerState = VideoPowerUnspecified; 00620 } 00621 00622 return NO_ERROR; 00623 } 00624 00625 return ERROR_DEV_NOT_EXIST; 00626 } 00627 00628 /* 00629 * VBESetPowerState 00630 * 00631 * Sets the power state of the specified device 00632 */ 00633 00634 VP_STATUS NTAPI 00635 VBESetPowerState( 00636 PVOID HwDeviceExtension, 00637 ULONG HwId, 00638 PVIDEO_POWER_MANAGEMENT VideoPowerControl) 00639 { 00640 INT10_BIOS_ARGUMENTS BiosRegisters; 00641 PVBE_DEVICE_EXTENSION VBEDeviceExtension = 00642 (PVBE_DEVICE_EXTENSION)HwDeviceExtension; 00643 00644 if (HwId != DISPLAY_ADAPTER_HW_ID || 00645 VideoPowerControl->Length < sizeof(VIDEO_POWER_MANAGEMENT) || 00646 VideoPowerControl->PowerState < VideoPowerOn || 00647 VideoPowerControl->PowerState > VideoPowerHibernate) 00648 return ERROR_INVALID_FUNCTION; 00649 00650 if (VideoPowerControl->PowerState == VideoPowerHibernate) 00651 return NO_ERROR; 00652 00653 /* 00654 * Set current power state. 00655 */ 00656 00657 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 00658 BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS; 00659 BiosRegisters.Ebx = 1; 00660 BiosRegisters.Edi = 0; 00661 BiosRegisters.SegEs = 0; 00662 switch (VideoPowerControl->PowerState) 00663 { 00664 case VideoPowerStandBy: BiosRegisters.Ebx |= 0x100; break; 00665 case VideoPowerSuspend: BiosRegisters.Ebx |= 0x200; break; 00666 case VideoPowerOff: BiosRegisters.Ebx |= 0x400; break; 00667 } 00668 00669 VBEDeviceExtension->Int10Interface.Int10CallBios( 00670 VBEDeviceExtension->Int10Interface.Context, 00671 &BiosRegisters); 00672 00673 if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_NOT_SUPPORTED) 00674 return ERROR_DEV_NOT_EXIST; 00675 if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS) 00676 return ERROR_INVALID_FUNCTION; 00677 00678 return VBE_SUCCESS; 00679 } 00680 00681 /* 00682 * VBESetCurrentMode 00683 * 00684 * Sets the adapter to the specified operating mode. 00685 */ 00686 00687 BOOLEAN FASTCALL 00688 VBESetCurrentMode( 00689 PVBE_DEVICE_EXTENSION DeviceExtension, 00690 PVIDEO_MODE RequestedMode, 00691 PSTATUS_BLOCK StatusBlock) 00692 { 00693 INT10_BIOS_ARGUMENTS BiosRegisters; 00694 00695 if (RequestedMode->RequestedMode >= DeviceExtension->ModeCount) 00696 { 00697 return ERROR_INVALID_PARAMETER; 00698 } 00699 00700 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 00701 BiosRegisters.Eax = VBE_SET_VBE_MODE; 00702 BiosRegisters.Ebx = DeviceExtension->ModeNumbers[RequestedMode->RequestedMode]; 00703 DeviceExtension->Int10Interface.Int10CallBios( 00704 DeviceExtension->Int10Interface.Context, 00705 &BiosRegisters); 00706 00707 if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS) 00708 { 00709 DeviceExtension->CurrentMode = RequestedMode->RequestedMode; 00710 } 00711 else 00712 { 00713 VideoPortDebugPrint(Error, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters.Eax); 00714 DeviceExtension->CurrentMode = -1; 00715 } 00716 00717 return VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS; 00718 } 00719 00720 /* 00721 * VBEResetDevice 00722 * 00723 * Resets the video hardware to the default mode, to which it was initialized 00724 * at system boot. 00725 */ 00726 00727 BOOLEAN FASTCALL 00728 VBEResetDevice( 00729 PVBE_DEVICE_EXTENSION DeviceExtension, 00730 PSTATUS_BLOCK StatusBlock) 00731 { 00732 INT10_BIOS_ARGUMENTS BiosRegisters; 00733 00734 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 00735 BiosRegisters.Eax = VBE_SET_VBE_MODE; 00736 BiosRegisters.Ebx = 0x3; 00737 DeviceExtension->Int10Interface.Int10CallBios( 00738 DeviceExtension->Int10Interface.Context, 00739 &BiosRegisters); 00740 00741 return VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS; 00742 } 00743 00744 /* 00745 * VBEMapVideoMemory 00746 * 00747 * Maps the video hardware frame buffer and video RAM into the virtual address 00748 * space of the requestor. 00749 */ 00750 00751 BOOLEAN FASTCALL 00752 VBEMapVideoMemory( 00753 PVBE_DEVICE_EXTENSION DeviceExtension, 00754 PVIDEO_MEMORY RequestedAddress, 00755 PVIDEO_MEMORY_INFORMATION MapInformation, 00756 PSTATUS_BLOCK StatusBlock) 00757 { 00758 PHYSICAL_ADDRESS FrameBuffer; 00759 ULONG inIoSpace = VIDEO_MEMORY_SPACE_MEMORY; 00760 00761 StatusBlock->Information = sizeof(VIDEO_MEMORY_INFORMATION); 00762 00763 if (DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].ModeAttributes & 00764 VBE_MODEATTR_LINEAR) 00765 { 00766 FrameBuffer.QuadPart = 00767 DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].PhysBasePtr; 00768 MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress; 00769 if (DeviceExtension->VbeInfo.Version < 0x300) 00770 { 00771 MapInformation->VideoRamLength = 00772 DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].BytesPerScanLine * 00773 DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution; 00774 } 00775 else 00776 { 00777 MapInformation->VideoRamLength = 00778 DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].LinBytesPerScanLine * 00779 DeviceExtension->ModeInfo[DeviceExtension->CurrentMode].YResolution; 00780 } 00781 } 00782 #ifdef VBE12_SUPPORT 00783 else 00784 { 00785 FrameBuffer.QuadPart = 0xA0000; 00786 MapInformation->VideoRamBase = RequestedAddress->RequestedVirtualAddress; 00787 MapInformation->VideoRamLength = 0x10000; 00788 } 00789 #endif 00790 00791 VideoPortMapMemory(DeviceExtension, FrameBuffer, 00792 &MapInformation->VideoRamLength, &inIoSpace, 00793 &MapInformation->VideoRamBase); 00794 00795 MapInformation->FrameBufferBase = MapInformation->VideoRamBase; 00796 MapInformation->FrameBufferLength = MapInformation->VideoRamLength; 00797 00798 return TRUE; 00799 } 00800 00801 /* 00802 * VBEUnmapVideoMemory 00803 * 00804 * Releases a mapping between the virtual address space and the adapter's 00805 * frame buffer and video RAM. 00806 */ 00807 00808 BOOLEAN FASTCALL 00809 VBEUnmapVideoMemory( 00810 PVBE_DEVICE_EXTENSION DeviceExtension, 00811 PVIDEO_MEMORY VideoMemory, 00812 PSTATUS_BLOCK StatusBlock) 00813 { 00814 VideoPortUnmapMemory(DeviceExtension, VideoMemory->RequestedVirtualAddress, 00815 NULL); 00816 return TRUE; 00817 } 00818 00819 /* 00820 * VBEQueryNumAvailModes 00821 * 00822 * Returns the number of video modes supported by the adapter and the size 00823 * in bytes of the video mode information, which can be used to allocate a 00824 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request. 00825 */ 00826 00827 BOOLEAN FASTCALL 00828 VBEQueryNumAvailModes( 00829 PVBE_DEVICE_EXTENSION DeviceExtension, 00830 PVIDEO_NUM_MODES Modes, 00831 PSTATUS_BLOCK StatusBlock) 00832 { 00833 Modes->NumModes = DeviceExtension->ModeCount; 00834 Modes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION); 00835 StatusBlock->Information = sizeof(VIDEO_NUM_MODES); 00836 return TRUE; 00837 } 00838 00839 /* 00840 * VBEQueryMode 00841 * 00842 * Returns information about one particular video mode. 00843 */ 00844 00845 VOID FASTCALL 00846 VBEQueryMode( 00847 PVBE_DEVICE_EXTENSION DeviceExtension, 00848 PVIDEO_MODE_INFORMATION VideoMode, 00849 ULONG VideoModeId) 00850 { 00851 PVBE_MODEINFO VBEMode = &DeviceExtension->ModeInfo[VideoModeId]; 00852 ULONG dpi; 00853 00854 VideoMode->Length = sizeof(VIDEO_MODE_INFORMATION); 00855 VideoMode->ModeIndex = VideoModeId; 00856 VideoMode->VisScreenWidth = VBEMode->XResolution; 00857 VideoMode->VisScreenHeight = VBEMode->YResolution; 00858 if (DeviceExtension->VbeInfo.Version < 0x300) 00859 VideoMode->ScreenStride = VBEMode->BytesPerScanLine; 00860 else 00861 VideoMode->ScreenStride = VBEMode->LinBytesPerScanLine; 00862 VideoMode->NumberOfPlanes = VBEMode->NumberOfPlanes; 00863 VideoMode->BitsPerPlane = VBEMode->BitsPerPixel / VBEMode->NumberOfPlanes; 00864 VideoMode->Frequency = 1; 00865 00866 /* Assume 96DPI and 25.4 millimeters per inch, round to nearest */ 00867 dpi = 96; 00868 VideoMode->XMillimeter = ((ULONGLONG)VBEMode->XResolution * 254 + (dpi * 5)) / (dpi * 10); 00869 VideoMode->YMillimeter = ((ULONGLONG)VBEMode->YResolution * 254 + (dpi * 5)) / (dpi * 10); 00870 00871 if (VBEMode->BitsPerPixel > 8) 00872 { 00873 /* 00874 * Always report 16bpp modes and not 15bpp mode... 00875 */ 00876 if (VBEMode->BitsPerPixel == 15 && VBEMode->NumberOfPlanes == 1) 00877 { 00878 VideoMode->BitsPerPlane = 16; 00879 } 00880 00881 if (DeviceExtension->VbeInfo.Version < 0x300) 00882 { 00883 VideoMode->NumberRedBits = VBEMode->RedMaskSize; 00884 VideoMode->NumberGreenBits = VBEMode->GreenMaskSize; 00885 VideoMode->NumberBlueBits = VBEMode->BlueMaskSize; 00886 VideoMode->RedMask = ((1 << VBEMode->RedMaskSize) - 1) << VBEMode->RedFieldPosition; 00887 VideoMode->GreenMask = ((1 << VBEMode->GreenMaskSize) - 1) << VBEMode->GreenFieldPosition; 00888 VideoMode->BlueMask = ((1 << VBEMode->BlueMaskSize) - 1) << VBEMode->BlueFieldPosition; 00889 } 00890 else 00891 { 00892 VideoMode->NumberRedBits = VBEMode->LinRedMaskSize; 00893 VideoMode->NumberGreenBits = VBEMode->LinGreenMaskSize; 00894 VideoMode->NumberBlueBits = VBEMode->LinBlueMaskSize; 00895 VideoMode->RedMask = ((1 << VBEMode->LinRedMaskSize) - 1) << VBEMode->LinRedFieldPosition; 00896 VideoMode->GreenMask = ((1 << VBEMode->LinGreenMaskSize) - 1) << VBEMode->LinGreenFieldPosition; 00897 VideoMode->BlueMask = ((1 << VBEMode->LinBlueMaskSize) - 1) << VBEMode->LinBlueFieldPosition; 00898 } 00899 } 00900 else 00901 { 00902 VideoMode->NumberRedBits = 00903 VideoMode->NumberGreenBits = 00904 VideoMode->NumberBlueBits = 6; 00905 VideoMode->RedMask = 00906 VideoMode->GreenMask = 00907 VideoMode->BlueMask = 0; 00908 } 00909 VideoMode->VideoMemoryBitmapWidth = VBEMode->XResolution; 00910 VideoMode->VideoMemoryBitmapHeight = VBEMode->YResolution; 00911 VideoMode->AttributeFlags = VIDEO_MODE_GRAPHICS | VIDEO_MODE_COLOR | 00912 VIDEO_MODE_NO_OFF_SCREEN; 00913 if (VideoMode->BitsPerPlane <= 8) 00914 VideoMode->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN; 00915 VideoMode->DriverSpecificAttributeFlags = 0; 00916 } 00917 00918 /* 00919 * VBEQueryAvailModes 00920 * 00921 * Returns information about each video mode supported by the adapter. 00922 */ 00923 00924 BOOLEAN FASTCALL 00925 VBEQueryAvailModes( 00926 PVBE_DEVICE_EXTENSION DeviceExtension, 00927 PVIDEO_MODE_INFORMATION ReturnedModes, 00928 PSTATUS_BLOCK StatusBlock) 00929 { 00930 ULONG CurrentModeId; 00931 PVIDEO_MODE_INFORMATION CurrentMode; 00932 PVBE_MODEINFO CurrentVBEMode; 00933 00934 for (CurrentModeId = 0, CurrentMode = ReturnedModes, 00935 CurrentVBEMode = DeviceExtension->ModeInfo; 00936 CurrentModeId < DeviceExtension->ModeCount; 00937 CurrentModeId++, CurrentMode++, CurrentVBEMode++) 00938 { 00939 VBEQueryMode(DeviceExtension, CurrentMode, CurrentModeId); 00940 } 00941 00942 StatusBlock->Information = 00943 sizeof(VIDEO_MODE_INFORMATION) * DeviceExtension->ModeCount; 00944 00945 return TRUE; 00946 } 00947 00948 /* 00949 * VBEQueryCurrentMode 00950 * 00951 * Returns information about current video mode. 00952 */ 00953 00954 BOOLEAN FASTCALL 00955 VBEQueryCurrentMode( 00956 PVBE_DEVICE_EXTENSION DeviceExtension, 00957 PVIDEO_MODE_INFORMATION VideoModeInfo, 00958 PSTATUS_BLOCK StatusBlock) 00959 { 00960 StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION); 00961 00962 VBEQueryMode( 00963 DeviceExtension, 00964 VideoModeInfo, 00965 DeviceExtension->CurrentMode); 00966 00967 return TRUE; 00968 } 00969 00970 /* 00971 * VBESetColorRegisters 00972 * 00973 * Sets the adapter's color registers to the specified RGB values. There 00974 * are code paths in this function, one generic and one for VGA compatible 00975 * controllers. The latter is needed for Bochs, where the generic one isn't 00976 * yet implemented. 00977 */ 00978 00979 BOOLEAN FASTCALL 00980 VBESetColorRegisters( 00981 PVBE_DEVICE_EXTENSION DeviceExtension, 00982 PVIDEO_CLUT ColorLookUpTable, 00983 PSTATUS_BLOCK StatusBlock) 00984 { 00985 INT10_BIOS_ARGUMENTS BiosRegisters; 00986 ULONG Entry; 00987 PULONG OutputEntry; 00988 ULONG OutputBuffer[256]; 00989 00990 if (ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry > 256) 00991 return FALSE; 00992 00993 /* 00994 * For VGA compatible adapters program the color registers directly. 00995 */ 00996 00997 if (!(DeviceExtension->VbeInfo.Capabilities & 2)) 00998 { 00999 for (Entry = ColorLookUpTable->FirstEntry; 01000 Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry; 01001 Entry++) 01002 { 01003 VideoPortWritePortUchar((PUCHAR)0x03c8, Entry); 01004 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Red); 01005 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Green); 01006 VideoPortWritePortUchar((PUCHAR)0x03c9, ColorLookUpTable->LookupTable[Entry].RgbArray.Blue); 01007 } 01008 01009 return TRUE; 01010 } 01011 else 01012 { 01013 /* 01014 * We can't just copy the values, because we need to swap the Red 01015 * and Blue values. 01016 */ 01017 01018 for (Entry = ColorLookUpTable->FirstEntry, 01019 OutputEntry = OutputBuffer; 01020 Entry < ColorLookUpTable->NumEntries + ColorLookUpTable->FirstEntry; 01021 Entry++, OutputEntry++) 01022 { 01023 *OutputEntry = 01024 (ColorLookUpTable->LookupTable[Entry].RgbArray.Red << 16) | 01025 (ColorLookUpTable->LookupTable[Entry].RgbArray.Green << 8) | 01026 (ColorLookUpTable->LookupTable[Entry].RgbArray.Blue); 01027 } 01028 01029 DeviceExtension->Int10Interface.Int10WriteMemory( 01030 DeviceExtension->Int10Interface.Context, 01031 DeviceExtension->TrampolineMemorySegment, 01032 DeviceExtension->TrampolineMemoryOffset, 01033 OutputBuffer, 01034 (OutputEntry - OutputBuffer) * sizeof(ULONG)); 01035 01036 VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); 01037 BiosRegisters.Eax = VBE_SET_GET_PALETTE_DATA; 01038 BiosRegisters.Ebx = 0; 01039 BiosRegisters.Ecx = ColorLookUpTable->NumEntries; 01040 BiosRegisters.Edx = ColorLookUpTable->FirstEntry; 01041 BiosRegisters.Edi = DeviceExtension->TrampolineMemoryOffset; 01042 BiosRegisters.SegEs = DeviceExtension->TrampolineMemorySegment; 01043 DeviceExtension->Int10Interface.Int10CallBios( 01044 DeviceExtension->Int10Interface.Context, 01045 &BiosRegisters); 01046 01047 return VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS; 01048 } 01049 } Generated on Sun May 27 2012 04:38:11 for ReactOS by
1.7.6.1
|