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 *******************************************************************/
36 #define LOWORD(l) ((USHORT)((ULONG_PTR)(l)))
37 #define HIWORD(l) ((USHORT)(((ULONG_PTR)(l)>>16)&0xFFFF))
39 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
42 DriverEntry(IN PVOID Context1
, IN PVOID Context2
)
44 VIDEO_HW_INITIALIZATION_DATA InitData
;
46 VideoPortZeroMemory(&InitData
, sizeof(InitData
));
47 InitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
48 InitData
.HwFindAdapter
= VBEFindAdapter
;
49 InitData
.HwInitialize
= VBEInitialize
;
50 InitData
.HwStartIO
= VBEStartIO
;
51 InitData
.HwResetHw
= VBEResetHw
;
52 InitData
.HwGetPowerState
= VBEGetPowerState
;
53 InitData
.HwSetPowerState
= VBESetPowerState
;
54 InitData
.HwGetVideoChildDescriptor
= VBEGetVideoChildDescriptor
;
55 InitData
.HwDeviceExtensionSize
= sizeof(VBE_DEVICE_EXTENSION
);
57 return VideoPortInitialize(Context1
, Context2
, &InitData
, NULL
);
63 * Should detect a VBE compatible display adapter, but it's not possible
64 * to use video port Int 10 services at this time during initialization,
65 * so we always return NO_ERROR and do the real work in VBEInitialize.
70 IN PVOID HwDeviceExtension
,
72 IN PWSTR ArgumentString
,
73 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
76 if (VideoPortIsNoVesa())
77 return ERROR_DEV_NOT_EXIST
;
83 * VBESortModesCallback
85 * Helper function for sorting video mode list.
89 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA
, PVBE_MODEINFO VbeModeInfoB
)
91 VideoPortDebugPrint(Info
, "VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
92 VbeModeInfoA
->XResolution
, VbeModeInfoA
->YResolution
,
93 VbeModeInfoA
->BitsPerPixel
,
94 VbeModeInfoB
->XResolution
, VbeModeInfoB
->YResolution
,
95 VbeModeInfoB
->BitsPerPixel
);
98 * FIXME: Until some reasonable method for changing video modes will
99 * be available we favor more bits per pixel. It should be changed
102 if (VbeModeInfoA
->BitsPerPixel
< VbeModeInfoB
->BitsPerPixel
) return -1;
103 if (VbeModeInfoA
->BitsPerPixel
> VbeModeInfoB
->BitsPerPixel
) return 1;
104 if (VbeModeInfoA
->XResolution
< VbeModeInfoB
->XResolution
) return -1;
105 if (VbeModeInfoA
->XResolution
> VbeModeInfoB
->XResolution
) return 1;
106 if (VbeModeInfoA
->YResolution
< VbeModeInfoB
->YResolution
) return -1;
107 if (VbeModeInfoA
->YResolution
> VbeModeInfoB
->YResolution
) return 1;
114 * Simple function for sorting the video mode list. Uses bubble sort.
118 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension
)
120 BOOLEAN Finished
= FALSE
;
123 VBE_MODEINFO TempModeInfo
;
124 USHORT TempModeNumber
;
129 for (Pos
= 0; Pos
< DeviceExtension
->ModeCount
- 1; Pos
++)
131 Result
= VBESortModesCallback(
132 DeviceExtension
->ModeInfo
+ Pos
,
133 DeviceExtension
->ModeInfo
+ Pos
+ 1);
140 DeviceExtension
->ModeInfo
+ Pos
,
141 sizeof(VBE_MODEINFO
));
142 TempModeNumber
= DeviceExtension
->ModeNumbers
[Pos
];
145 DeviceExtension
->ModeInfo
+ Pos
,
146 DeviceExtension
->ModeInfo
+ Pos
+ 1,
147 sizeof(VBE_MODEINFO
));
148 DeviceExtension
->ModeNumbers
[Pos
] =
149 DeviceExtension
->ModeNumbers
[Pos
+ 1];
152 DeviceExtension
->ModeInfo
+ Pos
+ 1,
154 sizeof(VBE_MODEINFO
));
155 DeviceExtension
->ModeNumbers
[Pos
+ 1] = TempModeNumber
;
164 * Performs the first initialization of the adapter, after the HAL has given
165 * up control of the video hardware to the video port driver.
167 * This function performs these steps:
168 * - Gets global VBE information and finds if VBE BIOS is present.
169 * - Builds the internal mode list using the list of modes provided by
174 VBEInitialize(PVOID HwDeviceExtension
)
176 INT10_BIOS_ARGUMENTS BiosRegisters
;
178 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
179 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
182 ULONG SuitableModeCount
;
185 PVBE_MODEINFO VbeModeInfo
;
188 * Get the Int 10 interface that we will use for allocating real
189 * mode memory and calling the video BIOS.
192 VBEDeviceExtension
->Int10Interface
.Version
= VIDEO_PORT_INT10_INTERFACE_VERSION_1
;
193 VBEDeviceExtension
->Int10Interface
.Size
= sizeof(VIDEO_PORT_INT10_INTERFACE
);
194 Status
= VideoPortQueryServices(
196 VideoPortServicesInt10
,
197 (PINTERFACE
)&VBEDeviceExtension
->Int10Interface
);
199 if (Status
!= NO_ERROR
)
201 VideoPortDebugPrint(Error
, "Failed to get Int 10 service functions (Status %x)\n", Status
);
206 * Allocate a bit of memory that will be later used for VBE transport
207 * buffer. This memory must be accessible from V86 mode so it must fit
208 * in the first megabyte of physical memory.
212 Status
= VBEDeviceExtension
->Int10Interface
.Int10AllocateBuffer(
213 VBEDeviceExtension
->Int10Interface
.Context
,
214 &VBEDeviceExtension
->TrampolineMemorySegment
,
215 &VBEDeviceExtension
->TrampolineMemoryOffset
,
218 if (Status
!= NO_ERROR
)
220 VideoPortDebugPrint(Error
, "Failed to allocate virtual memory (Status %x)\n", Status
);
225 * Get the VBE general information.
228 VBEDeviceExtension
->Int10Interface
.Int10WriteMemory(
229 VBEDeviceExtension
->Int10Interface
.Context
,
230 VBEDeviceExtension
->TrampolineMemorySegment
,
231 VBEDeviceExtension
->TrampolineMemoryOffset
,
235 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
236 BiosRegisters
.Eax
= VBE_GET_CONTROLLER_INFORMATION
;
237 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
;
238 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
239 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
240 VBEDeviceExtension
->Int10Interface
.Context
,
243 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
245 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
246 VBEDeviceExtension
->Int10Interface
.Context
,
247 VBEDeviceExtension
->TrampolineMemorySegment
,
248 VBEDeviceExtension
->TrampolineMemoryOffset
,
249 &VBEDeviceExtension
->VbeInfo
,
250 sizeof(VBEDeviceExtension
->VbeInfo
));
252 /* Verify the VBE signature. */
253 if (VideoPortCompareMemory(VBEDeviceExtension
->VbeInfo
.Signature
, "VESA", 4) != 4)
255 VideoPortDebugPrint(Error
, "No VBE BIOS present\n");
259 VideoPortDebugPrint(Trace
, "VBE BIOS Present (%d.%d, %8ld Kb)\n",
260 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
261 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF,
262 VBEDeviceExtension
->VbeInfo
.TotalMemory
* 64);
265 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x102)
267 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x200)
270 VideoPortDebugPrint(Error
, "VBE BIOS present, but incompatible version %d.%d\n",
271 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
272 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF);
278 VideoPortDebugPrint(Error
, "No VBE BIOS found.\n");
283 * Build a mode list here that can be later used by
284 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
289 * Get the number of supported video modes.
291 * No need to be map the memory. It's either in the video BIOS memory or
292 * in our trampoline memory. In either case the memory is already mapped.
295 for (ModeCount
= 0; ; ModeCount
++)
297 /* Read the VBE mode number. */
298 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
299 VBEDeviceExtension
->Int10Interface
.Context
,
300 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
301 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
306 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
311 * Allocate space for video modes information.
314 VBEDeviceExtension
->ModeInfo
=
315 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(VBE_MODEINFO
), TAG_VBE
);
316 VBEDeviceExtension
->ModeNumbers
=
317 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(USHORT
), TAG_VBE
);
320 * Get the actual mode infos.
323 for (CurrentMode
= 0, SuitableModeCount
= 0;
324 CurrentMode
< ModeCount
;
327 /* Read the VBE mode number. */
328 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
329 VBEDeviceExtension
->Int10Interface
.Context
,
330 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
331 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
335 /* Call VBE BIOS to read the mode info. */
336 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
337 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
338 BiosRegisters
.Ecx
= ModeTemp
;
339 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
340 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
341 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
342 VBEDeviceExtension
->Int10Interface
.Context
,
345 /* Read the VBE mode info. */
346 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
347 VBEDeviceExtension
->Int10Interface
.Context
,
348 VBEDeviceExtension
->TrampolineMemorySegment
,
349 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
350 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
351 sizeof(VBE_MODEINFO
));
353 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
355 /* Is this mode acceptable? */
356 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
&&
357 VbeModeInfo
->XResolution
>= 640 &&
358 VbeModeInfo
->YResolution
>= 480 &&
359 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
360 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
) &&
361 VbeModeInfo
->PhysBasePtr
!= 0)
363 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
365 /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */
366 // if (ModeTemp & 0x4000)
368 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
375 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
383 if (SuitableModeCount
== 0)
386 VideoPortDebugPrint(Warn
, "VBEMP: No video modes supported\n");
390 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
393 * Sort the video mode list according to resolution and bits per pixel.
396 VBESortModes(VBEDeviceExtension
);
399 * Print the supported video modes.
402 for (CurrentMode
= 0;
403 CurrentMode
< SuitableModeCount
;
406 VideoPortDebugPrint(Trace
, "%dx%dx%d\n",
407 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
408 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
409 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
413 * Enumerate our children.
415 VideoPortEnumerateChildren(HwDeviceExtension
, NULL
);
423 * Processes the specified Video Request Packet.
428 PVOID HwDeviceExtension
,
429 PVIDEO_REQUEST_PACKET RequestPacket
)
433 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
435 switch (RequestPacket
->IoControlCode
)
437 case IOCTL_VIDEO_SET_CURRENT_MODE
:
438 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
440 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
443 Result
= VBESetCurrentMode(
444 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
445 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
446 RequestPacket
->StatusBlock
);
449 case IOCTL_VIDEO_RESET_DEVICE
:
450 Result
= VBEResetDevice(
451 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
452 RequestPacket
->StatusBlock
);
455 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
456 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
457 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
459 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
462 Result
= VBEMapVideoMemory(
463 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
464 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
465 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
466 RequestPacket
->StatusBlock
);
469 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
470 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
472 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
475 Result
= VBEUnmapVideoMemory(
476 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
477 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
478 RequestPacket
->StatusBlock
);
481 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
482 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
484 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
487 Result
= VBEQueryNumAvailModes(
488 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
489 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
490 RequestPacket
->StatusBlock
);
493 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
494 if (RequestPacket
->OutputBufferLength
<
495 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
497 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
500 Result
= VBEQueryAvailModes(
501 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
502 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
503 RequestPacket
->StatusBlock
);
506 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
507 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
508 RequestPacket
->InputBufferLength
<
509 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
510 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
512 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
515 Result
= VBESetColorRegisters(
516 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
517 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
518 RequestPacket
->StatusBlock
);
521 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
522 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
524 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
527 Result
= VBEQueryCurrentMode(
528 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
529 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
530 RequestPacket
->StatusBlock
);
534 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
539 RequestPacket
->StatusBlock
->Status
= NO_ERROR
;
547 * This function is called to reset the hardware to a known state.
552 PVOID DeviceExtension
,
556 /* Return FALSE to let HAL reset the display with INT10 */
563 * Queries whether the device can support the requested power state.
568 PVOID HwDeviceExtension
,
570 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
572 INT10_BIOS_ARGUMENTS BiosRegisters
;
573 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
574 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
576 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
577 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
578 return ERROR_INVALID_FUNCTION
;
581 * Get general power support information.
584 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
585 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
586 BiosRegisters
.Ebx
= 0;
587 BiosRegisters
.Edi
= 0;
588 BiosRegisters
.SegEs
= 0;
589 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
590 VBEDeviceExtension
->Int10Interface
.Context
,
593 if ( VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
594 return ERROR_DEV_NOT_EXIST
;
595 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
596 return ERROR_INVALID_FUNCTION
;
599 * Get current power state.
602 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
603 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
604 BiosRegisters
.Ebx
= 0x2;
605 BiosRegisters
.Edi
= 0;
606 BiosRegisters
.SegEs
= 0;
607 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
608 VBEDeviceExtension
->Int10Interface
.Context
,
611 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
613 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
614 switch (BiosRegisters
.Ebx
>> 8)
616 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
617 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
618 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
619 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
620 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
621 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
627 return ERROR_DEV_NOT_EXIST
;
633 * Sets the power state of the specified device
638 PVOID HwDeviceExtension
,
640 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
642 INT10_BIOS_ARGUMENTS BiosRegisters
;
643 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
644 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
646 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
647 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
648 VideoPowerControl
->PowerState
< VideoPowerOn
||
649 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
650 return ERROR_INVALID_FUNCTION
;
652 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
656 * Set current power state.
659 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
660 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
661 BiosRegisters
.Ebx
= 1;
662 BiosRegisters
.Edi
= 0;
663 BiosRegisters
.SegEs
= 0;
664 switch (VideoPowerControl
->PowerState
)
666 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
667 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
668 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
671 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
672 VBEDeviceExtension
->Int10Interface
.Context
,
675 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
676 return ERROR_DEV_NOT_EXIST
;
677 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
678 return ERROR_INVALID_FUNCTION
;
686 * Sets the adapter to the specified operating mode.
691 PVBE_DEVICE_EXTENSION DeviceExtension
,
692 PVIDEO_MODE RequestedMode
,
693 PSTATUS_BLOCK StatusBlock
)
695 INT10_BIOS_ARGUMENTS BiosRegisters
;
697 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
699 return ERROR_INVALID_PARAMETER
;
702 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
703 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
704 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
705 DeviceExtension
->Int10Interface
.Int10CallBios(
706 DeviceExtension
->Int10Interface
.Context
,
709 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
711 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
715 VideoPortDebugPrint(Error
, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
716 DeviceExtension
->CurrentMode
= -1;
719 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
725 * Resets the video hardware to the default mode, to which it was initialized
731 PVBE_DEVICE_EXTENSION DeviceExtension
,
732 PSTATUS_BLOCK StatusBlock
)
734 INT10_BIOS_ARGUMENTS BiosRegisters
;
736 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
737 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
738 BiosRegisters
.Ebx
= 0x3;
739 DeviceExtension
->Int10Interface
.Int10CallBios(
740 DeviceExtension
->Int10Interface
.Context
,
743 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
749 * Maps the video hardware frame buffer and video RAM into the virtual address
750 * space of the requestor.
755 PVBE_DEVICE_EXTENSION DeviceExtension
,
756 PVIDEO_MEMORY RequestedAddress
,
757 PVIDEO_MEMORY_INFORMATION MapInformation
,
758 PSTATUS_BLOCK StatusBlock
)
760 PHYSICAL_ADDRESS FrameBuffer
;
761 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
763 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
765 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
768 FrameBuffer
.QuadPart
=
769 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
770 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
771 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
773 MapInformation
->VideoRamLength
=
774 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
775 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
779 MapInformation
->VideoRamLength
=
780 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
781 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
787 FrameBuffer
.QuadPart
= 0xA0000;
788 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
789 MapInformation
->VideoRamLength
= 0x10000;
793 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
794 &MapInformation
->VideoRamLength
, &inIoSpace
,
795 &MapInformation
->VideoRamBase
);
797 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
798 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
804 * VBEUnmapVideoMemory
806 * Releases a mapping between the virtual address space and the adapter's
807 * frame buffer and video RAM.
812 PVBE_DEVICE_EXTENSION DeviceExtension
,
813 PVIDEO_MEMORY VideoMemory
,
814 PSTATUS_BLOCK StatusBlock
)
816 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
822 * VBEQueryNumAvailModes
824 * Returns the number of video modes supported by the adapter and the size
825 * in bytes of the video mode information, which can be used to allocate a
826 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
830 VBEQueryNumAvailModes(
831 PVBE_DEVICE_EXTENSION DeviceExtension
,
832 PVIDEO_NUM_MODES Modes
,
833 PSTATUS_BLOCK StatusBlock
)
835 Modes
->NumModes
= DeviceExtension
->ModeCount
;
836 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
837 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
844 * Returns information about one particular video mode.
849 PVBE_DEVICE_EXTENSION DeviceExtension
,
850 PVIDEO_MODE_INFORMATION VideoMode
,
853 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
856 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
857 VideoMode
->ModeIndex
= VideoModeId
;
858 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
859 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
860 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
861 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
863 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
864 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
865 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
866 VideoMode
->Frequency
= 1;
868 /* Assume 96DPI and 25.4 millimeters per inch, round to nearest */
870 VideoMode
->XMillimeter
= ((ULONGLONG
)VBEMode
->XResolution
* 254 + (dpi
* 5)) / (dpi
* 10);
871 VideoMode
->YMillimeter
= ((ULONGLONG
)VBEMode
->YResolution
* 254 + (dpi
* 5)) / (dpi
* 10);
873 if (VBEMode
->BitsPerPixel
> 8)
876 * Always report 16bpp modes and not 15bpp mode...
878 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
880 VideoMode
->BitsPerPlane
= 16;
883 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
885 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
886 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
887 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
888 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
889 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
890 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
894 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
895 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
896 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
897 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
898 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
899 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
904 VideoMode
->NumberRedBits
=
905 VideoMode
->NumberGreenBits
=
906 VideoMode
->NumberBlueBits
= 6;
908 VideoMode
->GreenMask
=
909 VideoMode
->BlueMask
= 0;
911 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
912 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
913 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
914 VIDEO_MODE_NO_OFF_SCREEN
;
915 if (VideoMode
->BitsPerPlane
<= 8)
916 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
917 VideoMode
->DriverSpecificAttributeFlags
= 0;
923 * Returns information about each video mode supported by the adapter.
928 PVBE_DEVICE_EXTENSION DeviceExtension
,
929 PVIDEO_MODE_INFORMATION ReturnedModes
,
930 PSTATUS_BLOCK StatusBlock
)
933 PVIDEO_MODE_INFORMATION CurrentMode
;
934 PVBE_MODEINFO CurrentVBEMode
;
936 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
937 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
938 CurrentModeId
< DeviceExtension
->ModeCount
;
939 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
941 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
944 StatusBlock
->Information
=
945 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
951 * VBEQueryCurrentMode
953 * Returns information about current video mode.
958 PVBE_DEVICE_EXTENSION DeviceExtension
,
959 PVIDEO_MODE_INFORMATION VideoModeInfo
,
960 PSTATUS_BLOCK StatusBlock
)
962 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
967 DeviceExtension
->CurrentMode
);
973 * VBESetColorRegisters
975 * Sets the adapter's color registers to the specified RGB values. There
976 * are code paths in this function, one generic and one for VGA compatible
977 * controllers. The latter is needed for Bochs, where the generic one isn't
982 VBESetColorRegisters(
983 PVBE_DEVICE_EXTENSION DeviceExtension
,
984 PVIDEO_CLUT ColorLookUpTable
,
985 PSTATUS_BLOCK StatusBlock
)
987 INT10_BIOS_ARGUMENTS BiosRegisters
;
990 ULONG OutputBuffer
[256];
992 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
996 * For VGA compatible adapters program the color registers directly.
999 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
1001 for (Entry
= ColorLookUpTable
->FirstEntry
;
1002 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1005 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1006 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1007 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1008 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1016 * We can't just copy the values, because we need to swap the Red
1020 for (Entry
= ColorLookUpTable
->FirstEntry
,
1021 OutputEntry
= OutputBuffer
;
1022 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1023 Entry
++, OutputEntry
++)
1026 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1027 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1028 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1031 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1032 DeviceExtension
->Int10Interface
.Context
,
1033 DeviceExtension
->TrampolineMemorySegment
,
1034 DeviceExtension
->TrampolineMemoryOffset
,
1036 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1038 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1039 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1040 BiosRegisters
.Ebx
= 0;
1041 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1042 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1043 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1044 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1045 DeviceExtension
->Int10Interface
.Int10CallBios(
1046 DeviceExtension
->Int10Interface
.Context
,
1049 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;