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
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * - Check input parameters everywhere.
24 * - Call VideoPortVerifyAccessRanges to reserve the memory we're about
28 /* INCLUDES *******************************************************************/
32 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
35 DriverEntry(IN PVOID Context1
, IN PVOID Context2
)
37 VIDEO_HW_INITIALIZATION_DATA InitData
;
39 VideoPortZeroMemory(&InitData
, sizeof(InitData
));
40 InitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
41 InitData
.HwFindAdapter
= VBEFindAdapter
;
42 InitData
.HwInitialize
= VBEInitialize
;
43 InitData
.HwStartIO
= VBEStartIO
;
44 InitData
.HwResetHw
= VBEResetHw
;
45 InitData
.HwGetPowerState
= VBEGetPowerState
;
46 InitData
.HwSetPowerState
= VBESetPowerState
;
47 InitData
.HwDeviceExtensionSize
= sizeof(VBE_DEVICE_EXTENSION
);
49 return VideoPortInitialize(Context1
, Context2
, &InitData
, NULL
);
55 * Should detect a VBE compatible display adapter, but it's not possible
56 * to use video port Int 10 services at this time during initialization,
57 * so we always return NO_ERROR and do the real work in VBEInitialize.
62 IN PVOID HwDeviceExtension
,
64 IN PWSTR ArgumentString
,
65 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
72 * VBESortModesCallback
74 * Helper function for sorting video mode list.
78 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA
, PVBE_MODEINFO VbeModeInfoB
)
80 VideoPortDebugPrint(Info
, "VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
81 VbeModeInfoA
->XResolution
, VbeModeInfoA
->YResolution
,
82 VbeModeInfoA
->BitsPerPixel
,
83 VbeModeInfoB
->XResolution
, VbeModeInfoB
->YResolution
,
84 VbeModeInfoB
->BitsPerPixel
);
87 * FIXME: Until some reasonable method for changing video modes will
88 * be available we favor more bits per pixel. It should be changed
91 if (VbeModeInfoA
->BitsPerPixel
< VbeModeInfoB
->BitsPerPixel
) return -1;
92 if (VbeModeInfoA
->BitsPerPixel
> VbeModeInfoB
->BitsPerPixel
) return 1;
93 if (VbeModeInfoA
->XResolution
< VbeModeInfoB
->XResolution
) return -1;
94 if (VbeModeInfoA
->XResolution
> VbeModeInfoB
->XResolution
) return 1;
95 if (VbeModeInfoA
->YResolution
< VbeModeInfoB
->YResolution
) return -1;
96 if (VbeModeInfoA
->YResolution
> VbeModeInfoB
->YResolution
) return 1;
103 * Simple function for sorting the video mode list. Uses bubble sort.
107 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension
)
109 BOOLEAN Finished
= FALSE
;
112 VBE_MODEINFO TempModeInfo
;
113 USHORT TempModeNumber
;
118 for (Pos
= 0; Pos
< DeviceExtension
->ModeCount
- 1; Pos
++)
120 Result
= VBESortModesCallback(
121 DeviceExtension
->ModeInfo
+ Pos
,
122 DeviceExtension
->ModeInfo
+ Pos
+ 1);
129 DeviceExtension
->ModeInfo
+ Pos
,
130 sizeof(VBE_MODEINFO
));
131 TempModeNumber
= DeviceExtension
->ModeNumbers
[Pos
];
134 DeviceExtension
->ModeInfo
+ Pos
,
135 DeviceExtension
->ModeInfo
+ Pos
+ 1,
136 sizeof(VBE_MODEINFO
));
137 DeviceExtension
->ModeNumbers
[Pos
] =
138 DeviceExtension
->ModeNumbers
[Pos
+ 1];
141 DeviceExtension
->ModeInfo
+ Pos
+ 1,
143 sizeof(VBE_MODEINFO
));
144 DeviceExtension
->ModeNumbers
[Pos
+ 1] = TempModeNumber
;
153 * Performs the first initialization of the adapter, after the HAL has given
154 * up control of the video hardware to the video port driver.
156 * This function performs these steps:
157 * - Gets global VBE information and finds if VBE BIOS is present.
158 * - Builds the internal mode list using the list of modes provided by
163 VBEInitialize(PVOID HwDeviceExtension
)
165 INT10_BIOS_ARGUMENTS BiosRegisters
;
167 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
168 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
171 ULONG SuitableModeCount
;
174 PVBE_MODEINFO VbeModeInfo
;
177 * Get the Int 10 interface that we will use for allocating real
178 * mode memory and calling the video BIOS.
181 VBEDeviceExtension
->Int10Interface
.Version
= VIDEO_PORT_INT10_INTERFACE_VERSION_1
;
182 VBEDeviceExtension
->Int10Interface
.Size
= sizeof(VIDEO_PORT_INT10_INTERFACE
);
183 Status
= VideoPortQueryServices(
185 VideoPortServicesInt10
,
186 (PINTERFACE
)&VBEDeviceExtension
->Int10Interface
);
188 if (Status
!= NO_ERROR
)
190 VideoPortDebugPrint(Error
, "Failed to get Int 10 service functions (Status %x)\n", Status
);
195 * Allocate a bit of memory that will be later used for VBE transport
196 * buffer. This memory must be accessible from V86 mode so it must fit
197 * in the first megabyte of physical memory.
201 Status
= VBEDeviceExtension
->Int10Interface
.Int10AllocateBuffer(
202 VBEDeviceExtension
->Int10Interface
.Context
,
203 &VBEDeviceExtension
->TrampolineMemorySegment
,
204 &VBEDeviceExtension
->TrampolineMemoryOffset
,
207 if (Status
!= NO_ERROR
)
209 VideoPortDebugPrint(Error
, "Failed to allocate virtual memory (Status %x)\n", Status
);
214 * Get the VBE general information.
217 VBEDeviceExtension
->Int10Interface
.Int10WriteMemory(
218 VBEDeviceExtension
->Int10Interface
.Context
,
219 VBEDeviceExtension
->TrampolineMemorySegment
,
220 VBEDeviceExtension
->TrampolineMemoryOffset
,
224 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
225 BiosRegisters
.Eax
= VBE_GET_CONTROLLER_INFORMATION
;
226 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
;
227 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
228 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
229 VBEDeviceExtension
->Int10Interface
.Context
,
232 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
234 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
235 VBEDeviceExtension
->Int10Interface
.Context
,
236 VBEDeviceExtension
->TrampolineMemorySegment
,
237 VBEDeviceExtension
->TrampolineMemoryOffset
,
238 &VBEDeviceExtension
->VbeInfo
,
239 sizeof(VBEDeviceExtension
->VbeInfo
));
241 /* Verify the VBE signature. */
242 if (VideoPortCompareMemory(VBEDeviceExtension
->VbeInfo
.Signature
, "VESA", 4) != 4)
244 VideoPortDebugPrint(Warn
, "No VBE BIOS present\n");
248 VideoPortDebugPrint(Trace
, "VBE BIOS Present (%d.%d, %8ld Kb)\n",
249 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
250 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF,
251 VBEDeviceExtension
->VbeInfo
.TotalMemory
* 64);
254 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x102)
256 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x200)
259 VideoPortDebugPrint(Warn
, "VBE BIOS present, but incompatible version.\n");
265 VideoPortDebugPrint(Warn
, "No VBE BIOS found.\n");
270 * Build a mode list here that can be later used by
271 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
276 * Get the number of supported video modes.
278 * No need to be map the memory. It's either in the video BIOS memory or
279 * in our trampoline memory. In either case the memory is already mapped.
282 for (ModeCount
= 0; ; ModeCount
++)
284 /* Read the VBE mode number. */
285 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
286 VBEDeviceExtension
->Int10Interface
.Context
,
287 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
288 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
293 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
298 * Allocate space for video modes information.
301 VBEDeviceExtension
->ModeInfo
=
302 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(VBE_MODEINFO
), TAG_VBE
);
303 VBEDeviceExtension
->ModeNumbers
=
304 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(USHORT
), TAG_VBE
);
307 * Get the actual mode infos.
310 for (CurrentMode
= 0, SuitableModeCount
= 0;
311 CurrentMode
< ModeCount
;
314 /* Read the VBE mode number. */
315 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
316 VBEDeviceExtension
->Int10Interface
.Context
,
317 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
318 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
322 /* Call VBE BIOS to read the mode info. */
323 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
324 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
325 BiosRegisters
.Ecx
= ModeTemp
;
326 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
327 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
328 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
329 VBEDeviceExtension
->Int10Interface
.Context
,
332 /* Read the VBE mode info. */
333 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
334 VBEDeviceExtension
->Int10Interface
.Context
,
335 VBEDeviceExtension
->TrampolineMemorySegment
,
336 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
337 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
338 sizeof(VBE_MODEINFO
));
340 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
342 /* Is this mode acceptable? */
343 if (BiosRegisters
.Eax
== VBE_SUCCESS
&&
344 VbeModeInfo
->XResolution
>= 640 &&
345 VbeModeInfo
->YResolution
>= 480 &&
346 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
347 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
) &&
348 VbeModeInfo
->PhysBasePtr
!= 0)
350 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
352 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
358 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
365 if (SuitableModeCount
== 0)
367 VideoPortDebugPrint(Warn
, "VBEMP: No video modes supported\n");
371 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
374 * Sort the video mode list according to resolution and bits per pixel.
377 VBESortModes(VBEDeviceExtension
);
380 * Print the supported video modes when NDEBUG is not set.
383 for (CurrentMode
= 0;
384 CurrentMode
< SuitableModeCount
;
387 VideoPortDebugPrint(Trace
, "%dx%dx%d\n",
388 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
389 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
390 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
399 * Processes the specified Video Request Packet.
404 PVOID HwDeviceExtension
,
405 PVIDEO_REQUEST_PACKET RequestPacket
)
409 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
411 switch (RequestPacket
->IoControlCode
)
413 case IOCTL_VIDEO_SET_CURRENT_MODE
:
414 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
416 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
419 Result
= VBESetCurrentMode(
420 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
421 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
422 RequestPacket
->StatusBlock
);
425 case IOCTL_VIDEO_RESET_DEVICE
:
426 Result
= VBEResetDevice(
427 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
428 RequestPacket
->StatusBlock
);
431 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
432 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
433 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
435 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
438 Result
= VBEMapVideoMemory(
439 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
440 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
441 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
442 RequestPacket
->StatusBlock
);
445 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
446 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
448 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
451 Result
= VBEUnmapVideoMemory(
452 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
453 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
454 RequestPacket
->StatusBlock
);
457 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
458 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
460 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
463 Result
= VBEQueryNumAvailModes(
464 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
465 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
466 RequestPacket
->StatusBlock
);
469 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
470 if (RequestPacket
->OutputBufferLength
<
471 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
473 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
476 Result
= VBEQueryAvailModes(
477 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
478 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
479 RequestPacket
->StatusBlock
);
482 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
483 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
484 RequestPacket
->InputBufferLength
<
485 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
486 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
488 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
491 Result
= VBESetColorRegisters(
492 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
493 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
494 RequestPacket
->StatusBlock
);
497 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
498 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
500 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
503 Result
= VBEQueryCurrentMode(
504 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
505 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
506 RequestPacket
->StatusBlock
);
510 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
515 RequestPacket
->StatusBlock
->Status
= NO_ERROR
;
523 * This function is called to reset the hardware to a known state.
528 PVOID DeviceExtension
,
532 INT10_BIOS_ARGUMENTS BiosRegisters
;
533 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
534 (PVBE_DEVICE_EXTENSION
)DeviceExtension
;
536 if (!VBEResetDevice(DeviceExtension
, NULL
))
539 /* Change number of columns/rows */
540 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
542 if (Columns
== 80 && Rows
== 25)
544 /* Default text size, don't change anything. */
547 else if (Columns
== 80 && Rows
== 28)
549 /* Use 9x14 font (80x28) */
550 BiosRegisters
.Eax
= 0x1111;
552 else if (Columns
== 80 && Rows
== 43)
554 /* Use 8x8 font in 350 scans mode (80x43) */
555 BiosRegisters
.Eax
= 0x1201;
556 BiosRegisters
.Ebx
= 0x30;
557 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
558 VBEDeviceExtension
->Int10Interface
.Context
,
561 BiosRegisters
.Eax
= 0x3;
562 BiosRegisters
.Ebx
= 0;
563 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
564 VBEDeviceExtension
->Int10Interface
.Context
,
567 BiosRegisters
.Eax
= 0x1112;
569 else if (Columns
== 80 && Rows
== 50)
571 /* Use 8x8 font (80x50) */
572 BiosRegisters
.Eax
= 0x1112;
577 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
578 VBEDeviceExtension
->Int10Interface
.Context
,
587 * Queries whether the device can support the requested power state.
592 PVOID HwDeviceExtension
,
594 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
596 INT10_BIOS_ARGUMENTS BiosRegisters
;
597 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
598 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
600 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
601 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
602 return ERROR_INVALID_FUNCTION
;
605 * Get general power support information.
608 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
609 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
610 BiosRegisters
.Ebx
= 0;
611 BiosRegisters
.Edi
= 0;
612 BiosRegisters
.SegEs
= 0;
613 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
614 VBEDeviceExtension
->Int10Interface
.Context
,
617 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
618 return ERROR_DEV_NOT_EXIST
;
619 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
620 return ERROR_INVALID_FUNCTION
;
623 * Get current power state.
626 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
627 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
628 BiosRegisters
.Ebx
= 0x2;
629 BiosRegisters
.Edi
= 0;
630 BiosRegisters
.SegEs
= 0;
631 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
632 VBEDeviceExtension
->Int10Interface
.Context
,
635 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
637 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
638 switch (BiosRegisters
.Ebx
>> 8)
640 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
641 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
642 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
643 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
644 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
645 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
651 return ERROR_DEV_NOT_EXIST
;
657 * Sets the power state of the specified device
662 PVOID HwDeviceExtension
,
664 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
666 INT10_BIOS_ARGUMENTS BiosRegisters
;
667 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
668 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
670 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
671 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
672 VideoPowerControl
->PowerState
< VideoPowerOn
||
673 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
674 return ERROR_INVALID_FUNCTION
;
676 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
680 * Set current power state.
683 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
684 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
685 BiosRegisters
.Ebx
= 1;
686 BiosRegisters
.Edi
= 0;
687 BiosRegisters
.SegEs
= 0;
688 switch (VideoPowerControl
->PowerState
)
690 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
691 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
692 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
695 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
696 VBEDeviceExtension
->Int10Interface
.Context
,
699 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
700 return ERROR_DEV_NOT_EXIST
;
701 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
702 return ERROR_INVALID_FUNCTION
;
710 * Sets the adapter to the specified operating mode.
715 PVBE_DEVICE_EXTENSION DeviceExtension
,
716 PVIDEO_MODE RequestedMode
,
717 PSTATUS_BLOCK StatusBlock
)
719 INT10_BIOS_ARGUMENTS BiosRegisters
;
721 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
723 return ERROR_INVALID_PARAMETER
;
726 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
727 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
728 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
729 DeviceExtension
->Int10Interface
.Int10CallBios(
730 DeviceExtension
->Int10Interface
.Context
,
733 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
735 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
739 VideoPortDebugPrint(Error
, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
740 DeviceExtension
->CurrentMode
= -1;
743 return BiosRegisters
.Eax
== VBE_SUCCESS
;
749 * Resets the video hardware to the default mode, to which it was initialized
755 PVBE_DEVICE_EXTENSION DeviceExtension
,
756 PSTATUS_BLOCK StatusBlock
)
758 INT10_BIOS_ARGUMENTS BiosRegisters
;
760 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
761 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
762 BiosRegisters
.Ebx
= 0x3;
763 DeviceExtension
->Int10Interface
.Int10CallBios(
764 DeviceExtension
->Int10Interface
.Context
,
767 return BiosRegisters
.Eax
== VBE_SUCCESS
;
773 * Maps the video hardware frame buffer and video RAM into the virtual address
774 * space of the requestor.
779 PVBE_DEVICE_EXTENSION DeviceExtension
,
780 PVIDEO_MEMORY RequestedAddress
,
781 PVIDEO_MEMORY_INFORMATION MapInformation
,
782 PSTATUS_BLOCK StatusBlock
)
784 PHYSICAL_ADDRESS FrameBuffer
;
785 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
787 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
789 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
792 FrameBuffer
.QuadPart
=
793 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
794 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
795 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
797 MapInformation
->VideoRamLength
=
798 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
799 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
803 MapInformation
->VideoRamLength
=
804 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
805 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
811 FrameBuffer
.QuadPart
= 0xA0000;
812 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
813 MapInformation
->VideoRamLength
= 0x10000;
817 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
818 &MapInformation
->VideoRamLength
, &inIoSpace
,
819 &MapInformation
->VideoRamBase
);
821 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
822 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
828 * VBEUnmapVideoMemory
830 * Releases a mapping between the virtual address space and the adapter's
831 * frame buffer and video RAM.
836 PVBE_DEVICE_EXTENSION DeviceExtension
,
837 PVIDEO_MEMORY VideoMemory
,
838 PSTATUS_BLOCK StatusBlock
)
840 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
846 * VBEQueryNumAvailModes
848 * Returns the number of video modes supported by the adapter and the size
849 * in bytes of the video mode information, which can be used to allocate a
850 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
854 VBEQueryNumAvailModes(
855 PVBE_DEVICE_EXTENSION DeviceExtension
,
856 PVIDEO_NUM_MODES Modes
,
857 PSTATUS_BLOCK StatusBlock
)
859 Modes
->NumModes
= DeviceExtension
->ModeCount
;
860 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
861 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
868 * Returns information about one particular video mode.
873 PVBE_DEVICE_EXTENSION DeviceExtension
,
874 PVIDEO_MODE_INFORMATION VideoMode
,
877 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
879 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
880 VideoMode
->ModeIndex
= VideoModeId
;
881 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
882 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
883 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
884 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
886 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
887 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
888 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
889 VideoMode
->Frequency
= 1;
890 VideoMode
->XMillimeter
= 0; /* FIXME */
891 VideoMode
->YMillimeter
= 0; /* FIXME */
892 if (VBEMode
->BitsPerPixel
> 8)
895 * Always report 16bpp modes and not 15bpp mode...
897 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
899 VideoMode
->BitsPerPlane
= 16;
902 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
904 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
905 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
906 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
907 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
908 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
909 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
913 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
914 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
915 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
916 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
917 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
918 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
923 VideoMode
->NumberRedBits
=
924 VideoMode
->NumberGreenBits
=
925 VideoMode
->NumberBlueBits
= 6;
927 VideoMode
->GreenMask
=
928 VideoMode
->BlueMask
= 0;
930 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
931 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
932 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
933 VIDEO_MODE_NO_OFF_SCREEN
;
934 if (VideoMode
->BitsPerPlane
<= 8)
935 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
936 VideoMode
->DriverSpecificAttributeFlags
= 0;
942 * Returns information about each video mode supported by the adapter.
947 PVBE_DEVICE_EXTENSION DeviceExtension
,
948 PVIDEO_MODE_INFORMATION ReturnedModes
,
949 PSTATUS_BLOCK StatusBlock
)
952 PVIDEO_MODE_INFORMATION CurrentMode
;
953 PVBE_MODEINFO CurrentVBEMode
;
955 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
956 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
957 CurrentModeId
< DeviceExtension
->ModeCount
;
958 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
960 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
963 StatusBlock
->Information
=
964 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
970 * VBEQueryCurrentMode
972 * Returns information about current video mode.
977 PVBE_DEVICE_EXTENSION DeviceExtension
,
978 PVIDEO_MODE_INFORMATION VideoModeInfo
,
979 PSTATUS_BLOCK StatusBlock
)
981 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
986 DeviceExtension
->CurrentMode
);
992 * VBESetColorRegisters
994 * Sets the adapter's color registers to the specified RGB values. There
995 * are code paths in this function, one generic and one for VGA compatible
996 * controllers. The latter is needed for Bochs, where the generic one isn't
1001 VBESetColorRegisters(
1002 PVBE_DEVICE_EXTENSION DeviceExtension
,
1003 PVIDEO_CLUT ColorLookUpTable
,
1004 PSTATUS_BLOCK StatusBlock
)
1006 INT10_BIOS_ARGUMENTS BiosRegisters
;
1009 ULONG OutputBuffer
[256];
1011 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
1015 * For VGA compatible adapters program the color registers directly.
1018 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
1020 for (Entry
= ColorLookUpTable
->FirstEntry
;
1021 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1024 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1025 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1026 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1027 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1035 * We can't just copy the values, because we need to swap the Red
1039 for (Entry
= ColorLookUpTable
->FirstEntry
,
1040 OutputEntry
= OutputBuffer
;
1041 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1042 Entry
++, OutputEntry
++)
1045 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1046 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1047 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1050 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1051 DeviceExtension
->Int10Interface
.Context
,
1052 DeviceExtension
->TrampolineMemorySegment
,
1053 DeviceExtension
->TrampolineMemoryOffset
,
1055 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1057 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1058 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1059 BiosRegisters
.Ebx
= 0;
1060 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1061 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1062 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1063 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1064 DeviceExtension
->Int10Interface
.Int10CallBios(
1065 DeviceExtension
->Int10Interface
.Context
,
1068 return BiosRegisters
.Eax
== VBE_SUCCESS
;