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 /* Verify VBE is found and not anýthing else */
245 if (strncmp(VBEDeviceExtension
->VbeInfo
.Signature
,"VESA",4) != 0)
247 DPRINT("No VBE BIOS present\n");
251 /* Dectect Bad VBE BIOS some Graphice card report 0x200 when they are VBE 1.2 */
252 if (VBEDeviceExtension
->VbeInfo
.OemVendorNamePtr
== 0 && VBEDeviceExtension
->VbeInfo
.Version
== 0x200)
254 VBEDeviceExtension
->VbeInfo
.Version
= 0x102;
257 DPRINT("VBE BIOS Present (%d.%d, %8ld Kb)\n",
258 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
259 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF,
260 VBEDeviceExtension
->VbeInfo
.TotalMemory
* 64);
263 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x102)
265 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x200)
268 DPRINT("VBE BIOS present, but incompatible version.\n");
274 DPRINT("No VBE BIOS found.\n");
279 * Build a mode list here that can be later used by
280 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
285 * Get the number of supported video modes.
287 * No need to be map the memory. It's either in the video BIOS memory or
288 * in our trampoline memory. In either case the memory is already mapped.
291 for (ModeCount
= 0; ; ModeCount
++)
293 /* Read the VBE mode number. */
294 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
295 VBEDeviceExtension
->Int10Interface
.Context
,
296 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
297 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
302 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
307 * Allocate space for video modes information.
310 VBEDeviceExtension
->ModeInfo
=
311 ExAllocatePool(PagedPool
, ModeCount
* sizeof(VBE_MODEINFO
));
312 VBEDeviceExtension
->ModeNumbers
=
313 ExAllocatePool(PagedPool
, ModeCount
* sizeof(WORD
));
316 * Get the actual mode infos.
319 for (CurrentMode
= 0, SuitableModeCount
= 0;
320 CurrentMode
< ModeCount
;
323 /* Read the VBE mode number. */
324 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
325 VBEDeviceExtension
->Int10Interface
.Context
,
326 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
327 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
331 /* Call VBE BIOS to read the mode info. */
332 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
333 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
334 BiosRegisters
.Ecx
= ModeTemp
;
335 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
336 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
337 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
338 VBEDeviceExtension
->Int10Interface
.Context
,
341 /* Read the VBE mode info. */
342 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
343 VBEDeviceExtension
->Int10Interface
.Context
,
344 VBEDeviceExtension
->TrampolineMemorySegment
,
345 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
346 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
347 sizeof(VBE_MODEINFO
));
349 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
351 /* Is this mode acceptable? */
352 if (BiosRegisters
.Eax
== VBE_SUCCESS
&&
353 VbeModeInfo
->XResolution
>= 640 &&
354 VbeModeInfo
->YResolution
>= 480 &&
355 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
356 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
))
358 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
360 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
366 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
373 if (SuitableModeCount
== 0)
375 DPRINT("VBEMP: No video modes supported\n");
379 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
382 * Sort the video mode list according to resolution and bits per pixel.
385 VBESortModes(VBEDeviceExtension
);
388 * Print the supported video modes when NDEBUG is not set.
392 for (CurrentMode
= 0;
393 CurrentMode
< SuitableModeCount
;
397 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
398 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
399 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
409 * Processes the specified Video Request Packet.
414 PVOID HwDeviceExtension
,
415 PVIDEO_REQUEST_PACKET RequestPacket
)
419 RequestPacket
->StatusBlock
->Status
= STATUS_UNSUCCESSFUL
;
421 switch (RequestPacket
->IoControlCode
)
423 case IOCTL_VIDEO_SET_CURRENT_MODE
:
424 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
426 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
429 Result
= VBESetCurrentMode(
430 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
431 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
432 RequestPacket
->StatusBlock
);
435 case IOCTL_VIDEO_RESET_DEVICE
:
436 Result
= VBEResetDevice(
437 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
438 RequestPacket
->StatusBlock
);
441 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
442 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
443 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
445 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
448 Result
= VBEMapVideoMemory(
449 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
450 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
451 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
452 RequestPacket
->StatusBlock
);
455 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
456 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
458 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
461 Result
= VBEUnmapVideoMemory(
462 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
463 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
464 RequestPacket
->StatusBlock
);
467 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
468 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
470 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
473 Result
= VBEQueryNumAvailModes(
474 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
475 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
476 RequestPacket
->StatusBlock
);
479 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
480 if (RequestPacket
->OutputBufferLength
<
481 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
483 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
486 Result
= VBEQueryAvailModes(
487 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
488 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
489 RequestPacket
->StatusBlock
);
492 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
493 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
494 RequestPacket
->InputBufferLength
<
495 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
496 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
498 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
501 Result
= VBESetColorRegisters(
502 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
503 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
504 RequestPacket
->StatusBlock
);
507 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
508 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
510 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
513 Result
= VBEQueryCurrentMode(
514 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
515 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
516 RequestPacket
->StatusBlock
);
520 RequestPacket
->StatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
525 RequestPacket
->StatusBlock
->Status
= STATUS_SUCCESS
;
533 * This function is called to reset the hardware to a known state.
538 PVOID DeviceExtension
,
542 INT10_BIOS_ARGUMENTS BiosRegisters
;
543 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
544 (PVBE_DEVICE_EXTENSION
)DeviceExtension
;
546 if (!VBEResetDevice(DeviceExtension
, NULL
))
549 /* Change number of columns/rows */
550 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
552 if (Columns
== 80 && Rows
== 25)
554 /* Default text size, don't change anything. */
557 else if (Columns
== 80 && Rows
== 28)
559 /* Use 9x14 font (80x28) */
560 BiosRegisters
.Eax
= 0x1111;
562 else if (Columns
== 80 && Rows
== 43)
564 /* Use 8x8 font in 350 scans mode (80x43) */
565 BiosRegisters
.Eax
= 0x1201;
566 BiosRegisters
.Ebx
= 0x30;
567 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
568 VBEDeviceExtension
->Int10Interface
.Context
,
571 BiosRegisters
.Eax
= 0x3;
572 BiosRegisters
.Ebx
= 0;
573 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
574 VBEDeviceExtension
->Int10Interface
.Context
,
577 BiosRegisters
.Eax
= 0x1112;
579 else if (Columns
== 80 && Rows
== 50)
581 /* Use 8x8 font (80x50) */
582 BiosRegisters
.Eax
= 0x1112;
587 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
588 VBEDeviceExtension
->Int10Interface
.Context
,
597 * Queries whether the device can support the requested power state.
602 PVOID HwDeviceExtension
,
604 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
606 INT10_BIOS_ARGUMENTS BiosRegisters
;
607 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
608 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
610 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
611 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
612 return ERROR_INVALID_FUNCTION
;
615 * Get general power support information.
618 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
619 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
620 BiosRegisters
.Ebx
= 0;
621 BiosRegisters
.Edi
= 0;
622 BiosRegisters
.SegEs
= 0;
623 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
624 VBEDeviceExtension
->Int10Interface
.Context
,
627 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
628 return ERROR_NOT_SUPPORTED
;
629 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
630 return ERROR_INVALID_FUNCTION
;
633 * Get current power state.
636 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
637 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
638 BiosRegisters
.Ebx
= 0x2;
639 BiosRegisters
.Edi
= 0;
640 BiosRegisters
.SegEs
= 0;
641 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
642 VBEDeviceExtension
->Int10Interface
.Context
,
645 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
647 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
648 switch (BiosRegisters
.Ebx
>> 8)
650 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
651 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
652 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
653 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
654 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
655 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
661 return ERROR_NOT_SUPPORTED
;
667 * Sets the power state of the specified device
672 PVOID HwDeviceExtension
,
674 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
676 INT10_BIOS_ARGUMENTS BiosRegisters
;
677 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
678 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
680 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
681 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
682 VideoPowerControl
->PowerState
< VideoPowerOn
||
683 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
684 return ERROR_INVALID_FUNCTION
;
686 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
690 * Set current power state.
693 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
694 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
695 BiosRegisters
.Ebx
= 1;
696 BiosRegisters
.Edi
= 0;
697 BiosRegisters
.SegEs
= 0;
698 switch (VideoPowerControl
->PowerState
)
700 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
701 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
702 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
705 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
706 VBEDeviceExtension
->Int10Interface
.Context
,
709 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
710 return ERROR_NOT_SUPPORTED
;
711 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
712 return ERROR_INVALID_FUNCTION
;
720 * Sets the adapter to the specified operating mode.
725 PVBE_DEVICE_EXTENSION DeviceExtension
,
726 PVIDEO_MODE RequestedMode
,
727 PSTATUS_BLOCK StatusBlock
)
729 INT10_BIOS_ARGUMENTS BiosRegisters
;
731 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
733 return ERROR_INVALID_PARAMETER
;
736 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
737 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
738 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
739 DeviceExtension
->Int10Interface
.Int10CallBios(
740 DeviceExtension
->Int10Interface
.Context
,
743 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
745 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
749 DPRINT1("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
750 DeviceExtension
->CurrentMode
= -1;
753 return BiosRegisters
.Eax
== VBE_SUCCESS
;
759 * Resets the video hardware to the default mode, to which it was initialized
765 PVBE_DEVICE_EXTENSION DeviceExtension
,
766 PSTATUS_BLOCK StatusBlock
)
768 INT10_BIOS_ARGUMENTS BiosRegisters
;
770 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
771 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
772 BiosRegisters
.Ebx
= 0x3;
773 DeviceExtension
->Int10Interface
.Int10CallBios(
774 DeviceExtension
->Int10Interface
.Context
,
777 return BiosRegisters
.Eax
== VBE_SUCCESS
;
783 * Maps the video hardware frame buffer and video RAM into the virtual address
784 * space of the requestor.
789 PVBE_DEVICE_EXTENSION DeviceExtension
,
790 PVIDEO_MEMORY RequestedAddress
,
791 PVIDEO_MEMORY_INFORMATION MapInformation
,
792 PSTATUS_BLOCK StatusBlock
)
794 PHYSICAL_ADDRESS FrameBuffer
;
795 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
797 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
799 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
802 FrameBuffer
.QuadPart
=
803 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
804 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
805 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
807 MapInformation
->VideoRamLength
=
808 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
809 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
813 MapInformation
->VideoRamLength
=
814 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
815 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
821 FrameBuffer
.QuadPart
= 0xA0000;
822 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
823 MapInformation
->VideoRamLength
= 0x10000;
827 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
828 &MapInformation
->VideoRamLength
, &inIoSpace
,
829 &MapInformation
->VideoRamBase
);
831 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
832 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
838 * VBEUnmapVideoMemory
840 * Releases a mapping between the virtual address space and the adapter's
841 * frame buffer and video RAM.
846 PVBE_DEVICE_EXTENSION DeviceExtension
,
847 PVIDEO_MEMORY VideoMemory
,
848 PSTATUS_BLOCK StatusBlock
)
850 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
856 * VBEQueryNumAvailModes
858 * Returns the number of video modes supported by the adapter and the size
859 * in bytes of the video mode information, which can be used to allocate a
860 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
864 VBEQueryNumAvailModes(
865 PVBE_DEVICE_EXTENSION DeviceExtension
,
866 PVIDEO_NUM_MODES Modes
,
867 PSTATUS_BLOCK StatusBlock
)
869 Modes
->NumModes
= DeviceExtension
->ModeCount
;
870 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
871 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
878 * Returns information about one particular video mode.
883 PVBE_DEVICE_EXTENSION DeviceExtension
,
884 PVIDEO_MODE_INFORMATION VideoMode
,
887 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
889 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
890 VideoMode
->ModeIndex
= VideoModeId
;
891 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
892 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
893 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
894 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
896 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
897 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
898 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
899 VideoMode
->Frequency
= 1;
900 VideoMode
->XMillimeter
= 0; /* FIXME */
901 VideoMode
->YMillimeter
= 0; /* FIXME */
902 if (VBEMode
->BitsPerPixel
> 8)
905 * Always report 16bpp modes and not 15bpp mode...
907 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
909 VideoMode
->BitsPerPlane
= 16;
912 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
914 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
915 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
916 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
917 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
918 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
919 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
923 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
924 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
925 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
926 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
927 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
928 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
933 VideoMode
->NumberRedBits
=
934 VideoMode
->NumberGreenBits
=
935 VideoMode
->NumberBlueBits
= 6;
937 VideoMode
->GreenMask
=
938 VideoMode
->BlueMask
= 0;
940 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
941 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
942 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
943 VIDEO_MODE_NO_OFF_SCREEN
;
944 if (VideoMode
->BitsPerPlane
<= 8)
945 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
946 VideoMode
->DriverSpecificAttributeFlags
= 0;
952 * Returns information about each video mode supported by the adapter.
957 PVBE_DEVICE_EXTENSION DeviceExtension
,
958 PVIDEO_MODE_INFORMATION ReturnedModes
,
959 PSTATUS_BLOCK StatusBlock
)
962 PVIDEO_MODE_INFORMATION CurrentMode
;
963 PVBE_MODEINFO CurrentVBEMode
;
965 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
966 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
967 CurrentModeId
< DeviceExtension
->ModeCount
;
968 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
970 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
973 StatusBlock
->Information
=
974 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
980 * VBEQueryCurrentMode
982 * Returns information about current video mode.
987 PVBE_DEVICE_EXTENSION DeviceExtension
,
988 PVIDEO_MODE_INFORMATION VideoModeInfo
,
989 PSTATUS_BLOCK StatusBlock
)
991 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
996 DeviceExtension
->CurrentMode
);
1002 * VBESetColorRegisters
1004 * Sets the adapter's color registers to the specified RGB values. There
1005 * are code paths in this function, one generic and one for VGA compatible
1006 * controllers. The latter is needed for Bochs, where the generic one isn't
1011 VBESetColorRegisters(
1012 PVBE_DEVICE_EXTENSION DeviceExtension
,
1013 PVIDEO_CLUT ColorLookUpTable
,
1014 PSTATUS_BLOCK StatusBlock
)
1016 INT10_BIOS_ARGUMENTS BiosRegisters
;
1019 ULONG OutputBuffer
[256];
1021 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
1025 * For VGA compatible adapters program the color registers directly.
1028 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
1030 for (Entry
= ColorLookUpTable
->FirstEntry
;
1031 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1034 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1035 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1036 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1037 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1045 * We can't just copy the values, because we need to swap the Red
1049 for (Entry
= ColorLookUpTable
->FirstEntry
,
1050 OutputEntry
= OutputBuffer
;
1051 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1052 Entry
++, OutputEntry
++)
1055 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1056 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1057 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1060 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1061 DeviceExtension
->Int10Interface
.Context
,
1062 DeviceExtension
->TrampolineMemorySegment
,
1063 DeviceExtension
->TrampolineMemoryOffset
,
1065 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1067 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1068 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1069 BiosRegisters
.Ebx
= 0;
1070 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1071 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1072 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1073 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1074 DeviceExtension
->Int10Interface
.Int10CallBios(
1075 DeviceExtension
->Int10Interface
.Context
,
1078 return BiosRegisters
.Eax
== VBE_SUCCESS
;