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
;
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(WORD
), 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
))
349 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
351 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
357 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
364 if (SuitableModeCount
== 0)
366 VideoPortDebugPrint(Warn
, "VBEMP: No video modes supported\n");
370 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
373 * Sort the video mode list according to resolution and bits per pixel.
376 VBESortModes(VBEDeviceExtension
);
379 * Print the supported video modes when NDEBUG is not set.
382 for (CurrentMode
= 0;
383 CurrentMode
< SuitableModeCount
;
386 VideoPortDebugPrint(Trace
, "%dx%dx%d\n",
387 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
388 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
389 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
398 * Processes the specified Video Request Packet.
403 PVOID HwDeviceExtension
,
404 PVIDEO_REQUEST_PACKET RequestPacket
)
408 RequestPacket
->StatusBlock
->Status
= STATUS_UNSUCCESSFUL
;
410 switch (RequestPacket
->IoControlCode
)
412 case IOCTL_VIDEO_SET_CURRENT_MODE
:
413 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
415 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
418 Result
= VBESetCurrentMode(
419 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
420 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
421 RequestPacket
->StatusBlock
);
424 case IOCTL_VIDEO_RESET_DEVICE
:
425 Result
= VBEResetDevice(
426 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
427 RequestPacket
->StatusBlock
);
430 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
431 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
432 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
434 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
437 Result
= VBEMapVideoMemory(
438 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
439 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
440 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
441 RequestPacket
->StatusBlock
);
444 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
445 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
447 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
450 Result
= VBEUnmapVideoMemory(
451 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
452 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
453 RequestPacket
->StatusBlock
);
456 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
457 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
459 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
462 Result
= VBEQueryNumAvailModes(
463 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
464 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
465 RequestPacket
->StatusBlock
);
468 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
469 if (RequestPacket
->OutputBufferLength
<
470 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
472 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
475 Result
= VBEQueryAvailModes(
476 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
477 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
478 RequestPacket
->StatusBlock
);
481 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
482 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
483 RequestPacket
->InputBufferLength
<
484 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
485 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
487 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
490 Result
= VBESetColorRegisters(
491 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
492 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
493 RequestPacket
->StatusBlock
);
496 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
497 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
499 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
502 Result
= VBEQueryCurrentMode(
503 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
504 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
505 RequestPacket
->StatusBlock
);
509 RequestPacket
->StatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
514 RequestPacket
->StatusBlock
->Status
= STATUS_SUCCESS
;
522 * This function is called to reset the hardware to a known state.
527 PVOID DeviceExtension
,
531 INT10_BIOS_ARGUMENTS BiosRegisters
;
532 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
533 (PVBE_DEVICE_EXTENSION
)DeviceExtension
;
535 if (!VBEResetDevice(DeviceExtension
, NULL
))
538 /* Change number of columns/rows */
539 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
541 if (Columns
== 80 && Rows
== 25)
543 /* Default text size, don't change anything. */
546 else if (Columns
== 80 && Rows
== 28)
548 /* Use 9x14 font (80x28) */
549 BiosRegisters
.Eax
= 0x1111;
551 else if (Columns
== 80 && Rows
== 43)
553 /* Use 8x8 font in 350 scans mode (80x43) */
554 BiosRegisters
.Eax
= 0x1201;
555 BiosRegisters
.Ebx
= 0x30;
556 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
557 VBEDeviceExtension
->Int10Interface
.Context
,
560 BiosRegisters
.Eax
= 0x3;
561 BiosRegisters
.Ebx
= 0;
562 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
563 VBEDeviceExtension
->Int10Interface
.Context
,
566 BiosRegisters
.Eax
= 0x1112;
568 else if (Columns
== 80 && Rows
== 50)
570 /* Use 8x8 font (80x50) */
571 BiosRegisters
.Eax
= 0x1112;
576 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
577 VBEDeviceExtension
->Int10Interface
.Context
,
586 * Queries whether the device can support the requested power state.
591 PVOID HwDeviceExtension
,
593 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
595 INT10_BIOS_ARGUMENTS BiosRegisters
;
596 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
597 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
599 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
600 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
601 return ERROR_INVALID_FUNCTION
;
604 * Get general power support information.
607 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
608 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
609 BiosRegisters
.Ebx
= 0;
610 BiosRegisters
.Edi
= 0;
611 BiosRegisters
.SegEs
= 0;
612 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
613 VBEDeviceExtension
->Int10Interface
.Context
,
616 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
617 return ERROR_NOT_SUPPORTED
;
618 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
619 return ERROR_INVALID_FUNCTION
;
622 * Get current power state.
625 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
626 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
627 BiosRegisters
.Ebx
= 0x2;
628 BiosRegisters
.Edi
= 0;
629 BiosRegisters
.SegEs
= 0;
630 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
631 VBEDeviceExtension
->Int10Interface
.Context
,
634 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
636 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
637 switch (BiosRegisters
.Ebx
>> 8)
639 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
640 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
641 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
642 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
643 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
644 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
650 return ERROR_NOT_SUPPORTED
;
656 * Sets the power state of the specified device
661 PVOID HwDeviceExtension
,
663 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
665 INT10_BIOS_ARGUMENTS BiosRegisters
;
666 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
667 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
669 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
670 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
671 VideoPowerControl
->PowerState
< VideoPowerOn
||
672 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
673 return ERROR_INVALID_FUNCTION
;
675 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
679 * Set current power state.
682 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
683 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
684 BiosRegisters
.Ebx
= 1;
685 BiosRegisters
.Edi
= 0;
686 BiosRegisters
.SegEs
= 0;
687 switch (VideoPowerControl
->PowerState
)
689 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
690 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
691 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
694 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
695 VBEDeviceExtension
->Int10Interface
.Context
,
698 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
699 return ERROR_NOT_SUPPORTED
;
700 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
701 return ERROR_INVALID_FUNCTION
;
709 * Sets the adapter to the specified operating mode.
714 PVBE_DEVICE_EXTENSION DeviceExtension
,
715 PVIDEO_MODE RequestedMode
,
716 PSTATUS_BLOCK StatusBlock
)
718 INT10_BIOS_ARGUMENTS BiosRegisters
;
720 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
722 return ERROR_INVALID_PARAMETER
;
725 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
726 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
727 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
728 DeviceExtension
->Int10Interface
.Int10CallBios(
729 DeviceExtension
->Int10Interface
.Context
,
732 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
734 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
738 VideoPortDebugPrint(Error
, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
739 DeviceExtension
->CurrentMode
= -1;
742 return BiosRegisters
.Eax
== VBE_SUCCESS
;
748 * Resets the video hardware to the default mode, to which it was initialized
754 PVBE_DEVICE_EXTENSION DeviceExtension
,
755 PSTATUS_BLOCK StatusBlock
)
757 INT10_BIOS_ARGUMENTS BiosRegisters
;
759 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
760 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
761 BiosRegisters
.Ebx
= 0x3;
762 DeviceExtension
->Int10Interface
.Int10CallBios(
763 DeviceExtension
->Int10Interface
.Context
,
766 return BiosRegisters
.Eax
== VBE_SUCCESS
;
772 * Maps the video hardware frame buffer and video RAM into the virtual address
773 * space of the requestor.
778 PVBE_DEVICE_EXTENSION DeviceExtension
,
779 PVIDEO_MEMORY RequestedAddress
,
780 PVIDEO_MEMORY_INFORMATION MapInformation
,
781 PSTATUS_BLOCK StatusBlock
)
783 PHYSICAL_ADDRESS FrameBuffer
;
784 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
786 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
788 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
791 FrameBuffer
.QuadPart
=
792 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
793 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
794 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
796 MapInformation
->VideoRamLength
=
797 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
798 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
802 MapInformation
->VideoRamLength
=
803 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
804 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
810 FrameBuffer
.QuadPart
= 0xA0000;
811 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
812 MapInformation
->VideoRamLength
= 0x10000;
816 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
817 &MapInformation
->VideoRamLength
, &inIoSpace
,
818 &MapInformation
->VideoRamBase
);
820 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
821 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
827 * VBEUnmapVideoMemory
829 * Releases a mapping between the virtual address space and the adapter's
830 * frame buffer and video RAM.
835 PVBE_DEVICE_EXTENSION DeviceExtension
,
836 PVIDEO_MEMORY VideoMemory
,
837 PSTATUS_BLOCK StatusBlock
)
839 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
845 * VBEQueryNumAvailModes
847 * Returns the number of video modes supported by the adapter and the size
848 * in bytes of the video mode information, which can be used to allocate a
849 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
853 VBEQueryNumAvailModes(
854 PVBE_DEVICE_EXTENSION DeviceExtension
,
855 PVIDEO_NUM_MODES Modes
,
856 PSTATUS_BLOCK StatusBlock
)
858 Modes
->NumModes
= DeviceExtension
->ModeCount
;
859 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
860 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
867 * Returns information about one particular video mode.
872 PVBE_DEVICE_EXTENSION DeviceExtension
,
873 PVIDEO_MODE_INFORMATION VideoMode
,
876 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
878 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
879 VideoMode
->ModeIndex
= VideoModeId
;
880 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
881 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
882 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
883 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
885 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
886 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
887 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
888 VideoMode
->Frequency
= 1;
889 VideoMode
->XMillimeter
= 0; /* FIXME */
890 VideoMode
->YMillimeter
= 0; /* FIXME */
891 if (VBEMode
->BitsPerPixel
> 8)
894 * Always report 16bpp modes and not 15bpp mode...
896 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
898 VideoMode
->BitsPerPlane
= 16;
901 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
903 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
904 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
905 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
906 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
907 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
908 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
912 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
913 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
914 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
915 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
916 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
917 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
922 VideoMode
->NumberRedBits
=
923 VideoMode
->NumberGreenBits
=
924 VideoMode
->NumberBlueBits
= 6;
926 VideoMode
->GreenMask
=
927 VideoMode
->BlueMask
= 0;
929 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
930 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
931 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
932 VIDEO_MODE_NO_OFF_SCREEN
;
933 if (VideoMode
->BitsPerPlane
<= 8)
934 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
935 VideoMode
->DriverSpecificAttributeFlags
= 0;
941 * Returns information about each video mode supported by the adapter.
946 PVBE_DEVICE_EXTENSION DeviceExtension
,
947 PVIDEO_MODE_INFORMATION ReturnedModes
,
948 PSTATUS_BLOCK StatusBlock
)
951 PVIDEO_MODE_INFORMATION CurrentMode
;
952 PVBE_MODEINFO CurrentVBEMode
;
954 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
955 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
956 CurrentModeId
< DeviceExtension
->ModeCount
;
957 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
959 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
962 StatusBlock
->Information
=
963 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
969 * VBEQueryCurrentMode
971 * Returns information about current video mode.
976 PVBE_DEVICE_EXTENSION DeviceExtension
,
977 PVIDEO_MODE_INFORMATION VideoModeInfo
,
978 PSTATUS_BLOCK StatusBlock
)
980 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
985 DeviceExtension
->CurrentMode
);
991 * VBESetColorRegisters
993 * Sets the adapter's color registers to the specified RGB values. There
994 * are code paths in this function, one generic and one for VGA compatible
995 * controllers. The latter is needed for Bochs, where the generic one isn't
1000 VBESetColorRegisters(
1001 PVBE_DEVICE_EXTENSION DeviceExtension
,
1002 PVIDEO_CLUT ColorLookUpTable
,
1003 PSTATUS_BLOCK StatusBlock
)
1005 INT10_BIOS_ARGUMENTS BiosRegisters
;
1008 ULONG OutputBuffer
[256];
1010 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
1014 * For VGA compatible adapters program the color registers directly.
1017 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
1019 for (Entry
= ColorLookUpTable
->FirstEntry
;
1020 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1023 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1024 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1025 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1026 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1034 * We can't just copy the values, because we need to swap the Red
1038 for (Entry
= ColorLookUpTable
->FirstEntry
,
1039 OutputEntry
= OutputBuffer
;
1040 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1041 Entry
++, OutputEntry
++)
1044 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1045 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1046 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1049 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1050 DeviceExtension
->Int10Interface
.Context
,
1051 DeviceExtension
->TrampolineMemorySegment
,
1052 DeviceExtension
->TrampolineMemoryOffset
,
1054 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1056 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1057 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1058 BiosRegisters
.Ebx
= 0;
1059 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1060 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1061 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1062 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1063 DeviceExtension
->Int10Interface
.Int10CallBios(
1064 DeviceExtension
->Int10Interface
.Context
,
1067 return BiosRegisters
.Eax
== VBE_SUCCESS
;