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(Error
, "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(Error
, "VBE BIOS present, but incompatible version %d.%d\n",
269 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
270 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF);
276 VideoPortDebugPrint(Error
, "No VBE BIOS found.\n");
281 * Build a mode list here that can be later used by
282 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
287 * Get the number of supported video modes.
289 * No need to be map the memory. It's either in the video BIOS memory or
290 * in our trampoline memory. In either case the memory is already mapped.
293 for (ModeCount
= 0; ; ModeCount
++)
295 /* Read the VBE mode number. */
296 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
297 VBEDeviceExtension
->Int10Interface
.Context
,
298 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
299 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
304 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
309 * Allocate space for video modes information.
312 VBEDeviceExtension
->ModeInfo
=
313 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(VBE_MODEINFO
), TAG_VBE
);
314 VBEDeviceExtension
->ModeNumbers
=
315 VideoPortAllocatePool(HwDeviceExtension
, VpPagedPool
, ModeCount
* sizeof(USHORT
), TAG_VBE
);
318 * Get the actual mode infos.
321 for (CurrentMode
= 0, SuitableModeCount
= 0;
322 CurrentMode
< ModeCount
;
325 /* Read the VBE mode number. */
326 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
327 VBEDeviceExtension
->Int10Interface
.Context
,
328 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
329 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
333 /* Call VBE BIOS to read the mode info. */
334 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
335 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
336 BiosRegisters
.Ecx
= ModeTemp
;
337 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
338 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
339 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
340 VBEDeviceExtension
->Int10Interface
.Context
,
343 /* Read the VBE mode info. */
344 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
345 VBEDeviceExtension
->Int10Interface
.Context
,
346 VBEDeviceExtension
->TrampolineMemorySegment
,
347 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
348 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
349 sizeof(VBE_MODEINFO
));
351 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
353 /* Is this mode acceptable? */
354 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
&&
355 VbeModeInfo
->XResolution
>= 640 &&
356 VbeModeInfo
->YResolution
>= 480 &&
357 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
358 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
) &&
359 VbeModeInfo
->PhysBasePtr
!= 0)
361 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
363 /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */
364 // if (ModeTemp & 0x4000)
366 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
373 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
381 if (SuitableModeCount
== 0)
384 VideoPortDebugPrint(Warn
, "VBEMP: No video modes supported\n");
388 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
391 * Sort the video mode list according to resolution and bits per pixel.
394 VBESortModes(VBEDeviceExtension
);
397 * Print the supported video modes.
400 for (CurrentMode
= 0;
401 CurrentMode
< SuitableModeCount
;
404 VideoPortDebugPrint(Trace
, "%dx%dx%d\n",
405 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
406 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
407 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
);
411 * Enumerate our children.
413 VideoPortEnumerateChildren(HwDeviceExtension
, NULL
);
421 * Processes the specified Video Request Packet.
426 PVOID HwDeviceExtension
,
427 PVIDEO_REQUEST_PACKET RequestPacket
)
431 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
433 switch (RequestPacket
->IoControlCode
)
435 case IOCTL_VIDEO_SET_CURRENT_MODE
:
436 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
438 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
441 Result
= VBESetCurrentMode(
442 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
443 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
444 RequestPacket
->StatusBlock
);
447 case IOCTL_VIDEO_RESET_DEVICE
:
448 Result
= VBEResetDevice(
449 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
450 RequestPacket
->StatusBlock
);
453 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
454 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
455 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
457 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
460 Result
= VBEMapVideoMemory(
461 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
462 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
463 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
464 RequestPacket
->StatusBlock
);
467 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
468 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
470 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
473 Result
= VBEUnmapVideoMemory(
474 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
475 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
476 RequestPacket
->StatusBlock
);
479 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
480 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
482 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
485 Result
= VBEQueryNumAvailModes(
486 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
487 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
488 RequestPacket
->StatusBlock
);
491 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
492 if (RequestPacket
->OutputBufferLength
<
493 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
495 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
498 Result
= VBEQueryAvailModes(
499 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
500 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
501 RequestPacket
->StatusBlock
);
504 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
505 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
506 RequestPacket
->InputBufferLength
<
507 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
508 FIELD_OFFSET(VIDEO_CLUT
, LookupTable
))
510 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
513 Result
= VBESetColorRegisters(
514 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
515 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
516 RequestPacket
->StatusBlock
);
519 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
520 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
522 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
525 Result
= VBEQueryCurrentMode(
526 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
527 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
528 RequestPacket
->StatusBlock
);
532 RequestPacket
->StatusBlock
->Status
= ERROR_INVALID_FUNCTION
;
537 RequestPacket
->StatusBlock
->Status
= NO_ERROR
;
545 * This function is called to reset the hardware to a known state.
550 PVOID DeviceExtension
,
554 /* Return FALSE to let HAL reset the display with INT10 */
561 * Queries whether the device can support the requested power state.
566 PVOID HwDeviceExtension
,
568 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
570 INT10_BIOS_ARGUMENTS BiosRegisters
;
571 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
572 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
574 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
575 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
576 return ERROR_INVALID_FUNCTION
;
579 * Get general power support information.
582 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
583 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
584 BiosRegisters
.Ebx
= 0;
585 BiosRegisters
.Edi
= 0;
586 BiosRegisters
.SegEs
= 0;
587 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
588 VBEDeviceExtension
->Int10Interface
.Context
,
591 if ( VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
592 return ERROR_DEV_NOT_EXIST
;
593 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
594 return ERROR_INVALID_FUNCTION
;
597 * Get current power state.
600 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
601 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
602 BiosRegisters
.Ebx
= 0x2;
603 BiosRegisters
.Edi
= 0;
604 BiosRegisters
.SegEs
= 0;
605 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
606 VBEDeviceExtension
->Int10Interface
.Context
,
609 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
611 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
612 switch (BiosRegisters
.Ebx
>> 8)
614 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
615 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
616 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
617 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
618 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
619 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
625 return ERROR_DEV_NOT_EXIST
;
631 * Sets the power state of the specified device
636 PVOID HwDeviceExtension
,
638 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
640 INT10_BIOS_ARGUMENTS BiosRegisters
;
641 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
642 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
644 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
645 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
646 VideoPowerControl
->PowerState
< VideoPowerOn
||
647 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
648 return ERROR_INVALID_FUNCTION
;
650 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
654 * Set current power state.
657 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
658 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
659 BiosRegisters
.Ebx
= 1;
660 BiosRegisters
.Edi
= 0;
661 BiosRegisters
.SegEs
= 0;
662 switch (VideoPowerControl
->PowerState
)
664 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
665 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
666 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
669 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
670 VBEDeviceExtension
->Int10Interface
.Context
,
673 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_NOT_SUPPORTED
)
674 return ERROR_DEV_NOT_EXIST
;
675 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) != VBE_SUCCESS
)
676 return ERROR_INVALID_FUNCTION
;
684 * Sets the adapter to the specified operating mode.
689 PVBE_DEVICE_EXTENSION DeviceExtension
,
690 PVIDEO_MODE RequestedMode
,
691 PSTATUS_BLOCK StatusBlock
)
693 INT10_BIOS_ARGUMENTS BiosRegisters
;
695 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
697 return ERROR_INVALID_PARAMETER
;
700 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
701 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
702 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
703 DeviceExtension
->Int10Interface
.Int10CallBios(
704 DeviceExtension
->Int10Interface
.Context
,
707 if (VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
)
709 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
713 VideoPortDebugPrint(Error
, "VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
);
714 DeviceExtension
->CurrentMode
= -1;
717 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
723 * Resets the video hardware to the default mode, to which it was initialized
729 PVBE_DEVICE_EXTENSION DeviceExtension
,
730 PSTATUS_BLOCK StatusBlock
)
732 INT10_BIOS_ARGUMENTS BiosRegisters
;
734 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
735 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
736 BiosRegisters
.Ebx
= 0x3;
737 DeviceExtension
->Int10Interface
.Int10CallBios(
738 DeviceExtension
->Int10Interface
.Context
,
741 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;
747 * Maps the video hardware frame buffer and video RAM into the virtual address
748 * space of the requestor.
753 PVBE_DEVICE_EXTENSION DeviceExtension
,
754 PVIDEO_MEMORY RequestedAddress
,
755 PVIDEO_MEMORY_INFORMATION MapInformation
,
756 PSTATUS_BLOCK StatusBlock
)
758 PHYSICAL_ADDRESS FrameBuffer
;
759 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
761 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
763 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
766 FrameBuffer
.QuadPart
=
767 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
768 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
769 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
771 MapInformation
->VideoRamLength
=
772 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
773 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
777 MapInformation
->VideoRamLength
=
778 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
779 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
785 FrameBuffer
.QuadPart
= 0xA0000;
786 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
787 MapInformation
->VideoRamLength
= 0x10000;
791 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
792 &MapInformation
->VideoRamLength
, &inIoSpace
,
793 &MapInformation
->VideoRamBase
);
795 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
796 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
802 * VBEUnmapVideoMemory
804 * Releases a mapping between the virtual address space and the adapter's
805 * frame buffer and video RAM.
810 PVBE_DEVICE_EXTENSION DeviceExtension
,
811 PVIDEO_MEMORY VideoMemory
,
812 PSTATUS_BLOCK StatusBlock
)
814 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
820 * VBEQueryNumAvailModes
822 * Returns the number of video modes supported by the adapter and the size
823 * in bytes of the video mode information, which can be used to allocate a
824 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
828 VBEQueryNumAvailModes(
829 PVBE_DEVICE_EXTENSION DeviceExtension
,
830 PVIDEO_NUM_MODES Modes
,
831 PSTATUS_BLOCK StatusBlock
)
833 Modes
->NumModes
= DeviceExtension
->ModeCount
;
834 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
835 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
842 * Returns information about one particular video mode.
847 PVBE_DEVICE_EXTENSION DeviceExtension
,
848 PVIDEO_MODE_INFORMATION VideoMode
,
851 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
854 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
855 VideoMode
->ModeIndex
= VideoModeId
;
856 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
857 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
858 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
859 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
861 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
862 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
863 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
864 VideoMode
->Frequency
= 1;
866 /* Assume 96DPI and 25.4 millimeters per inch, round to nearest */
868 VideoMode
->XMillimeter
= ((ULONGLONG
)VBEMode
->XResolution
* 254 + (dpi
* 5)) / (dpi
* 10);
869 VideoMode
->YMillimeter
= ((ULONGLONG
)VBEMode
->YResolution
* 254 + (dpi
* 5)) / (dpi
* 10);
871 if (VBEMode
->BitsPerPixel
> 8)
874 * Always report 16bpp modes and not 15bpp mode...
876 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
878 VideoMode
->BitsPerPlane
= 16;
881 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
883 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
884 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
885 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
886 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
887 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
888 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
892 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
893 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
894 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
895 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
896 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
897 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
902 VideoMode
->NumberRedBits
=
903 VideoMode
->NumberGreenBits
=
904 VideoMode
->NumberBlueBits
= 6;
906 VideoMode
->GreenMask
=
907 VideoMode
->BlueMask
= 0;
909 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
910 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
911 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
912 VIDEO_MODE_NO_OFF_SCREEN
;
913 if (VideoMode
->BitsPerPlane
<= 8)
914 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
915 VideoMode
->DriverSpecificAttributeFlags
= 0;
921 * Returns information about each video mode supported by the adapter.
926 PVBE_DEVICE_EXTENSION DeviceExtension
,
927 PVIDEO_MODE_INFORMATION ReturnedModes
,
928 PSTATUS_BLOCK StatusBlock
)
931 PVIDEO_MODE_INFORMATION CurrentMode
;
932 PVBE_MODEINFO CurrentVBEMode
;
934 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
935 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
936 CurrentModeId
< DeviceExtension
->ModeCount
;
937 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
939 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
942 StatusBlock
->Information
=
943 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
949 * VBEQueryCurrentMode
951 * Returns information about current video mode.
956 PVBE_DEVICE_EXTENSION DeviceExtension
,
957 PVIDEO_MODE_INFORMATION VideoModeInfo
,
958 PSTATUS_BLOCK StatusBlock
)
960 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
965 DeviceExtension
->CurrentMode
);
971 * VBESetColorRegisters
973 * Sets the adapter's color registers to the specified RGB values. There
974 * are code paths in this function, one generic and one for VGA compatible
975 * controllers. The latter is needed for Bochs, where the generic one isn't
980 VBESetColorRegisters(
981 PVBE_DEVICE_EXTENSION DeviceExtension
,
982 PVIDEO_CLUT ColorLookUpTable
,
983 PSTATUS_BLOCK StatusBlock
)
985 INT10_BIOS_ARGUMENTS BiosRegisters
;
988 ULONG OutputBuffer
[256];
990 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
994 * For VGA compatible adapters program the color registers directly.
997 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
999 for (Entry
= ColorLookUpTable
->FirstEntry
;
1000 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1003 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1004 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1005 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1006 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1014 * We can't just copy the values, because we need to swap the Red
1018 for (Entry
= ColorLookUpTable
->FirstEntry
,
1019 OutputEntry
= OutputBuffer
;
1020 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1021 Entry
++, OutputEntry
++)
1024 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1025 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1026 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1029 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1030 DeviceExtension
->Int10Interface
.Context
,
1031 DeviceExtension
->TrampolineMemorySegment
,
1032 DeviceExtension
->TrampolineMemoryOffset
,
1034 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1036 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1037 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1038 BiosRegisters
.Ebx
= 0;
1039 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1040 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1041 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1042 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1043 DeviceExtension
->Int10Interface
.Int10CallBios(
1044 DeviceExtension
->Int10Interface
.Context
,
1047 return VBE_GETRETURNCODE(BiosRegisters
.Eax
) == VBE_SUCCESS
;