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 DPRINT("VBE BIOS Present (%d.%d, %8ld Kb)\n",
245 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
246 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF,
247 VBEDeviceExtension
->VbeInfo
.TotalMemory
* 16);
250 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x102)
252 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x200)
255 DPRINT("VBE BIOS present, but incompatible version.\n");
261 DPRINT("No VBE BIOS found.\n");
266 * Build a mode list here that can be later used by
267 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
272 * Get the number of supported video modes.
274 * No need to be map the memory. It's either in the video BIOS memory or
275 * in our trampoline memory. In either case the memory is already mapped.
278 for (ModeCount
= 0; ; ModeCount
++)
280 /* Read the VBE mode number. */
281 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
282 VBEDeviceExtension
->Int10Interface
.Context
,
283 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
284 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
289 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
294 * Allocate space for video modes information.
297 VBEDeviceExtension
->ModeInfo
=
298 ExAllocatePool(PagedPool
, ModeCount
* sizeof(VBE_MODEINFO
));
299 VBEDeviceExtension
->ModeNumbers
=
300 ExAllocatePool(PagedPool
, ModeCount
* sizeof(WORD
));
303 * Get the actual mode infos.
306 for (CurrentMode
= 0, SuitableModeCount
= 0;
307 CurrentMode
< ModeCount
;
310 /* Read the VBE mode number. */
311 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
312 VBEDeviceExtension
->Int10Interface
.Context
,
313 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
314 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
318 /* Call VBE BIOS to read the mode info. */
319 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
320 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
321 BiosRegisters
.Ecx
= ModeTemp
;
322 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
323 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
324 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
325 VBEDeviceExtension
->Int10Interface
.Context
,
328 /* Read the VBE mode info. */
329 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
330 VBEDeviceExtension
->Int10Interface
.Context
,
331 VBEDeviceExtension
->TrampolineMemorySegment
,
332 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
333 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
334 sizeof(VBE_MODEINFO
));
336 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
338 /* Is this mode acceptable? */
339 if (BiosRegisters
.Eax
== VBE_SUCCESS
&&
340 VbeModeInfo
->XResolution
>= 640 &&
341 VbeModeInfo
->YResolution
>= 480 &&
342 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
343 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
))
345 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
347 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
353 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
360 if (SuitableModeCount
== 0)
362 DPRINT("VBEMP: No video modes supported\n");
366 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
369 * Sort the video mode list according to resolution and bits per pixel.
372 VBESortModes(VBEDeviceExtension
);
375 * Print the supported video modes when DBG is set.
378 #if defined(DBG) && ! defined(NDEBUG)
379 for (CurrentMode
= 0;
380 CurrentMode
< SuitableModeCount
;
384 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
385 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
386 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
396 * Processes the specified Video Request Packet.
401 PVOID HwDeviceExtension
,
402 PVIDEO_REQUEST_PACKET RequestPacket
)
406 RequestPacket
->StatusBlock
->Status
= STATUS_UNSUCCESSFUL
;
408 switch (RequestPacket
->IoControlCode
)
410 case IOCTL_VIDEO_SET_CURRENT_MODE
:
411 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
413 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
416 Result
= VBESetCurrentMode(
417 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
418 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
419 RequestPacket
->StatusBlock
);
422 case IOCTL_VIDEO_RESET_DEVICE
:
423 Result
= VBEResetDevice(
424 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
425 RequestPacket
->StatusBlock
);
428 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
429 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
430 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
432 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
435 Result
= VBEMapVideoMemory(
436 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
437 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
438 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
439 RequestPacket
->StatusBlock
);
442 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
443 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
445 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
448 Result
= VBEUnmapVideoMemory(
449 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
450 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
451 RequestPacket
->StatusBlock
);
454 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
455 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
457 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
460 Result
= VBEQueryNumAvailModes(
461 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
462 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
463 RequestPacket
->StatusBlock
);
466 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
467 if (RequestPacket
->OutputBufferLength
<
468 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
470 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
473 Result
= VBEQueryAvailModes(
474 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
475 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
476 RequestPacket
->StatusBlock
);
479 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
480 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
481 RequestPacket
->InputBufferLength
<
482 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
485 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
488 Result
= VBESetColorRegisters(
489 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
490 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
491 RequestPacket
->StatusBlock
);
494 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
495 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
497 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
500 Result
= VBEQueryCurrentMode(
501 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
502 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
503 RequestPacket
->StatusBlock
);
507 RequestPacket
->StatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
512 RequestPacket
->StatusBlock
->Status
= STATUS_SUCCESS
;
520 * This function is called to reset the hardware to a known state.
525 PVOID DeviceExtension
,
529 INT10_BIOS_ARGUMENTS BiosRegisters
;
530 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
531 (PVBE_DEVICE_EXTENSION
)DeviceExtension
;
533 if (!VBEResetDevice(DeviceExtension
, NULL
))
536 /* Change number of columns/rows */
537 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
539 if (Columns
== 80 && Rows
== 25)
541 /* Default text size, don't change anything. */
544 else if (Columns
== 80 && Rows
== 28)
546 /* Use 9x14 font (80x28) */
547 BiosRegisters
.Eax
= 0x1111;
549 else if (Columns
== 80 && Rows
== 43)
551 /* Use 8x8 font in 350 scans mode (80x43) */
552 BiosRegisters
.Eax
= 0x1201;
553 BiosRegisters
.Ebx
= 0x30;
554 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
555 VBEDeviceExtension
->Int10Interface
.Context
,
558 BiosRegisters
.Eax
= 0x3;
559 BiosRegisters
.Ebx
= 0;
560 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
561 VBEDeviceExtension
->Int10Interface
.Context
,
564 BiosRegisters
.Eax
= 0x1112;
566 else if (Columns
== 80 && Rows
== 50)
568 /* Use 8x8 font (80x50) */
569 BiosRegisters
.Eax
= 0x1112;
574 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
575 VBEDeviceExtension
->Int10Interface
.Context
,
584 * Queries whether the device can support the requested power state.
589 PVOID HwDeviceExtension
,
591 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
593 INT10_BIOS_ARGUMENTS BiosRegisters
;
594 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
595 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
597 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
598 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
599 return ERROR_INVALID_FUNCTION
;
602 * Get general power support information.
605 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
606 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
607 BiosRegisters
.Ebx
= 0;
608 BiosRegisters
.Edi
= 0;
609 BiosRegisters
.SegEs
= 0;
610 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
611 VBEDeviceExtension
->Int10Interface
.Context
,
614 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
615 return ERROR_NOT_SUPPORTED
;
616 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
617 return ERROR_INVALID_FUNCTION
;
620 * Get current power state.
623 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
624 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
625 BiosRegisters
.Ebx
= 0x2;
626 BiosRegisters
.Edi
= 0;
627 BiosRegisters
.SegEs
= 0;
628 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
629 VBEDeviceExtension
->Int10Interface
.Context
,
632 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
634 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
635 switch (BiosRegisters
.Ebx
>> 8)
637 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
638 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
639 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
640 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
641 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
642 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
648 return ERROR_NOT_SUPPORTED
;
654 * Sets the power state of the specified device
659 PVOID HwDeviceExtension
,
661 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
663 INT10_BIOS_ARGUMENTS BiosRegisters
;
664 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
665 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
667 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
668 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
669 VideoPowerControl
->PowerState
< VideoPowerOn
||
670 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
671 return ERROR_INVALID_FUNCTION
;
673 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
677 * Set current power state.
680 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
681 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
682 BiosRegisters
.Ebx
= 1;
683 BiosRegisters
.Edi
= 0;
684 BiosRegisters
.SegEs
= 0;
685 switch (VideoPowerControl
->PowerState
)
687 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
688 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
689 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
692 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
693 VBEDeviceExtension
->Int10Interface
.Context
,
696 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
697 return ERROR_NOT_SUPPORTED
;
698 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
699 return ERROR_INVALID_FUNCTION
;
707 * Sets the adapter to the specified operating mode.
712 PVBE_DEVICE_EXTENSION DeviceExtension
,
713 PVIDEO_MODE RequestedMode
,
714 PSTATUS_BLOCK StatusBlock
)
716 INT10_BIOS_ARGUMENTS BiosRegisters
;
718 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
720 return ERROR_INVALID_PARAMETER
;
723 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
724 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
725 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
726 DeviceExtension
->Int10Interface
.Int10CallBios(
727 DeviceExtension
->Int10Interface
.Context
,
730 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
732 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
736 DPRINT1("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
737 DeviceExtension
->CurrentMode
= -1;
740 return BiosRegisters
.Eax
== VBE_SUCCESS
;
746 * Resets the video hardware to the default mode, to which it was initialized
752 PVBE_DEVICE_EXTENSION DeviceExtension
,
753 PSTATUS_BLOCK StatusBlock
)
755 INT10_BIOS_ARGUMENTS BiosRegisters
;
757 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
758 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
759 BiosRegisters
.Ebx
= 0x3;
760 DeviceExtension
->Int10Interface
.Int10CallBios(
761 DeviceExtension
->Int10Interface
.Context
,
764 return BiosRegisters
.Eax
== VBE_SUCCESS
;
770 * Maps the video hardware frame buffer and video RAM into the virtual address
771 * space of the requestor.
776 PVBE_DEVICE_EXTENSION DeviceExtension
,
777 PVIDEO_MEMORY RequestedAddress
,
778 PVIDEO_MEMORY_INFORMATION MapInformation
,
779 PSTATUS_BLOCK StatusBlock
)
781 PHYSICAL_ADDRESS FrameBuffer
;
782 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
784 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
786 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
789 FrameBuffer
.QuadPart
=
790 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
791 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
792 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
794 MapInformation
->VideoRamLength
=
795 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
796 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
800 MapInformation
->VideoRamLength
=
801 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
802 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
808 FrameBuffer
.QuadPart
= 0xA0000;
809 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
810 MapInformation
->VideoRamLength
= 0x10000;
814 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
815 &MapInformation
->VideoRamLength
, &inIoSpace
,
816 &MapInformation
->VideoRamBase
);
818 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
819 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
825 * VBEUnmapVideoMemory
827 * Releases a mapping between the virtual address space and the adapter's
828 * frame buffer and video RAM.
833 PVBE_DEVICE_EXTENSION DeviceExtension
,
834 PVIDEO_MEMORY VideoMemory
,
835 PSTATUS_BLOCK StatusBlock
)
837 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
843 * VBEQueryNumAvailModes
845 * Returns the number of video modes supported by the adapter and the size
846 * in bytes of the video mode information, which can be used to allocate a
847 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
851 VBEQueryNumAvailModes(
852 PVBE_DEVICE_EXTENSION DeviceExtension
,
853 PVIDEO_NUM_MODES Modes
,
854 PSTATUS_BLOCK StatusBlock
)
856 Modes
->NumModes
= DeviceExtension
->ModeCount
;
857 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
858 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
865 * Returns information about one particular video mode.
870 PVBE_DEVICE_EXTENSION DeviceExtension
,
871 PVIDEO_MODE_INFORMATION VideoMode
,
874 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
876 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
877 VideoMode
->ModeIndex
= VideoModeId
;
878 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
879 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
880 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
881 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
883 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
884 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
885 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
886 VideoMode
->Frequency
= 1;
887 VideoMode
->XMillimeter
= 0; /* FIXME */
888 VideoMode
->YMillimeter
= 0; /* FIXME */
889 if (VBEMode
->BitsPerPixel
> 8)
892 * Always report 16bpp modes and not 15bpp mode...
894 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
896 VideoMode
->BitsPerPlane
= 16;
899 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
901 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
902 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
903 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
904 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
905 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
906 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
910 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
911 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
912 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
913 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
914 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
915 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
920 VideoMode
->NumberRedBits
=
921 VideoMode
->NumberGreenBits
=
922 VideoMode
->NumberBlueBits
= 6;
924 VideoMode
->GreenMask
=
925 VideoMode
->BlueMask
= 0;
927 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
928 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
929 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
930 VIDEO_MODE_NO_OFF_SCREEN
;
931 if (VideoMode
->BitsPerPlane
<= 8)
932 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
933 VideoMode
->DriverSpecificAttributeFlags
= 0;
939 * Returns information about each video mode supported by the adapter.
944 PVBE_DEVICE_EXTENSION DeviceExtension
,
945 PVIDEO_MODE_INFORMATION ReturnedModes
,
946 PSTATUS_BLOCK StatusBlock
)
949 PVIDEO_MODE_INFORMATION CurrentMode
;
950 PVBE_MODEINFO CurrentVBEMode
;
952 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
953 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
954 CurrentModeId
< DeviceExtension
->ModeCount
;
955 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
957 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
960 StatusBlock
->Information
=
961 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
967 * VBEQueryCurrentMode
969 * Returns information about current video mode.
974 PVBE_DEVICE_EXTENSION DeviceExtension
,
975 PVIDEO_MODE_INFORMATION VideoModeInfo
,
976 PSTATUS_BLOCK StatusBlock
)
978 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
983 DeviceExtension
->CurrentMode
);
989 * VBESetColorRegisters
991 * Sets the adapter's color registers to the specified RGB values. There
992 * are code paths in this function, one generic and one for VGA compatible
993 * controllers. The latter is needed for Bochs, where the generic one isn't
998 VBESetColorRegisters(
999 PVBE_DEVICE_EXTENSION DeviceExtension
,
1000 PVIDEO_CLUT ColorLookUpTable
,
1001 PSTATUS_BLOCK StatusBlock
)
1003 INT10_BIOS_ARGUMENTS BiosRegisters
;
1006 ULONG OutputBuffer
[256];
1008 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
1012 * For VGA compatible adapters program the color registers directly.
1015 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
1017 for (Entry
= ColorLookUpTable
->FirstEntry
;
1018 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1021 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1022 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1023 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1024 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1032 * We can't just copy the values, because we need to swap the Red
1036 for (Entry
= ColorLookUpTable
->FirstEntry
,
1037 OutputEntry
= OutputBuffer
;
1038 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1039 Entry
++, OutputEntry
++)
1042 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1043 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1044 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1047 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1048 DeviceExtension
->Int10Interface
.Context
,
1049 DeviceExtension
->TrampolineMemorySegment
,
1050 DeviceExtension
->TrampolineMemoryOffset
,
1052 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1054 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1055 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1056 BiosRegisters
.Ebx
= 0;
1057 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1058 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1059 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1060 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1061 DeviceExtension
->Int10Interface
.Int10CallBios(
1062 DeviceExtension
->Int10Interface
.Context
,
1065 return BiosRegisters
.Eax
== VBE_SUCCESS
;