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 along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 * - Check input parameters everywhere.
24 * - Call VideoPortVerifyAccessRanges to reserve the memory we're about
28 /* INCLUDES *******************************************************************/
34 #define LOWORD(l) ((USHORT)((ULONG_PTR)(l)))
35 #define HIWORD(l) ((USHORT)(((ULONG_PTR)(l)>>16)&0xFFFF))
37 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
40 DriverEntry(IN PVOID Context1
, IN PVOID Context2
)
42 VIDEO_HW_INITIALIZATION_DATA InitData
;
44 VideoPortZeroMemory(&InitData
, sizeof(InitData
));
45 InitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
46 InitData
.HwFindAdapter
= VBEFindAdapter
;
47 InitData
.HwInitialize
= VBEInitialize
;
48 InitData
.HwStartIO
= VBEStartIO
;
49 InitData
.HwResetHw
= VBEResetHw
;
50 //InitData.HwGetPowerState = VBEGetPowerState;
51 //InitData.HwSetPowerState = VBESetPowerState;
52 //InitData.HwGetVideoChildDescriptor = VBEGetVideoChildDescriptor;
53 InitData
.HwDeviceExtensionSize
= sizeof(VBE_DEVICE_EXTENSION
);
55 return VideoPortInitialize(Context1
, Context2
, &InitData
, NULL
);
61 * Should detect a VBE compatible display adapter, but it's not possible
62 * to use video port Int 10 services at this time during initialization,
63 * so we always return NO_ERROR and do the real work in VBEInitialize.
68 IN PVOID HwDeviceExtension
,
70 IN PWSTR ArgumentString
,
71 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
74 if (VideoPortIsNoVesa())
75 return ERROR_DEV_NOT_EXIST
;
81 * VBESortModesCallback
83 * Helper function for sorting video mode list.
87 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA
, PVBE_MODEINFO VbeModeInfoB
)
89 VideoPortDebugPrint(Info
, "VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
90 VbeModeInfoA
->XResolution
, VbeModeInfoA
->YResolution
,
91 VbeModeInfoA
->BitsPerPixel
,
92 VbeModeInfoB
->XResolution
, VbeModeInfoB
->YResolution
,
93 VbeModeInfoB
->BitsPerPixel
);
96 * FIXME: Until some reasonable method for changing video modes will
97 * be available we favor more bits per pixel. It should be changed
100 if (VbeModeInfoA
->BitsPerPixel
< VbeModeInfoB
->BitsPerPixel
) return -1;
101 if (VbeModeInfoA
->BitsPerPixel
> VbeModeInfoB
->BitsPerPixel
) return 1;
102 if (VbeModeInfoA
->XResolution
< VbeModeInfoB
->XResolution
) return -1;
103 if (VbeModeInfoA
->XResolution
> VbeModeInfoB
->XResolution
) return 1;
104 if (VbeModeInfoA
->YResolution
< VbeModeInfoB
->YResolution
) return -1;
105 if (VbeModeInfoA
->YResolution
> VbeModeInfoB
->YResolution
) return 1;
112 * Simple function for sorting the video mode list. Uses bubble sort.
116 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension
)
118 BOOLEAN Finished
= FALSE
;
121 VBE_MODEINFO TempModeInfo
;
122 USHORT TempModeNumber
;
127 for (Pos
= 0; Pos
< DeviceExtension
->ModeCount
- 1; Pos
++)
129 Result
= VBESortModesCallback(
130 DeviceExtension
->ModeInfo
+ Pos
,
131 DeviceExtension
->ModeInfo
+ Pos
+ 1);
138 DeviceExtension
->ModeInfo
+ Pos
,
139 sizeof(VBE_MODEINFO
));
140 TempModeNumber
= DeviceExtension
->ModeNumbers
[Pos
];
143 DeviceExtension
->ModeInfo
+ Pos
,
144 DeviceExtension
->ModeInfo
+ Pos
+ 1,
145 sizeof(VBE_MODEINFO
));
146 DeviceExtension
->ModeNumbers
[Pos
] =
147 DeviceExtension
->ModeNumbers
[Pos
+ 1];
150 DeviceExtension
->ModeInfo
+ Pos
+ 1,
152 sizeof(VBE_MODEINFO
));
153 DeviceExtension
->ModeNumbers
[Pos
+ 1] = TempModeNumber
;
162 * Performs the first initialization of the adapter, after the HAL has given
163 * up control of the video hardware to the video port driver.
165 * This function performs these steps:
166 * - Gets global VBE information and finds if VBE BIOS is present.
167 * - Builds the internal mode list using the list of modes provided by
172 VBEInitialize(PVOID HwDeviceExtension
)
174 INT10_BIOS_ARGUMENTS BiosRegisters
;
176 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
177 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
180 ULONG SuitableModeCount
;
183 PVBE_MODEINFO VbeModeInfo
;
186 * Get the Int 10 interface that we will use for allocating real
187 * mode memory and calling the video BIOS.
190 VBEDeviceExtension
->Int10Interface
.Version
= VIDEO_PORT_INT10_INTERFACE_VERSION_1
;
191 VBEDeviceExtension
->Int10Interface
.Size
= sizeof(VIDEO_PORT_INT10_INTERFACE
);
192 Status
= VideoPortQueryServices(
194 VideoPortServicesInt10
,
195 (PINTERFACE
)&VBEDeviceExtension
->Int10Interface
);
197 if (Status
!= NO_ERROR
)
199 VideoPortDebugPrint(Error
, "Failed to get Int 10 service functions (Status %x)\n", Status
);
204 * Allocate a bit of memory that will be later used for VBE transport
205 * buffer. This memory must be accessible from V86 mode so it must fit
206 * in the first megabyte of physical memory.
210 Status
= VBEDeviceExtension
->Int10Interface
.Int10AllocateBuffer(
211 VBEDeviceExtension
->Int10Interface
.Context
,
212 &VBEDeviceExtension
->TrampolineMemorySegment
,
213 &VBEDeviceExtension
->TrampolineMemoryOffset
,
216 if (Status
!= NO_ERROR
)
218 VideoPortDebugPrint(Error
, "Failed to allocate virtual memory (Status %x)\n", Status
);
223 * Get the VBE general information.
226 VBEDeviceExtension
->Int10Interface
.Int10WriteMemory(
227 VBEDeviceExtension
->Int10Interface
.Context
,
228 VBEDeviceExtension
->TrampolineMemorySegment
,
229 VBEDeviceExtension
->TrampolineMemoryOffset
,
233 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
234 BiosRegisters
.Eax
= VBE_GET_CONTROLLER_INFORMATION
;
235 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
;
236 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
237 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
238 VBEDeviceExtension
->Int10Interface
.Context
,
241 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
243 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
244 VBEDeviceExtension
->Int10Interface
.Context
,
245 VBEDeviceExtension
->TrampolineMemorySegment
,
246 VBEDeviceExtension
->TrampolineMemoryOffset
,
247 &VBEDeviceExtension
->VbeInfo
,
248 sizeof(VBEDeviceExtension
->VbeInfo
));
250 /* Verify the VBE signature. */
251 if (VideoPortCompareMemory(VBEDeviceExtension
->VbeInfo
.Signature
, "VESA", 4) != 4)
253 VideoPortDebugPrint(Warn
, "No VBE BIOS present\n");
257 VideoPortDebugPrint(Trace
, "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 VideoPortDebugPrint(Warn
, "VBE BIOS present, but incompatible version.\n");
274 VideoPortDebugPrint(Warn
, "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 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(VBE_MODEINFO
), TAG_VBE
);
312 VBEDeviceExtension
->ModeNumbers
=
313 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(USHORT
), TAG_VBE
);
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 (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
&&
353 VbeModeInfo
->XResolution
>= 640 &&
354 VbeModeInfo
->YResolution
>= 480 &&
355 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
356 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
) &&
357 VbeModeInfo
->PhysBasePtr
!= 0)
359 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
361 /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */
362 // if (ModeTemp & 0x4000)
364 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
371 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
379 if (SuitableModeCount
== 0)
382 VideoPortDebugPrint(Warn
, "VBEMP: No video modes supported\n");
386 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
389 * Sort the video mode list according to resolution and bits per pixel.
392 VBESortModes(VBEDeviceExtension
);
395 * Print the supported video modes.
398 for (CurrentMode
= 0;
399 CurrentMode
< SuitableModeCount
;
402 VideoPortDebugPrint(Trace
, "%dx%dx%d\n",
403 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
404 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
405 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
409 * Enumerate our children.
411 VideoPortEnumerateChildren(HwDeviceExtension
, NULL
);
419 * Processes the specified Video Request Packet.
424 PVOID HwDeviceExtension
,
425 PVIDEO_REQUEST_PACKET RequestPacket
)
429 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
431 switch (RequestPacket
->IoControlCode
)
433 case IOCTL_VIDEO_SET_CURRENT_MODE
:
434 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
436 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
439 Result
= VBESetCurrentMode(
440 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
441 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
442 RequestPacket
->StatusBlock
);
445 case IOCTL_VIDEO_RESET_DEVICE
:
446 Result
= VBEResetDevice(
447 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
448 RequestPacket
->StatusBlock
);
451 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
452 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
453 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
455 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
458 Result
= VBEMapVideoMemory(
459 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
460 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
461 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
462 RequestPacket
->StatusBlock
);
465 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
466 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
468 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
471 Result
= VBEUnmapVideoMemory(
472 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
473 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
474 RequestPacket
->StatusBlock
);
477 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
478 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
480 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
483 Result
= VBEQueryNumAvailModes(
484 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
485 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
486 RequestPacket
->StatusBlock
);
489 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
490 if (RequestPacket
->OutputBufferLength
<
491 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
493 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
496 Result
= VBEQueryAvailModes(
497 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
498 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
499 RequestPacket
->StatusBlock
);
502 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
503 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
504 RequestPacket
->InputBufferLength
<
505 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
506 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
508 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
511 Result
= VBESetColorRegisters(
512 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
513 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
514 RequestPacket
->StatusBlock
);
517 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
518 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
520 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
523 Result
= VBEQueryCurrentMode(
524 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
525 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
526 RequestPacket
->StatusBlock
);
530 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
535 RequestPacket
->StatusBlock
->Status
= NO_ERROR
;
543 * This function is called to reset the hardware to a known state.
548 PVOID DeviceExtension
,
552 /* Return FALSE to let HAL reset the display with INT10 */
559 * Queries whether the device can support the requested power state.
564 PVOID HwDeviceExtension
,
566 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
568 INT10_BIOS_ARGUMENTS BiosRegisters
;
569 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
570 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
572 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
573 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
574 return ERROR_INVALID_FUNCTION
;
577 * Get general power support information.
580 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
581 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
582 BiosRegisters
.Ebx
= 0;
583 BiosRegisters
.Edi
= 0;
584 BiosRegisters
.SegEs
= 0;
585 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
586 VBEDeviceExtension
->Int10Interface
.Context
,
589 if ( VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
590 return ERROR_DEV_NOT_EXIST
;
591 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
592 return ERROR_INVALID_FUNCTION
;
595 * Get current power state.
598 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
599 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
600 BiosRegisters
.Ebx
= 0x2;
601 BiosRegisters
.Edi
= 0;
602 BiosRegisters
.SegEs
= 0;
603 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
604 VBEDeviceExtension
->Int10Interface
.Context
,
607 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
609 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
610 switch (BiosRegisters
.Ebx
>> 8)
612 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
613 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
614 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
615 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
616 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
617 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
623 return ERROR_DEV_NOT_EXIST
;
629 * Sets the power state of the specified device
634 PVOID HwDeviceExtension
,
636 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
638 INT10_BIOS_ARGUMENTS BiosRegisters
;
639 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
640 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
642 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
643 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
644 VideoPowerControl
->PowerState
< VideoPowerOn
||
645 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
646 return ERROR_INVALID_FUNCTION
;
648 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
652 * Set current power state.
655 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
656 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
657 BiosRegisters
.Ebx
= 1;
658 BiosRegisters
.Edi
= 0;
659 BiosRegisters
.SegEs
= 0;
660 switch (VideoPowerControl
->PowerState
)
662 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
663 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
664 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
667 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
668 VBEDeviceExtension
->Int10Interface
.Context
,
671 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
672 return ERROR_DEV_NOT_EXIST
;
673 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
674 return ERROR_INVALID_FUNCTION
;
682 * Sets the adapter to the specified operating mode.
687 PVBE_DEVICE_EXTENSION DeviceExtension
,
688 PVIDEO_MODE RequestedMode
,
689 PSTATUS_BLOCK StatusBlock
)
691 INT10_BIOS_ARGUMENTS BiosRegisters
;
693 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
695 return ERROR_INVALID_PARAMETER
;
698 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
699 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
700 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
701 DeviceExtension
->Int10Interface
.Int10CallBios(
702 DeviceExtension
->Int10Interface
.Context
,
705 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
707 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
711 VideoPortDebugPrint(Error
, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
712 DeviceExtension
->CurrentMode
= -1;
715 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
721 * Resets the video hardware to the default mode, to which it was initialized
727 PVBE_DEVICE_EXTENSION DeviceExtension
,
728 PSTATUS_BLOCK StatusBlock
)
730 INT10_BIOS_ARGUMENTS BiosRegisters
;
732 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
733 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
734 BiosRegisters
.Ebx
= 0x3;
735 DeviceExtension
->Int10Interface
.Int10CallBios(
736 DeviceExtension
->Int10Interface
.Context
,
739 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
745 * Maps the video hardware frame buffer and video RAM into the virtual address
746 * space of the requestor.
751 PVBE_DEVICE_EXTENSION DeviceExtension
,
752 PVIDEO_MEMORY RequestedAddress
,
753 PVIDEO_MEMORY_INFORMATION MapInformation
,
754 PSTATUS_BLOCK StatusBlock
)
756 PHYSICAL_ADDRESS FrameBuffer
;
757 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
759 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
761 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
764 FrameBuffer
.QuadPart
=
765 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
766 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
767 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
769 MapInformation
->VideoRamLength
=
770 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
771 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
775 MapInformation
->VideoRamLength
=
776 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
777 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
783 FrameBuffer
.QuadPart
= 0xA0000;
784 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
785 MapInformation
->VideoRamLength
= 0x10000;
789 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
790 &MapInformation
->VideoRamLength
, &inIoSpace
,
791 &MapInformation
->VideoRamBase
);
793 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
794 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
800 * VBEUnmapVideoMemory
802 * Releases a mapping between the virtual address space and the adapter's
803 * frame buffer and video RAM.
808 PVBE_DEVICE_EXTENSION DeviceExtension
,
809 PVIDEO_MEMORY VideoMemory
,
810 PSTATUS_BLOCK StatusBlock
)
812 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
818 * VBEQueryNumAvailModes
820 * Returns the number of video modes supported by the adapter and the size
821 * in bytes of the video mode information, which can be used to allocate a
822 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
826 VBEQueryNumAvailModes(
827 PVBE_DEVICE_EXTENSION DeviceExtension
,
828 PVIDEO_NUM_MODES Modes
,
829 PSTATUS_BLOCK StatusBlock
)
831 Modes
->NumModes
= DeviceExtension
->ModeCount
;
832 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
833 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
840 * Returns information about one particular video mode.
845 PVBE_DEVICE_EXTENSION DeviceExtension
,
846 PVIDEO_MODE_INFORMATION VideoMode
,
849 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
852 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
853 VideoMode
->ModeIndex
= VideoModeId
;
854 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
855 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
856 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
857 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
859 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
860 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
861 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
862 VideoMode
->Frequency
= 1;
864 /* Assume 96DPI and 25.4 millimeters per inch, round to nearest */
866 VideoMode
->XMillimeter
= ((ULONGLONG
)VBEMode
->XResolution
* 254 + (dpi
* 5)) / (dpi
* 10);
867 VideoMode
->YMillimeter
= ((ULONGLONG
)VBEMode
->YResolution
* 254 + (dpi
* 5)) / (dpi
* 10);
869 if (VBEMode
->BitsPerPixel
> 8)
872 * Always report 16bpp modes and not 15bpp mode...
874 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
876 VideoMode
->BitsPerPlane
= 16;
879 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
881 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
882 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
883 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
884 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
885 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
886 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
890 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
891 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
892 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
893 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
894 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
895 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
900 VideoMode
->NumberRedBits
=
901 VideoMode
->NumberGreenBits
=
902 VideoMode
->NumberBlueBits
= 6;
904 VideoMode
->GreenMask
=
905 VideoMode
->BlueMask
= 0;
907 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
908 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
909 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
910 VIDEO_MODE_NO_OFF_SCREEN
;
911 if (VideoMode
->BitsPerPlane
<= 8)
912 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
913 VideoMode
->DriverSpecificAttributeFlags
= 0;
919 * Returns information about each video mode supported by the adapter.
924 PVBE_DEVICE_EXTENSION DeviceExtension
,
925 PVIDEO_MODE_INFORMATION ReturnedModes
,
926 PSTATUS_BLOCK StatusBlock
)
929 PVIDEO_MODE_INFORMATION CurrentMode
;
930 PVBE_MODEINFO CurrentVBEMode
;
932 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
933 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
934 CurrentModeId
< DeviceExtension
->ModeCount
;
935 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
937 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
940 StatusBlock
->Information
=
941 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
947 * VBEQueryCurrentMode
949 * Returns information about current video mode.
954 PVBE_DEVICE_EXTENSION DeviceExtension
,
955 PVIDEO_MODE_INFORMATION VideoModeInfo
,
956 PSTATUS_BLOCK StatusBlock
)
958 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
963 DeviceExtension
->CurrentMode
);
969 * VBESetColorRegisters
971 * Sets the adapter's color registers to the specified RGB values. There
972 * are code paths in this function, one generic and one for VGA compatible
973 * controllers. The latter is needed for Bochs, where the generic one isn't
978 VBESetColorRegisters(
979 PVBE_DEVICE_EXTENSION DeviceExtension
,
980 PVIDEO_CLUT ColorLookUpTable
,
981 PSTATUS_BLOCK StatusBlock
)
983 INT10_BIOS_ARGUMENTS BiosRegisters
;
986 ULONG OutputBuffer
[256];
988 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
992 * For VGA compatible adapters program the color registers directly.
995 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
997 for (Entry
= ColorLookUpTable
->FirstEntry
;
998 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1001 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1002 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1003 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1004 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1012 * We can't just copy the values, because we need to swap the Red
1016 for (Entry
= ColorLookUpTable
->FirstEntry
,
1017 OutputEntry
= OutputBuffer
;
1018 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1019 Entry
++, OutputEntry
++)
1022 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1023 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1024 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1027 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1028 DeviceExtension
->Int10Interface
.Context
,
1029 DeviceExtension
->TrampolineMemorySegment
,
1030 DeviceExtension
->TrampolineMemoryOffset
,
1032 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1034 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1035 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1036 BiosRegisters
.Ebx
= 0;
1037 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1038 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1039 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1040 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1041 DeviceExtension
->Int10Interface
.Int10CallBios(
1042 DeviceExtension
->Int10Interface
.Context
,
1045 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;