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 *******************************************************************/
35 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
38 DriverEntry(IN PVOID Context1
, IN PVOID Context2
)
40 VIDEO_HW_INITIALIZATION_DATA InitData
;
42 VideoPortZeroMemory(&InitData
, sizeof(InitData
));
43 InitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
44 InitData
.HwFindAdapter
= VBEFindAdapter
;
45 InitData
.HwInitialize
= VBEInitialize
;
46 InitData
.HwStartIO
= VBEStartIO
;
47 InitData
.HwResetHw
= VBEResetHw
;
48 InitData
.HwGetPowerState
= VBEGetPowerState
;
49 InitData
.HwSetPowerState
= VBESetPowerState
;
50 InitData
.HwDeviceExtensionSize
= sizeof(VBE_DEVICE_EXTENSION
);
52 return VideoPortInitialize(Context1
, Context2
, &InitData
, NULL
);
58 * Should detect a VBE compatible display adapter, but it's not possible
59 * to use video port Int 10 services at this time during initialization,
60 * so we always return NO_ERROR and do the real work in VBEInitialize.
65 IN PVOID HwDeviceExtension
,
67 IN PWSTR ArgumentString
,
68 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
75 * VBESortModesCallback
77 * Helper function for sorting video mode list.
81 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA
, PVBE_MODEINFO VbeModeInfoB
)
83 DPRINT("VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
84 VbeModeInfoA
->XResolution
, VbeModeInfoA
->YResolution
,
85 VbeModeInfoA
->BitsPerPixel
,
86 VbeModeInfoB
->XResolution
, VbeModeInfoB
->YResolution
,
87 VbeModeInfoB
->BitsPerPixel
);
90 * FIXME: Until some reasonable method for changing video modes will
91 * be available we favor more bits per pixel. It should be changed
94 if (VbeModeInfoA
->BitsPerPixel
< VbeModeInfoB
->BitsPerPixel
) return -1;
95 if (VbeModeInfoA
->BitsPerPixel
> VbeModeInfoB
->BitsPerPixel
) return 1;
96 if (VbeModeInfoA
->XResolution
< VbeModeInfoB
->XResolution
) return -1;
97 if (VbeModeInfoA
->XResolution
> VbeModeInfoB
->XResolution
) return 1;
98 if (VbeModeInfoA
->YResolution
< VbeModeInfoB
->YResolution
) return -1;
99 if (VbeModeInfoA
->YResolution
> VbeModeInfoB
->YResolution
) return 1;
106 * Simple function for sorting the video mode list. Uses bubble sort.
110 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension
)
112 BOOLEAN Finished
= FALSE
;
115 VBE_MODEINFO TempModeInfo
;
121 for (Pos
= 0; Pos
< DeviceExtension
->ModeCount
- 1; Pos
++)
123 Result
= VBESortModesCallback(
124 DeviceExtension
->ModeInfo
+ Pos
,
125 DeviceExtension
->ModeInfo
+ Pos
+ 1);
132 DeviceExtension
->ModeInfo
+ Pos
,
133 sizeof(VBE_MODEINFO
));
134 TempModeNumber
= DeviceExtension
->ModeNumbers
[Pos
];
137 DeviceExtension
->ModeInfo
+ Pos
,
138 DeviceExtension
->ModeInfo
+ Pos
+ 1,
139 sizeof(VBE_MODEINFO
));
140 DeviceExtension
->ModeNumbers
[Pos
] =
141 DeviceExtension
->ModeNumbers
[Pos
+ 1];
144 DeviceExtension
->ModeInfo
+ Pos
+ 1,
146 sizeof(VBE_MODEINFO
));
147 DeviceExtension
->ModeNumbers
[Pos
+ 1] = TempModeNumber
;
156 * Performs the first initialization of the adapter, after the HAL has given
157 * up control of the video hardware to the video port driver.
159 * This function performs these steps:
160 * - Gets global VBE information and finds if VBE BIOS is present.
161 * - Builds the internal mode list using the list of modes provided by
166 VBEInitialize(PVOID HwDeviceExtension
)
168 INT10_BIOS_ARGUMENTS BiosRegisters
;
170 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
171 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
174 ULONG SuitableModeCount
;
177 PVBE_MODEINFO VbeModeInfo
;
180 * Get the Int 10 interface that we will use for allocating real
181 * mode memory and calling the video BIOS.
184 VBEDeviceExtension
->Int10Interface
.Version
= VIDEO_PORT_INT10_INTERFACE_VERSION_1
;
185 VBEDeviceExtension
->Int10Interface
.Size
= sizeof(VIDEO_PORT_INT10_INTERFACE
);
186 Status
= VideoPortQueryServices(
188 VideoPortServicesInt10
,
189 (PINTERFACE
)&VBEDeviceExtension
->Int10Interface
);
191 if (Status
!= NO_ERROR
)
193 DPRINT1("Failed to get Int 10 service functions (Status %x)\n", Status
);
198 * Allocate a bit of memory that will be later used for VBE transport
199 * buffer. This memory must be accessible from V86 mode so it must fit
200 * in the first megabyte of physical memory.
204 Status
= VBEDeviceExtension
->Int10Interface
.Int10AllocateBuffer(
205 VBEDeviceExtension
->Int10Interface
.Context
,
206 &VBEDeviceExtension
->TrampolineMemorySegment
,
207 &VBEDeviceExtension
->TrampolineMemoryOffset
,
210 if (Status
!= NO_ERROR
)
212 DPRINT1("Failed to allocate virtual memory (Status %x)\n", Status
);
217 * Get the VBE general information.
220 VBEDeviceExtension
->Int10Interface
.Int10WriteMemory(
221 VBEDeviceExtension
->Int10Interface
.Context
,
222 VBEDeviceExtension
->TrampolineMemorySegment
,
223 VBEDeviceExtension
->TrampolineMemoryOffset
,
227 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
228 BiosRegisters
.Eax
= VBE_GET_CONTROLLER_INFORMATION
;
229 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
;
230 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
231 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
232 VBEDeviceExtension
->Int10Interface
.Context
,
235 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
237 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
238 VBEDeviceExtension
->Int10Interface
.Context
,
239 VBEDeviceExtension
->TrampolineMemorySegment
,
240 VBEDeviceExtension
->TrampolineMemoryOffset
,
241 &VBEDeviceExtension
->VbeInfo
,
242 sizeof(VBEDeviceExtension
->VbeInfo
));
244 /* Dectect Bad VBE BIOS some Graphice card report 0x200 when they are VBE 1.2 */
245 if (VBEDeviceExtension
->VbeInfo
.OemVendorNamePtr
== 0 && VBEDeviceExtension
->VbeInfo
.Version
== 0x200)
247 VBEDeviceExtension
->VbeInfo
.Version
= 0x102;
251 DPRINT("VBE BIOS Present (%d.%d, %8ld Kb)\n",
252 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
253 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF,
254 VBEDeviceExtension
->VbeInfo
.TotalMemory
* 16);
257 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x102)
259 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x200)
262 DPRINT("VBE BIOS present, but incompatible version.\n");
268 DPRINT("No VBE BIOS found.\n");
273 * Build a mode list here that can be later used by
274 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
279 * Get the number of supported video modes.
281 * No need to be map the memory. It's either in the video BIOS memory or
282 * in our trampoline memory. In either case the memory is already mapped.
285 for (ModeCount
= 0; ; ModeCount
++)
287 /* Read the VBE mode number. */
288 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
289 VBEDeviceExtension
->Int10Interface
.Context
,
290 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
291 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
296 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
301 * Allocate space for video modes information.
304 VBEDeviceExtension
->ModeInfo
=
305 ExAllocatePool(PagedPool
, ModeCount
* sizeof(VBE_MODEINFO
));
306 VBEDeviceExtension
->ModeNumbers
=
307 ExAllocatePool(PagedPool
, ModeCount
* sizeof(WORD
));
310 * Get the actual mode infos.
313 for (CurrentMode
= 0, SuitableModeCount
= 0;
314 CurrentMode
< ModeCount
;
317 /* Read the VBE mode number. */
318 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
319 VBEDeviceExtension
->Int10Interface
.Context
,
320 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
321 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
325 /* Call VBE BIOS to read the mode info. */
326 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
327 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
328 BiosRegisters
.Ecx
= ModeTemp
;
329 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
330 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
331 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
332 VBEDeviceExtension
->Int10Interface
.Context
,
335 /* Read the VBE mode info. */
336 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
337 VBEDeviceExtension
->Int10Interface
.Context
,
338 VBEDeviceExtension
->TrampolineMemorySegment
,
339 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
340 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
341 sizeof(VBE_MODEINFO
));
343 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
345 /* Is this mode acceptable? */
346 if (BiosRegisters
.Eax
== VBE_SUCCESS
&&
347 VbeModeInfo
->XResolution
>= 640 &&
348 VbeModeInfo
->YResolution
>= 480 &&
349 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
350 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
))
352 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
354 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
360 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
367 if (SuitableModeCount
== 0)
369 DPRINT("VBEMP: No video modes supported\n");
373 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
376 * Sort the video mode list according to resolution and bits per pixel.
379 VBESortModes(VBEDeviceExtension
);
382 * Print the supported video modes when NDEBUG is not set.
386 for (CurrentMode
= 0;
387 CurrentMode
< SuitableModeCount
;
391 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
392 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
393 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
403 * Processes the specified Video Request Packet.
408 PVOID HwDeviceExtension
,
409 PVIDEO_REQUEST_PACKET RequestPacket
)
413 RequestPacket
->StatusBlock
->Status
= STATUS_UNSUCCESSFUL
;
415 switch (RequestPacket
->IoControlCode
)
417 case IOCTL_VIDEO_SET_CURRENT_MODE
:
418 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
420 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
423 Result
= VBESetCurrentMode(
424 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
425 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
426 RequestPacket
->StatusBlock
);
429 case IOCTL_VIDEO_RESET_DEVICE
:
430 Result
= VBEResetDevice(
431 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
432 RequestPacket
->StatusBlock
);
435 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
436 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
437 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
439 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
442 Result
= VBEMapVideoMemory(
443 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
444 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
445 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
446 RequestPacket
->StatusBlock
);
449 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
450 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
452 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
455 Result
= VBEUnmapVideoMemory(
456 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
457 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
458 RequestPacket
->StatusBlock
);
461 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
462 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
464 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
467 Result
= VBEQueryNumAvailModes(
468 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
469 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
470 RequestPacket
->StatusBlock
);
473 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
474 if (RequestPacket
->OutputBufferLength
<
475 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
477 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
480 Result
= VBEQueryAvailModes(
481 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
482 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
483 RequestPacket
->StatusBlock
);
486 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
487 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
488 RequestPacket
->InputBufferLength
<
489 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
490 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
492 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
495 Result
= VBESetColorRegisters(
496 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
497 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
498 RequestPacket
->StatusBlock
);
501 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
502 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
504 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
507 Result
= VBEQueryCurrentMode(
508 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
509 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
510 RequestPacket
->StatusBlock
);
514 RequestPacket
->StatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
519 RequestPacket
->StatusBlock
->Status
= STATUS_SUCCESS
;
527 * This function is called to reset the hardware to a known state.
532 PVOID DeviceExtension
,
536 INT10_BIOS_ARGUMENTS BiosRegisters
;
537 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
538 (PVBE_DEVICE_EXTENSION
)DeviceExtension
;
540 if (!VBEResetDevice(DeviceExtension
, NULL
))
543 /* Change number of columns/rows */
544 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
546 if (Columns
== 80 && Rows
== 25)
548 /* Default text size, don't change anything. */
551 else if (Columns
== 80 && Rows
== 28)
553 /* Use 9x14 font (80x28) */
554 BiosRegisters
.Eax
= 0x1111;
556 else if (Columns
== 80 && Rows
== 43)
558 /* Use 8x8 font in 350 scans mode (80x43) */
559 BiosRegisters
.Eax
= 0x1201;
560 BiosRegisters
.Ebx
= 0x30;
561 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
562 VBEDeviceExtension
->Int10Interface
.Context
,
565 BiosRegisters
.Eax
= 0x3;
566 BiosRegisters
.Ebx
= 0;
567 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
568 VBEDeviceExtension
->Int10Interface
.Context
,
571 BiosRegisters
.Eax
= 0x1112;
573 else if (Columns
== 80 && Rows
== 50)
575 /* Use 8x8 font (80x50) */
576 BiosRegisters
.Eax
= 0x1112;
581 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
582 VBEDeviceExtension
->Int10Interface
.Context
,
591 * Queries whether the device can support the requested power state.
596 PVOID HwDeviceExtension
,
598 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
600 INT10_BIOS_ARGUMENTS BiosRegisters
;
601 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
602 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
604 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
605 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
606 return ERROR_INVALID_FUNCTION
;
609 * Get general power support information.
612 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
613 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
614 BiosRegisters
.Ebx
= 0;
615 BiosRegisters
.Edi
= 0;
616 BiosRegisters
.SegEs
= 0;
617 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
618 VBEDeviceExtension
->Int10Interface
.Context
,
621 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
622 return ERROR_NOT_SUPPORTED
;
623 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
624 return ERROR_INVALID_FUNCTION
;
627 * Get current power state.
630 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
631 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
632 BiosRegisters
.Ebx
= 0x2;
633 BiosRegisters
.Edi
= 0;
634 BiosRegisters
.SegEs
= 0;
635 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
636 VBEDeviceExtension
->Int10Interface
.Context
,
639 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
641 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
642 switch (BiosRegisters
.Ebx
>> 8)
644 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
645 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
646 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
647 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
648 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
649 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
655 return ERROR_NOT_SUPPORTED
;
661 * Sets the power state of the specified device
666 PVOID HwDeviceExtension
,
668 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
670 INT10_BIOS_ARGUMENTS BiosRegisters
;
671 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
672 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
674 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
675 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
676 VideoPowerControl
->PowerState
< VideoPowerOn
||
677 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
678 return ERROR_INVALID_FUNCTION
;
680 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
684 * Set current power state.
687 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
688 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
689 BiosRegisters
.Ebx
= 1;
690 BiosRegisters
.Edi
= 0;
691 BiosRegisters
.SegEs
= 0;
692 switch (VideoPowerControl
->PowerState
)
694 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
695 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
696 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
699 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
700 VBEDeviceExtension
->Int10Interface
.Context
,
703 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
704 return ERROR_NOT_SUPPORTED
;
705 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
706 return ERROR_INVALID_FUNCTION
;
714 * Sets the adapter to the specified operating mode.
719 PVBE_DEVICE_EXTENSION DeviceExtension
,
720 PVIDEO_MODE RequestedMode
,
721 PSTATUS_BLOCK StatusBlock
)
723 INT10_BIOS_ARGUMENTS BiosRegisters
;
725 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
727 return ERROR_INVALID_PARAMETER
;
730 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
731 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
732 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
733 DeviceExtension
->Int10Interface
.Int10CallBios(
734 DeviceExtension
->Int10Interface
.Context
,
737 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
739 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
743 DPRINT1("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
744 DeviceExtension
->CurrentMode
= -1;
747 return BiosRegisters
.Eax
== VBE_SUCCESS
;
753 * Resets the video hardware to the default mode, to which it was initialized
759 PVBE_DEVICE_EXTENSION DeviceExtension
,
760 PSTATUS_BLOCK StatusBlock
)
762 INT10_BIOS_ARGUMENTS BiosRegisters
;
764 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
765 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
766 BiosRegisters
.Ebx
= 0x3;
767 DeviceExtension
->Int10Interface
.Int10CallBios(
768 DeviceExtension
->Int10Interface
.Context
,
771 return BiosRegisters
.Eax
== VBE_SUCCESS
;
777 * Maps the video hardware frame buffer and video RAM into the virtual address
778 * space of the requestor.
783 PVBE_DEVICE_EXTENSION DeviceExtension
,
784 PVIDEO_MEMORY RequestedAddress
,
785 PVIDEO_MEMORY_INFORMATION MapInformation
,
786 PSTATUS_BLOCK StatusBlock
)
788 PHYSICAL_ADDRESS FrameBuffer
;
789 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
791 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
793 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
796 FrameBuffer
.QuadPart
=
797 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
798 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
799 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
801 MapInformation
->VideoRamLength
=
802 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
803 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
807 MapInformation
->VideoRamLength
=
808 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
809 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
815 FrameBuffer
.QuadPart
= 0xA0000;
816 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
817 MapInformation
->VideoRamLength
= 0x10000;
821 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
822 &MapInformation
->VideoRamLength
, &inIoSpace
,
823 &MapInformation
->VideoRamBase
);
825 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
826 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
832 * VBEUnmapVideoMemory
834 * Releases a mapping between the virtual address space and the adapter's
835 * frame buffer and video RAM.
840 PVBE_DEVICE_EXTENSION DeviceExtension
,
841 PVIDEO_MEMORY VideoMemory
,
842 PSTATUS_BLOCK StatusBlock
)
844 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
850 * VBEQueryNumAvailModes
852 * Returns the number of video modes supported by the adapter and the size
853 * in bytes of the video mode information, which can be used to allocate a
854 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
858 VBEQueryNumAvailModes(
859 PVBE_DEVICE_EXTENSION DeviceExtension
,
860 PVIDEO_NUM_MODES Modes
,
861 PSTATUS_BLOCK StatusBlock
)
863 Modes
->NumModes
= DeviceExtension
->ModeCount
;
864 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
865 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
872 * Returns information about one particular video mode.
877 PVBE_DEVICE_EXTENSION DeviceExtension
,
878 PVIDEO_MODE_INFORMATION VideoMode
,
881 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
883 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
884 VideoMode
->ModeIndex
= VideoModeId
;
885 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
886 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
887 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
888 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
890 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
891 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
892 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
893 VideoMode
->Frequency
= 1;
894 VideoMode
->XMillimeter
= 0; /* FIXME */
895 VideoMode
->YMillimeter
= 0; /* FIXME */
896 if (VBEMode
->BitsPerPixel
> 8)
899 * Always report 16bpp modes and not 15bpp mode...
901 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
903 VideoMode
->BitsPerPlane
= 16;
906 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
908 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
909 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
910 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
911 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
912 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
913 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
917 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
918 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
919 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
920 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
921 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
922 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
927 VideoMode
->NumberRedBits
=
928 VideoMode
->NumberGreenBits
=
929 VideoMode
->NumberBlueBits
= 6;
931 VideoMode
->GreenMask
=
932 VideoMode
->BlueMask
= 0;
934 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
935 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
936 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
937 VIDEO_MODE_NO_OFF_SCREEN
;
938 if (VideoMode
->BitsPerPlane
<= 8)
939 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
940 VideoMode
->DriverSpecificAttributeFlags
= 0;
946 * Returns information about each video mode supported by the adapter.
951 PVBE_DEVICE_EXTENSION DeviceExtension
,
952 PVIDEO_MODE_INFORMATION ReturnedModes
,
953 PSTATUS_BLOCK StatusBlock
)
956 PVIDEO_MODE_INFORMATION CurrentMode
;
957 PVBE_MODEINFO CurrentVBEMode
;
959 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
960 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
961 CurrentModeId
< DeviceExtension
->ModeCount
;
962 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
964 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
967 StatusBlock
->Information
=
968 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
974 * VBEQueryCurrentMode
976 * Returns information about current video mode.
981 PVBE_DEVICE_EXTENSION DeviceExtension
,
982 PVIDEO_MODE_INFORMATION VideoModeInfo
,
983 PSTATUS_BLOCK StatusBlock
)
985 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
990 DeviceExtension
->CurrentMode
);
996 * VBESetColorRegisters
998 * Sets the adapter's color registers to the specified RGB values. There
999 * are code paths in this function, one generic and one for VGA compatible
1000 * controllers. The latter is needed for Bochs, where the generic one isn't
1005 VBESetColorRegisters(
1006 PVBE_DEVICE_EXTENSION DeviceExtension
,
1007 PVIDEO_CLUT ColorLookUpTable
,
1008 PSTATUS_BLOCK StatusBlock
)
1010 INT10_BIOS_ARGUMENTS BiosRegisters
;
1013 ULONG OutputBuffer
[256];
1015 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
1019 * For VGA compatible adapters program the color registers directly.
1022 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
1024 for (Entry
= ColorLookUpTable
->FirstEntry
;
1025 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1028 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1029 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1030 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1031 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1039 * We can't just copy the values, because we need to swap the Red
1043 for (Entry
= ColorLookUpTable
->FirstEntry
,
1044 OutputEntry
= OutputBuffer
;
1045 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1046 Entry
++, OutputEntry
++)
1049 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1050 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1051 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1054 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1055 DeviceExtension
->Int10Interface
.Context
,
1056 DeviceExtension
->TrampolineMemorySegment
,
1057 DeviceExtension
->TrampolineMemoryOffset
,
1059 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1061 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1062 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1063 BiosRegisters
.Ebx
= 0;
1064 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1065 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1066 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1067 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1068 DeviceExtension
->Int10Interface
.Int10CallBios(
1069 DeviceExtension
->Int10Interface
.Context
,
1072 return BiosRegisters
.Eax
== VBE_SUCCESS
;