2 * ReactOS VBE miniport video driver
3 * Copyright (C) 2004 Filip Navara
5 * Power Management and VBE 1.2 support
6 * Copyright (C) 2004 Magnus Olsen
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 * - Check input parameters everywhere.
24 * - Call VideoPortVerifyAccessRanges to reserve the memory we're about
28 /* INCLUDES *******************************************************************/
34 #define LOWORD(l) ((USHORT)((ULONG_PTR)(l)))
35 #define HIWORD(l) ((USHORT)(((ULONG_PTR)(l)>>16)&0xFFFF))
37 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
40 DriverEntry(IN PVOID Context1
, IN PVOID Context2
)
42 VIDEO_HW_INITIALIZATION_DATA InitData
;
44 VideoPortZeroMemory(&InitData
, sizeof(InitData
));
45 InitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
46 InitData
.HwFindAdapter
= VBEFindAdapter
;
47 InitData
.HwInitialize
= VBEInitialize
;
48 InitData
.HwStartIO
= VBEStartIO
;
49 InitData
.HwResetHw
= VBEResetHw
;
50 //InitData.HwGetPowerState = VBEGetPowerState;
51 //InitData.HwSetPowerState = VBESetPowerState;
52 //InitData.HwGetVideoChildDescriptor = VBEGetVideoChildDescriptor;
53 InitData
.HwDeviceExtensionSize
= sizeof(VBE_DEVICE_EXTENSION
);
55 return VideoPortInitialize(Context1
, Context2
, &InitData
, NULL
);
61 * Should detect a VBE compatible display adapter, but it's not possible
62 * to use video port Int 10 services at this time during initialization,
63 * so we always return NO_ERROR and do the real work in VBEInitialize.
68 IN PVOID HwDeviceExtension
,
70 IN PWSTR ArgumentString
,
71 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
78 * VBESortModesCallback
80 * Helper function for sorting video mode list.
84 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA
, PVBE_MODEINFO VbeModeInfoB
)
86 VideoPortDebugPrint(Info
, "VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
87 VbeModeInfoA
->XResolution
, VbeModeInfoA
->YResolution
,
88 VbeModeInfoA
->BitsPerPixel
,
89 VbeModeInfoB
->XResolution
, VbeModeInfoB
->YResolution
,
90 VbeModeInfoB
->BitsPerPixel
);
93 * FIXME: Until some reasonable method for changing video modes will
94 * be available we favor more bits per pixel. It should be changed
97 if (VbeModeInfoA
->BitsPerPixel
< VbeModeInfoB
->BitsPerPixel
) return -1;
98 if (VbeModeInfoA
->BitsPerPixel
> VbeModeInfoB
->BitsPerPixel
) return 1;
99 if (VbeModeInfoA
->XResolution
< VbeModeInfoB
->XResolution
) return -1;
100 if (VbeModeInfoA
->XResolution
> VbeModeInfoB
->XResolution
) return 1;
101 if (VbeModeInfoA
->YResolution
< VbeModeInfoB
->YResolution
) return -1;
102 if (VbeModeInfoA
->YResolution
> VbeModeInfoB
->YResolution
) return 1;
109 * Simple function for sorting the video mode list. Uses bubble sort.
113 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension
)
115 BOOLEAN Finished
= FALSE
;
118 VBE_MODEINFO TempModeInfo
;
119 USHORT TempModeNumber
;
124 for (Pos
= 0; Pos
< DeviceExtension
->ModeCount
- 1; Pos
++)
126 Result
= VBESortModesCallback(
127 DeviceExtension
->ModeInfo
+ Pos
,
128 DeviceExtension
->ModeInfo
+ Pos
+ 1);
135 DeviceExtension
->ModeInfo
+ Pos
,
136 sizeof(VBE_MODEINFO
));
137 TempModeNumber
= DeviceExtension
->ModeNumbers
[Pos
];
140 DeviceExtension
->ModeInfo
+ Pos
,
141 DeviceExtension
->ModeInfo
+ Pos
+ 1,
142 sizeof(VBE_MODEINFO
));
143 DeviceExtension
->ModeNumbers
[Pos
] =
144 DeviceExtension
->ModeNumbers
[Pos
+ 1];
147 DeviceExtension
->ModeInfo
+ Pos
+ 1,
149 sizeof(VBE_MODEINFO
));
150 DeviceExtension
->ModeNumbers
[Pos
+ 1] = TempModeNumber
;
159 * Performs the first initialization of the adapter, after the HAL has given
160 * up control of the video hardware to the video port driver.
162 * This function performs these steps:
163 * - Gets global VBE information and finds if VBE BIOS is present.
164 * - Builds the internal mode list using the list of modes provided by
169 VBEInitialize(PVOID HwDeviceExtension
)
171 INT10_BIOS_ARGUMENTS BiosRegisters
;
173 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
174 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
177 ULONG SuitableModeCount
;
180 PVBE_MODEINFO VbeModeInfo
;
183 * Get the Int 10 interface that we will use for allocating real
184 * mode memory and calling the video BIOS.
187 VBEDeviceExtension
->Int10Interface
.Version
= VIDEO_PORT_INT10_INTERFACE_VERSION_1
;
188 VBEDeviceExtension
->Int10Interface
.Size
= sizeof(VIDEO_PORT_INT10_INTERFACE
);
189 Status
= VideoPortQueryServices(
191 VideoPortServicesInt10
,
192 (PINTERFACE
)&VBEDeviceExtension
->Int10Interface
);
194 if (Status
!= NO_ERROR
)
196 VideoPortDebugPrint(Error
, "Failed to get Int 10 service functions (Status %x)\n", Status
);
201 * Allocate a bit of memory that will be later used for VBE transport
202 * buffer. This memory must be accessible from V86 mode so it must fit
203 * in the first megabyte of physical memory.
207 Status
= VBEDeviceExtension
->Int10Interface
.Int10AllocateBuffer(
208 VBEDeviceExtension
->Int10Interface
.Context
,
209 &VBEDeviceExtension
->TrampolineMemorySegment
,
210 &VBEDeviceExtension
->TrampolineMemoryOffset
,
213 if (Status
!= NO_ERROR
)
215 VideoPortDebugPrint(Error
, "Failed to allocate virtual memory (Status %x)\n", Status
);
220 * Get the VBE general information.
223 VBEDeviceExtension
->Int10Interface
.Int10WriteMemory(
224 VBEDeviceExtension
->Int10Interface
.Context
,
225 VBEDeviceExtension
->TrampolineMemorySegment
,
226 VBEDeviceExtension
->TrampolineMemoryOffset
,
230 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
231 BiosRegisters
.Eax
= VBE_GET_CONTROLLER_INFORMATION
;
232 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
;
233 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
234 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
235 VBEDeviceExtension
->Int10Interface
.Context
,
238 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
240 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
241 VBEDeviceExtension
->Int10Interface
.Context
,
242 VBEDeviceExtension
->TrampolineMemorySegment
,
243 VBEDeviceExtension
->TrampolineMemoryOffset
,
244 &VBEDeviceExtension
->VbeInfo
,
245 sizeof(VBEDeviceExtension
->VbeInfo
));
247 /* Verify the VBE signature. */
248 if (VideoPortCompareMemory(VBEDeviceExtension
->VbeInfo
.Signature
, "VESA", 4) != 4)
250 VideoPortDebugPrint(Warn
, "No VBE BIOS present\n");
254 VideoPortDebugPrint(Trace
, "VBE BIOS Present (%d.%d, %8ld Kb)\n",
255 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
256 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF,
257 VBEDeviceExtension
->VbeInfo
.TotalMemory
* 64);
260 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x102)
262 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x200)
265 VideoPortDebugPrint(Warn
, "VBE BIOS present, but incompatible version.\n");
271 VideoPortDebugPrint(Warn
, "No VBE BIOS found.\n");
276 * Build a mode list here that can be later used by
277 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
282 * Get the number of supported video modes.
284 * No need to be map the memory. It's either in the video BIOS memory or
285 * in our trampoline memory. In either case the memory is already mapped.
288 for (ModeCount
= 0; ; ModeCount
++)
290 /* Read the VBE mode number. */
291 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
292 VBEDeviceExtension
->Int10Interface
.Context
,
293 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
294 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
299 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
304 * Allocate space for video modes information.
307 VBEDeviceExtension
->ModeInfo
=
308 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(VBE_MODEINFO
), TAG_VBE
);
309 VBEDeviceExtension
->ModeNumbers
=
310 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(USHORT
), TAG_VBE
);
313 * Get the actual mode infos.
316 for (CurrentMode
= 0, SuitableModeCount
= 0;
317 CurrentMode
< ModeCount
;
320 /* Read the VBE mode number. */
321 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
322 VBEDeviceExtension
->Int10Interface
.Context
,
323 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
324 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
328 /* Call VBE BIOS to read the mode info. */
329 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
330 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
331 BiosRegisters
.Ecx
= ModeTemp
;
332 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
333 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
334 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
335 VBEDeviceExtension
->Int10Interface
.Context
,
338 /* Read the VBE mode info. */
339 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
340 VBEDeviceExtension
->Int10Interface
.Context
,
341 VBEDeviceExtension
->TrampolineMemorySegment
,
342 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
343 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
344 sizeof(VBE_MODEINFO
));
346 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
348 /* Is this mode acceptable? */
349 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
&&
350 VbeModeInfo
->XResolution
>= 640 &&
351 VbeModeInfo
->YResolution
>= 480 &&
352 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
353 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
) &&
354 VbeModeInfo
->PhysBasePtr
!= 0)
356 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
358 /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */
359 // if (ModeTemp & 0x4000)
361 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
368 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
376 if (SuitableModeCount
== 0)
379 VideoPortDebugPrint(Warn
, "VBEMP: No video modes supported\n");
383 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
386 * Sort the video mode list according to resolution and bits per pixel.
389 VBESortModes(VBEDeviceExtension
);
392 * Print the supported video modes.
395 for (CurrentMode
= 0;
396 CurrentMode
< SuitableModeCount
;
399 VideoPortDebugPrint(Trace
, "%dx%dx%d\n",
400 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
401 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
402 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
406 * Enumerate our children.
408 VideoPortEnumerateChildren(HwDeviceExtension
, NULL
);
416 * Processes the specified Video Request Packet.
421 PVOID HwDeviceExtension
,
422 PVIDEO_REQUEST_PACKET RequestPacket
)
426 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
428 switch (RequestPacket
->IoControlCode
)
430 case IOCTL_VIDEO_SET_CURRENT_MODE
:
431 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
433 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
436 Result
= VBESetCurrentMode(
437 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
438 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
439 RequestPacket
->StatusBlock
);
442 case IOCTL_VIDEO_RESET_DEVICE
:
443 Result
= VBEResetDevice(
444 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
445 RequestPacket
->StatusBlock
);
448 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
449 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
450 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
452 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
455 Result
= VBEMapVideoMemory(
456 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
457 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
458 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
459 RequestPacket
->StatusBlock
);
462 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
463 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
465 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
468 Result
= VBEUnmapVideoMemory(
469 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
470 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
471 RequestPacket
->StatusBlock
);
474 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
475 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
477 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
480 Result
= VBEQueryNumAvailModes(
481 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
482 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
483 RequestPacket
->StatusBlock
);
486 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
487 if (RequestPacket
->OutputBufferLength
<
488 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
490 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
493 Result
= VBEQueryAvailModes(
494 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
495 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
496 RequestPacket
->StatusBlock
);
499 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
500 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
501 RequestPacket
->InputBufferLength
<
502 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
503 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
505 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
508 Result
= VBESetColorRegisters(
509 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
510 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
511 RequestPacket
->StatusBlock
);
514 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
515 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
517 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
520 Result
= VBEQueryCurrentMode(
521 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
522 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
523 RequestPacket
->StatusBlock
);
527 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
532 RequestPacket
->StatusBlock
->Status
= NO_ERROR
;
540 * This function is called to reset the hardware to a known state.
545 PVOID DeviceExtension
,
549 /* Return FALSE to let HAL reset the display with INT10 */
556 * Queries whether the device can support the requested power state.
561 PVOID HwDeviceExtension
,
563 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
565 INT10_BIOS_ARGUMENTS BiosRegisters
;
566 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
567 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
569 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
570 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
571 return ERROR_INVALID_FUNCTION
;
574 * Get general power support information.
577 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
578 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
579 BiosRegisters
.Ebx
= 0;
580 BiosRegisters
.Edi
= 0;
581 BiosRegisters
.SegEs
= 0;
582 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
583 VBEDeviceExtension
->Int10Interface
.Context
,
586 if ( VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
587 return ERROR_DEV_NOT_EXIST
;
588 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
589 return ERROR_INVALID_FUNCTION
;
592 * Get current power state.
595 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
596 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
597 BiosRegisters
.Ebx
= 0x2;
598 BiosRegisters
.Edi
= 0;
599 BiosRegisters
.SegEs
= 0;
600 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
601 VBEDeviceExtension
->Int10Interface
.Context
,
604 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
606 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
607 switch (BiosRegisters
.Ebx
>> 8)
609 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
610 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
611 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
612 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
613 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
614 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
620 return ERROR_DEV_NOT_EXIST
;
626 * Sets the power state of the specified device
631 PVOID HwDeviceExtension
,
633 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
635 INT10_BIOS_ARGUMENTS BiosRegisters
;
636 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
637 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
639 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
640 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
641 VideoPowerControl
->PowerState
< VideoPowerOn
||
642 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
643 return ERROR_INVALID_FUNCTION
;
645 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
649 * Set current power state.
652 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
653 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
654 BiosRegisters
.Ebx
= 1;
655 BiosRegisters
.Edi
= 0;
656 BiosRegisters
.SegEs
= 0;
657 switch (VideoPowerControl
->PowerState
)
659 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
660 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
661 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
664 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
665 VBEDeviceExtension
->Int10Interface
.Context
,
668 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
669 return ERROR_DEV_NOT_EXIST
;
670 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
671 return ERROR_INVALID_FUNCTION
;
679 * Sets the adapter to the specified operating mode.
684 PVBE_DEVICE_EXTENSION DeviceExtension
,
685 PVIDEO_MODE RequestedMode
,
686 PSTATUS_BLOCK StatusBlock
)
688 INT10_BIOS_ARGUMENTS BiosRegisters
;
690 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
692 return ERROR_INVALID_PARAMETER
;
695 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
696 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
697 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
698 DeviceExtension
->Int10Interface
.Int10CallBios(
699 DeviceExtension
->Int10Interface
.Context
,
702 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
704 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
708 VideoPortDebugPrint(Error
, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
709 DeviceExtension
->CurrentMode
= -1;
712 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
718 * Resets the video hardware to the default mode, to which it was initialized
724 PVBE_DEVICE_EXTENSION DeviceExtension
,
725 PSTATUS_BLOCK StatusBlock
)
727 INT10_BIOS_ARGUMENTS BiosRegisters
;
729 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
730 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
731 BiosRegisters
.Ebx
= 0x3;
732 DeviceExtension
->Int10Interface
.Int10CallBios(
733 DeviceExtension
->Int10Interface
.Context
,
736 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
742 * Maps the video hardware frame buffer and video RAM into the virtual address
743 * space of the requestor.
748 PVBE_DEVICE_EXTENSION DeviceExtension
,
749 PVIDEO_MEMORY RequestedAddress
,
750 PVIDEO_MEMORY_INFORMATION MapInformation
,
751 PSTATUS_BLOCK StatusBlock
)
753 PHYSICAL_ADDRESS FrameBuffer
;
754 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
756 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
758 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
761 FrameBuffer
.QuadPart
=
762 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
763 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
764 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
766 MapInformation
->VideoRamLength
=
767 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
768 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
772 MapInformation
->VideoRamLength
=
773 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
774 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
780 FrameBuffer
.QuadPart
= 0xA0000;
781 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
782 MapInformation
->VideoRamLength
= 0x10000;
786 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
787 &MapInformation
->VideoRamLength
, &inIoSpace
,
788 &MapInformation
->VideoRamBase
);
790 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
791 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
797 * VBEUnmapVideoMemory
799 * Releases a mapping between the virtual address space and the adapter's
800 * frame buffer and video RAM.
805 PVBE_DEVICE_EXTENSION DeviceExtension
,
806 PVIDEO_MEMORY VideoMemory
,
807 PSTATUS_BLOCK StatusBlock
)
809 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
815 * VBEQueryNumAvailModes
817 * Returns the number of video modes supported by the adapter and the size
818 * in bytes of the video mode information, which can be used to allocate a
819 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
823 VBEQueryNumAvailModes(
824 PVBE_DEVICE_EXTENSION DeviceExtension
,
825 PVIDEO_NUM_MODES Modes
,
826 PSTATUS_BLOCK StatusBlock
)
828 Modes
->NumModes
= DeviceExtension
->ModeCount
;
829 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
830 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
837 * Returns information about one particular video mode.
842 PVBE_DEVICE_EXTENSION DeviceExtension
,
843 PVIDEO_MODE_INFORMATION VideoMode
,
846 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
848 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
849 VideoMode
->ModeIndex
= VideoModeId
;
850 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
851 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
852 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
853 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
855 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
856 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
857 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
858 VideoMode
->Frequency
= 1;
860 /* Assume 96DPI and 25.4 millimeters per inch */
861 VideoMode
->XMillimeter
= VBEMode
->XResolution
* 254 / 960;
862 VideoMode
->YMillimeter
= VBEMode
->YResolution
* 254 / 960;
864 if (VBEMode
->BitsPerPixel
> 8)
867 * Always report 16bpp modes and not 15bpp mode...
869 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
871 VideoMode
->BitsPerPlane
= 16;
874 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
876 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
877 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
878 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
879 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
880 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
881 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
885 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
886 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
887 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
888 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
889 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
890 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
895 VideoMode
->NumberRedBits
=
896 VideoMode
->NumberGreenBits
=
897 VideoMode
->NumberBlueBits
= 6;
899 VideoMode
->GreenMask
=
900 VideoMode
->BlueMask
= 0;
902 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
903 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
904 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
905 VIDEO_MODE_NO_OFF_SCREEN
;
906 if (VideoMode
->BitsPerPlane
<= 8)
907 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
908 VideoMode
->DriverSpecificAttributeFlags
= 0;
914 * Returns information about each video mode supported by the adapter.
919 PVBE_DEVICE_EXTENSION DeviceExtension
,
920 PVIDEO_MODE_INFORMATION ReturnedModes
,
921 PSTATUS_BLOCK StatusBlock
)
924 PVIDEO_MODE_INFORMATION CurrentMode
;
925 PVBE_MODEINFO CurrentVBEMode
;
927 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
928 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
929 CurrentModeId
< DeviceExtension
->ModeCount
;
930 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
932 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
935 StatusBlock
->Information
=
936 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
942 * VBEQueryCurrentMode
944 * Returns information about current video mode.
949 PVBE_DEVICE_EXTENSION DeviceExtension
,
950 PVIDEO_MODE_INFORMATION VideoModeInfo
,
951 PSTATUS_BLOCK StatusBlock
)
953 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
958 DeviceExtension
->CurrentMode
);
964 * VBESetColorRegisters
966 * Sets the adapter's color registers to the specified RGB values. There
967 * are code paths in this function, one generic and one for VGA compatible
968 * controllers. The latter is needed for Bochs, where the generic one isn't
973 VBESetColorRegisters(
974 PVBE_DEVICE_EXTENSION DeviceExtension
,
975 PVIDEO_CLUT ColorLookUpTable
,
976 PSTATUS_BLOCK StatusBlock
)
978 INT10_BIOS_ARGUMENTS BiosRegisters
;
981 ULONG OutputBuffer
[256];
983 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
987 * For VGA compatible adapters program the color registers directly.
990 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
992 for (Entry
= ColorLookUpTable
->FirstEntry
;
993 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
996 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
997 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
998 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
999 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1007 * We can't just copy the values, because we need to swap the Red
1011 for (Entry
= ColorLookUpTable
->FirstEntry
,
1012 OutputEntry
= OutputBuffer
;
1013 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1014 Entry
++, OutputEntry
++)
1017 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1018 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1019 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1022 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1023 DeviceExtension
->Int10Interface
.Context
,
1024 DeviceExtension
->TrampolineMemorySegment
,
1025 DeviceExtension
->TrampolineMemoryOffset
,
1027 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1029 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1030 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1031 BiosRegisters
.Ebx
= 0;
1032 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1033 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1034 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1035 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1036 DeviceExtension
->Int10Interface
.Int10CallBios(
1037 DeviceExtension
->Int10Interface
.Context
,
1040 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;