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 *******************************************************************/
32 /* PUBLIC AND PRIVATE FUNCTIONS ***********************************************/
35 DriverEntry(IN PVOID Context1
, IN PVOID Context2
)
37 VIDEO_HW_INITIALIZATION_DATA InitData
;
39 VideoPortZeroMemory(&InitData
, sizeof(InitData
));
40 InitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
41 InitData
.HwFindAdapter
= VBEFindAdapter
;
42 InitData
.HwInitialize
= VBEInitialize
;
43 InitData
.HwStartIO
= VBEStartIO
;
44 InitData
.HwResetHw
= VBEResetHw
;
45 InitData
.HwGetPowerState
= VBEGetPowerState
;
46 InitData
.HwSetPowerState
= VBESetPowerState
;
47 InitData
.HwDeviceExtensionSize
= sizeof(VBE_DEVICE_EXTENSION
);
49 return VideoPortInitialize(Context1
, Context2
, &InitData
, NULL
);
55 * Should detect a VBE compatible display adapter, but it's not possible
56 * to use video port Int 10 services at this time during initialization,
57 * so we always return NO_ERROR and do the real work in VBEInitialize.
62 IN PVOID HwDeviceExtension
,
64 IN PWSTR ArgumentString
,
65 IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
72 * VBESortModesCallback
74 * Helper function for sorting video mode list.
78 VBESortModesCallback(PVBE_MODEINFO VbeModeInfoA
, PVBE_MODEINFO VbeModeInfoB
)
80 DPRINT(("VBESortModesCallback: %dx%dx%d / %dx%dx%d\n",
81 VbeModeInfoA
->XResolution
, VbeModeInfoA
->YResolution
,
82 VbeModeInfoA
->BitsPerPixel
,
83 VbeModeInfoB
->XResolution
, VbeModeInfoB
->YResolution
,
84 VbeModeInfoB
->BitsPerPixel
));
87 * FIXME: Until some reasonable method for changing video modes will
88 * be available we favor more bits per pixel. It should be changed
91 if (VbeModeInfoA
->BitsPerPixel
< VbeModeInfoB
->BitsPerPixel
) return -1;
92 if (VbeModeInfoA
->BitsPerPixel
> VbeModeInfoB
->BitsPerPixel
) return 1;
93 if (VbeModeInfoA
->XResolution
< VbeModeInfoB
->XResolution
) return -1;
94 if (VbeModeInfoA
->XResolution
> VbeModeInfoB
->XResolution
) return 1;
95 if (VbeModeInfoA
->YResolution
< VbeModeInfoB
->YResolution
) return -1;
96 if (VbeModeInfoA
->YResolution
> VbeModeInfoB
->YResolution
) return 1;
103 * Simple function for sorting the video mode list. Uses bubble sort.
107 VBESortModes(PVBE_DEVICE_EXTENSION DeviceExtension
)
109 BOOLEAN Finished
= FALSE
;
112 VBE_MODEINFO TempModeInfo
;
118 for (Pos
= 0; Pos
< DeviceExtension
->ModeCount
- 1; Pos
++)
120 Result
= VBESortModesCallback(
121 DeviceExtension
->ModeInfo
+ Pos
,
122 DeviceExtension
->ModeInfo
+ Pos
+ 1);
129 DeviceExtension
->ModeInfo
+ Pos
,
130 sizeof(VBE_MODEINFO
));
131 TempModeNumber
= DeviceExtension
->ModeNumbers
[Pos
];
134 DeviceExtension
->ModeInfo
+ Pos
,
135 DeviceExtension
->ModeInfo
+ Pos
+ 1,
136 sizeof(VBE_MODEINFO
));
137 DeviceExtension
->ModeNumbers
[Pos
] =
138 DeviceExtension
->ModeNumbers
[Pos
+ 1];
141 DeviceExtension
->ModeInfo
+ Pos
+ 1,
143 sizeof(VBE_MODEINFO
));
144 DeviceExtension
->ModeNumbers
[Pos
+ 1] = TempModeNumber
;
153 * Performs the first initialization of the adapter, after the HAL has given
154 * up control of the video hardware to the video port driver.
156 * This function performs these steps:
157 * - Gets global VBE information and finds if VBE BIOS is present.
158 * - Builds the internal mode list using the list of modes provided by
163 VBEInitialize(PVOID HwDeviceExtension
)
165 INT10_BIOS_ARGUMENTS BiosRegisters
;
167 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
168 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
171 ULONG SuitableModeCount
;
174 PVBE_MODEINFO VbeModeInfo
;
177 * Get the Int 10 interface that we will use for allocating real
178 * mode memory and calling the video BIOS.
181 VBEDeviceExtension
->Int10Interface
.Version
= VIDEO_PORT_INT10_INTERFACE_VERSION_1
;
182 VBEDeviceExtension
->Int10Interface
.Size
= sizeof(VIDEO_PORT_INT10_INTERFACE
);
183 Status
= VideoPortQueryServices(
185 VideoPortServicesInt10
,
186 (PINTERFACE
)&VBEDeviceExtension
->Int10Interface
);
188 if (Status
!= NO_ERROR
)
190 DPRINT(("Failed to get Int 10 service functions (Status %x)\n", Status
));
195 * Allocate a bit of memory that will be later used for VBE transport
196 * buffer. This memory must be accessible from V86 mode so it must fit
197 * in the first megabyte of physical memory.
201 Status
= VBEDeviceExtension
->Int10Interface
.Int10AllocateBuffer(
202 VBEDeviceExtension
->Int10Interface
.Context
,
203 &VBEDeviceExtension
->TrampolineMemorySegment
,
204 &VBEDeviceExtension
->TrampolineMemoryOffset
,
207 if (Status
!= NO_ERROR
)
209 DPRINT(("Failed to allocate virtual memory (Status %x)\n", Status
));
214 * Get the VBE general information.
217 VBEDeviceExtension
->Int10Interface
.Int10WriteMemory(
218 VBEDeviceExtension
->Int10Interface
.Context
,
219 VBEDeviceExtension
->TrampolineMemorySegment
,
220 VBEDeviceExtension
->TrampolineMemoryOffset
,
224 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
225 BiosRegisters
.Eax
= VBE_GET_CONTROLLER_INFORMATION
;
226 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
;
227 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
228 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
229 VBEDeviceExtension
->Int10Interface
.Context
,
232 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
234 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
235 VBEDeviceExtension
->Int10Interface
.Context
,
236 VBEDeviceExtension
->TrampolineMemorySegment
,
237 VBEDeviceExtension
->TrampolineMemoryOffset
,
238 &VBEDeviceExtension
->VbeInfo
,
239 sizeof(VBEDeviceExtension
->VbeInfo
));
241 DPRINT(("VBE BIOS Present (%d.%d, %8ld Kb)\n",
242 VBEDeviceExtension
->VbeInfo
.Version
/ 0x100,
243 VBEDeviceExtension
->VbeInfo
.Version
& 0xFF,
244 VBEDeviceExtension
->VbeInfo
.TotalMemory
* 16));
247 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x102)
249 if (VBEDeviceExtension
->VbeInfo
.Version
< 0x200)
252 DPRINT(("VBE BIOS present, but incompatible version.\n"));
258 DPRINT(("No VBE BIOS found.\n"));
263 * Build a mode list here that can be later used by
264 * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES
269 * Get the number of supported video modes.
271 * No need to be map the memory. It's either in the video BIOS memory or
272 * in our trampoline memory. In either case the memory is already mapped.
275 for (ModeCount
= 0; ; ModeCount
++)
277 /* Read the VBE mode number. */
278 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
279 VBEDeviceExtension
->Int10Interface
.Context
,
280 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
281 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (ModeCount
<< 1),
286 if (ModeTemp
== 0xFFFF || ModeTemp
== 0)
291 * Allocate space for video modes information.
294 VBEDeviceExtension
->ModeInfo
=
295 ExAllocatePool(PagedPool
, ModeCount
* sizeof(VBE_MODEINFO
));
296 VBEDeviceExtension
->ModeNumbers
=
297 ExAllocatePool(PagedPool
, ModeCount
* sizeof(WORD
));
300 * Get the actual mode infos.
303 for (CurrentMode
= 0, SuitableModeCount
= 0;
304 CurrentMode
< ModeCount
;
307 /* Read the VBE mode number. */
308 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
309 VBEDeviceExtension
->Int10Interface
.Context
,
310 HIWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
),
311 LOWORD(VBEDeviceExtension
->VbeInfo
.VideoModePtr
) + (CurrentMode
<< 1),
315 /* Call VBE BIOS to read the mode info. */
316 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
317 BiosRegisters
.Eax
= VBE_GET_MODE_INFORMATION
;
318 BiosRegisters
.Ecx
= ModeTemp
;
319 BiosRegisters
.Edi
= VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200;
320 BiosRegisters
.SegEs
= VBEDeviceExtension
->TrampolineMemorySegment
;
321 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
322 VBEDeviceExtension
->Int10Interface
.Context
,
325 /* Read the VBE mode info. */
326 VBEDeviceExtension
->Int10Interface
.Int10ReadMemory(
327 VBEDeviceExtension
->Int10Interface
.Context
,
328 VBEDeviceExtension
->TrampolineMemorySegment
,
329 VBEDeviceExtension
->TrampolineMemoryOffset
+ 0x200,
330 VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
,
331 sizeof(VBE_MODEINFO
));
333 VbeModeInfo
= VBEDeviceExtension
->ModeInfo
+ SuitableModeCount
;
335 /* Is this mode acceptable? */
336 if (BiosRegisters
.Eax
== VBE_SUCCESS
&&
337 VbeModeInfo
->XResolution
>= 640 &&
338 VbeModeInfo
->YResolution
>= 480 &&
339 (VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_PACKEDPIXEL
||
340 VbeModeInfo
->MemoryModel
== VBE_MEMORYMODEL_DIRECTCOLOR
))
342 if (VbeModeInfo
->ModeAttributes
& VBE_MODEATTR_LINEAR
)
344 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
| 0x4000;
350 VBEDeviceExtension
->ModeNumbers
[SuitableModeCount
] = ModeTemp
;
357 if (SuitableModeCount
== 0)
359 DPRINT(("VBEMP: No video modes supported\n"));
363 VBEDeviceExtension
->ModeCount
= SuitableModeCount
;
366 * Sort the video mode list according to resolution and bits per pixel.
369 VBESortModes(VBEDeviceExtension
);
372 * Print the supported video modes when DBG is set.
376 for (CurrentMode
= 0;
377 CurrentMode
< SuitableModeCount
;
380 DPRINT(("%dx%dx%d\n",
381 VBEDeviceExtension
->ModeInfo
[CurrentMode
].XResolution
,
382 VBEDeviceExtension
->ModeInfo
[CurrentMode
].YResolution
,
383 VBEDeviceExtension
->ModeInfo
[CurrentMode
].BitsPerPixel
));
393 * Processes the specified Video Request Packet.
398 PVOID HwDeviceExtension
,
399 PVIDEO_REQUEST_PACKET RequestPacket
)
403 RequestPacket
->StatusBlock
->Status
= STATUS_UNSUCCESSFUL
;
405 switch (RequestPacket
->IoControlCode
)
407 case IOCTL_VIDEO_SET_CURRENT_MODE
:
408 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MODE
))
410 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
413 Result
= VBESetCurrentMode(
414 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
415 (PVIDEO_MODE
)RequestPacket
->InputBuffer
,
416 RequestPacket
->StatusBlock
);
419 case IOCTL_VIDEO_RESET_DEVICE
:
420 Result
= VBEResetDevice(
421 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
422 RequestPacket
->StatusBlock
);
425 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
426 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MEMORY_INFORMATION
) ||
427 RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
429 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
432 Result
= VBEMapVideoMemory(
433 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
434 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
435 (PVIDEO_MEMORY_INFORMATION
)RequestPacket
->OutputBuffer
,
436 RequestPacket
->StatusBlock
);
439 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
440 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
))
442 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
445 Result
= VBEUnmapVideoMemory(
446 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
447 (PVIDEO_MEMORY
)RequestPacket
->InputBuffer
,
448 RequestPacket
->StatusBlock
);
451 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
452 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_NUM_MODES
))
454 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
457 Result
= VBEQueryNumAvailModes(
458 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
459 (PVIDEO_NUM_MODES
)RequestPacket
->OutputBuffer
,
460 RequestPacket
->StatusBlock
);
463 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
464 if (RequestPacket
->OutputBufferLength
<
465 ((PVBE_DEVICE_EXTENSION
)HwDeviceExtension
)->ModeCount
* sizeof(VIDEO_MODE_INFORMATION
))
467 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
470 Result
= VBEQueryAvailModes(
471 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
472 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
473 RequestPacket
->StatusBlock
);
476 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
477 if (RequestPacket
->InputBufferLength
< sizeof(VIDEO_CLUT
) ||
478 RequestPacket
->InputBufferLength
<
479 (((PVIDEO_CLUT
)RequestPacket
->InputBuffer
)->NumEntries
* sizeof(ULONG
)) +
482 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
485 Result
= VBESetColorRegisters(
486 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
487 (PVIDEO_CLUT
)RequestPacket
->InputBuffer
,
488 RequestPacket
->StatusBlock
);
491 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
492 if (RequestPacket
->OutputBufferLength
< sizeof(VIDEO_MODE_INFORMATION
))
494 RequestPacket
->StatusBlock
->Status
= ERROR_INSUFFICIENT_BUFFER
;
497 Result
= VBEQueryCurrentMode(
498 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
,
499 (PVIDEO_MODE_INFORMATION
)RequestPacket
->OutputBuffer
,
500 RequestPacket
->StatusBlock
);
504 RequestPacket
->StatusBlock
->Status
= STATUS_NOT_IMPLEMENTED
;
509 RequestPacket
->StatusBlock
->Status
= STATUS_SUCCESS
;
517 * This function is called to reset the hardware to a known state.
522 PVOID DeviceExtension
,
526 INT10_BIOS_ARGUMENTS BiosRegisters
;
527 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
528 (PVBE_DEVICE_EXTENSION
)DeviceExtension
;
530 if (!VBEResetDevice(DeviceExtension
, NULL
))
533 /* Change number of columns/rows */
534 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
536 if (Columns
== 80 && Rows
== 25)
538 /* Default text size, don't change anything. */
541 else if (Columns
== 80 && Rows
== 28)
543 /* Use 9x14 font (80x28) */
544 BiosRegisters
.Eax
= 0x1111;
546 else if (Columns
== 80 && Rows
== 43)
548 /* Use 8x8 font in 350 scans mode (80x43) */
549 BiosRegisters
.Eax
= 0x1201;
550 BiosRegisters
.Ebx
= 0x30;
551 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
552 VBEDeviceExtension
->Int10Interface
.Context
,
555 BiosRegisters
.Eax
= 0x3;
556 BiosRegisters
.Ebx
= 0;
557 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
558 VBEDeviceExtension
->Int10Interface
.Context
,
561 BiosRegisters
.Eax
= 0x1112;
563 else if (Columns
== 80 && Rows
== 50)
565 /* Use 8x8 font (80x50) */
566 BiosRegisters
.Eax
= 0x1112;
571 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
572 VBEDeviceExtension
->Int10Interface
.Context
,
581 * Queries whether the device can support the requested power state.
586 PVOID HwDeviceExtension
,
588 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
590 INT10_BIOS_ARGUMENTS BiosRegisters
;
591 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
592 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
594 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
595 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
))
596 return ERROR_INVALID_FUNCTION
;
599 * Get general power support information.
602 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
603 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
604 BiosRegisters
.Ebx
= 0;
605 BiosRegisters
.Edi
= 0;
606 BiosRegisters
.SegEs
= 0;
607 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
608 VBEDeviceExtension
->Int10Interface
.Context
,
611 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
612 return ERROR_NOT_SUPPORTED
;
613 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
614 return ERROR_INVALID_FUNCTION
;
617 * Get current power state.
620 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
621 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
622 BiosRegisters
.Ebx
= 0x2;
623 BiosRegisters
.Edi
= 0;
624 BiosRegisters
.SegEs
= 0;
625 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
626 VBEDeviceExtension
->Int10Interface
.Context
,
629 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
631 VideoPowerControl
->DPMSVersion
= BiosRegisters
.Ebx
& 0xFF;
632 switch (BiosRegisters
.Ebx
>> 8)
634 case 0: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
635 case 1: VideoPowerControl
->PowerState
= VideoPowerStandBy
; break;
636 case 2: VideoPowerControl
->PowerState
= VideoPowerSuspend
; break;
637 case 4: VideoPowerControl
->PowerState
= VideoPowerOff
; break;
638 case 5: VideoPowerControl
->PowerState
= VideoPowerOn
; break;
639 default: VideoPowerControl
->PowerState
= VideoPowerUnspecified
;
645 return ERROR_NOT_SUPPORTED
;
651 * Sets the power state of the specified device
656 PVOID HwDeviceExtension
,
658 PVIDEO_POWER_MANAGEMENT VideoPowerControl
)
660 INT10_BIOS_ARGUMENTS BiosRegisters
;
661 PVBE_DEVICE_EXTENSION VBEDeviceExtension
=
662 (PVBE_DEVICE_EXTENSION
)HwDeviceExtension
;
664 if (HwId
!= DISPLAY_ADAPTER_HW_ID
||
665 VideoPowerControl
->Length
< sizeof(VIDEO_POWER_MANAGEMENT
) ||
666 VideoPowerControl
->PowerState
< VideoPowerOn
||
667 VideoPowerControl
->PowerState
> VideoPowerHibernate
)
668 return ERROR_INVALID_FUNCTION
;
670 if (VideoPowerControl
->PowerState
== VideoPowerHibernate
)
674 * Set current power state.
677 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
678 BiosRegisters
.Eax
= VBE_POWER_MANAGEMENT_EXTENSIONS
;
679 BiosRegisters
.Ebx
= 1;
680 BiosRegisters
.Edi
= 0;
681 BiosRegisters
.SegEs
= 0;
682 switch (VideoPowerControl
->PowerState
)
684 case VideoPowerStandBy
: BiosRegisters
.Ebx
|= 0x100; break;
685 case VideoPowerSuspend
: BiosRegisters
.Ebx
|= 0x200; break;
686 case VideoPowerOff
: BiosRegisters
.Ebx
|= 0x400; break;
689 VBEDeviceExtension
->Int10Interface
.Int10CallBios(
690 VBEDeviceExtension
->Int10Interface
.Context
,
693 if (BiosRegisters
.Eax
== VBE_NOT_SUPPORTED
)
694 return ERROR_NOT_SUPPORTED
;
695 if (BiosRegisters
.Eax
!= VBE_SUCCESS
)
696 return ERROR_INVALID_FUNCTION
;
704 * Sets the adapter to the specified operating mode.
709 PVBE_DEVICE_EXTENSION DeviceExtension
,
710 PVIDEO_MODE RequestedMode
,
711 PSTATUS_BLOCK StatusBlock
)
713 INT10_BIOS_ARGUMENTS BiosRegisters
;
715 if (RequestedMode
->RequestedMode
>= DeviceExtension
->ModeCount
)
717 return ERROR_INVALID_PARAMETER
;
720 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
721 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
722 BiosRegisters
.Ebx
= DeviceExtension
->ModeNumbers
[RequestedMode
->RequestedMode
];
723 DeviceExtension
->Int10Interface
.Int10CallBios(
724 DeviceExtension
->Int10Interface
.Context
,
727 if (BiosRegisters
.Eax
== VBE_SUCCESS
)
729 DeviceExtension
->CurrentMode
= RequestedMode
->RequestedMode
;
733 DPRINT(("VBEMP: VBESetCurrentMode failed (%x)\n", BiosRegisters
.Eax
));
734 DeviceExtension
->CurrentMode
= -1;
737 return BiosRegisters
.Eax
== VBE_SUCCESS
;
743 * Resets the video hardware to the default mode, to which it was initialized
749 PVBE_DEVICE_EXTENSION DeviceExtension
,
750 PSTATUS_BLOCK StatusBlock
)
752 INT10_BIOS_ARGUMENTS BiosRegisters
;
754 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
755 BiosRegisters
.Eax
= VBE_SET_VBE_MODE
;
756 BiosRegisters
.Ebx
= 0x3;
757 DeviceExtension
->Int10Interface
.Int10CallBios(
758 DeviceExtension
->Int10Interface
.Context
,
761 return BiosRegisters
.Eax
== VBE_SUCCESS
;
767 * Maps the video hardware frame buffer and video RAM into the virtual address
768 * space of the requestor.
773 PVBE_DEVICE_EXTENSION DeviceExtension
,
774 PVIDEO_MEMORY RequestedAddress
,
775 PVIDEO_MEMORY_INFORMATION MapInformation
,
776 PSTATUS_BLOCK StatusBlock
)
778 PHYSICAL_ADDRESS FrameBuffer
;
779 ULONG inIoSpace
= VIDEO_MEMORY_SPACE_MEMORY
;
781 StatusBlock
->Information
= sizeof(VIDEO_MEMORY_INFORMATION
);
783 if (DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].ModeAttributes
&
786 FrameBuffer
.QuadPart
=
787 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].PhysBasePtr
;
788 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
789 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
791 MapInformation
->VideoRamLength
=
792 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].BytesPerScanLine
*
793 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
797 MapInformation
->VideoRamLength
=
798 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].LinBytesPerScanLine
*
799 DeviceExtension
->ModeInfo
[DeviceExtension
->CurrentMode
].YResolution
;
805 FrameBuffer
.QuadPart
= 0xA0000;
806 MapInformation
->VideoRamBase
= RequestedAddress
->RequestedVirtualAddress
;
807 MapInformation
->VideoRamLength
= 0x10000;
811 VideoPortMapMemory(DeviceExtension
, FrameBuffer
,
812 &MapInformation
->VideoRamLength
, &inIoSpace
,
813 &MapInformation
->VideoRamBase
);
815 MapInformation
->FrameBufferBase
= MapInformation
->VideoRamBase
;
816 MapInformation
->FrameBufferLength
= MapInformation
->VideoRamLength
;
822 * VBEUnmapVideoMemory
824 * Releases a mapping between the virtual address space and the adapter's
825 * frame buffer and video RAM.
830 PVBE_DEVICE_EXTENSION DeviceExtension
,
831 PVIDEO_MEMORY VideoMemory
,
832 PSTATUS_BLOCK StatusBlock
)
834 VideoPortUnmapMemory(DeviceExtension
, VideoMemory
->RequestedVirtualAddress
,
840 * VBEQueryNumAvailModes
842 * Returns the number of video modes supported by the adapter and the size
843 * in bytes of the video mode information, which can be used to allocate a
844 * buffer for an IOCTL_VIDEO_QUERY_AVAIL_MODES request.
848 VBEQueryNumAvailModes(
849 PVBE_DEVICE_EXTENSION DeviceExtension
,
850 PVIDEO_NUM_MODES Modes
,
851 PSTATUS_BLOCK StatusBlock
)
853 Modes
->NumModes
= DeviceExtension
->ModeCount
;
854 Modes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
855 StatusBlock
->Information
= sizeof(VIDEO_NUM_MODES
);
862 * Returns information about one particular video mode.
867 PVBE_DEVICE_EXTENSION DeviceExtension
,
868 PVIDEO_MODE_INFORMATION VideoMode
,
871 PVBE_MODEINFO VBEMode
= &DeviceExtension
->ModeInfo
[VideoModeId
];
873 VideoMode
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
874 VideoMode
->ModeIndex
= VideoModeId
;
875 VideoMode
->VisScreenWidth
= VBEMode
->XResolution
;
876 VideoMode
->VisScreenHeight
= VBEMode
->YResolution
;
877 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
878 VideoMode
->ScreenStride
= VBEMode
->BytesPerScanLine
;
880 VideoMode
->ScreenStride
= VBEMode
->LinBytesPerScanLine
;
881 VideoMode
->NumberOfPlanes
= VBEMode
->NumberOfPlanes
;
882 VideoMode
->BitsPerPlane
= VBEMode
->BitsPerPixel
/ VBEMode
->NumberOfPlanes
;
883 VideoMode
->Frequency
= 1;
884 VideoMode
->XMillimeter
= 0; /* FIXME */
885 VideoMode
->YMillimeter
= 0; /* FIXME */
886 if (VBEMode
->BitsPerPixel
> 8)
889 * Always report 16bpp modes and not 15bpp mode...
891 if (VBEMode
->BitsPerPixel
== 15 && VBEMode
->NumberOfPlanes
== 1)
893 VideoMode
->BitsPerPlane
= 16;
896 if (DeviceExtension
->VbeInfo
.Version
< 0x300)
898 VideoMode
->NumberRedBits
= VBEMode
->RedMaskSize
;
899 VideoMode
->NumberGreenBits
= VBEMode
->GreenMaskSize
;
900 VideoMode
->NumberBlueBits
= VBEMode
->BlueMaskSize
;
901 VideoMode
->RedMask
= ((1 << VBEMode
->RedMaskSize
) - 1) << VBEMode
->RedFieldPosition
;
902 VideoMode
->GreenMask
= ((1 << VBEMode
->GreenMaskSize
) - 1) << VBEMode
->GreenFieldPosition
;
903 VideoMode
->BlueMask
= ((1 << VBEMode
->BlueMaskSize
) - 1) << VBEMode
->BlueFieldPosition
;
907 VideoMode
->NumberRedBits
= VBEMode
->LinRedMaskSize
;
908 VideoMode
->NumberGreenBits
= VBEMode
->LinGreenMaskSize
;
909 VideoMode
->NumberBlueBits
= VBEMode
->LinBlueMaskSize
;
910 VideoMode
->RedMask
= ((1 << VBEMode
->LinRedMaskSize
) - 1) << VBEMode
->LinRedFieldPosition
;
911 VideoMode
->GreenMask
= ((1 << VBEMode
->LinGreenMaskSize
) - 1) << VBEMode
->LinGreenFieldPosition
;
912 VideoMode
->BlueMask
= ((1 << VBEMode
->LinBlueMaskSize
) - 1) << VBEMode
->LinBlueFieldPosition
;
917 VideoMode
->NumberRedBits
=
918 VideoMode
->NumberGreenBits
=
919 VideoMode
->NumberBlueBits
= 6;
921 VideoMode
->GreenMask
=
922 VideoMode
->BlueMask
= 0;
924 VideoMode
->VideoMemoryBitmapWidth
= VBEMode
->XResolution
;
925 VideoMode
->VideoMemoryBitmapHeight
= VBEMode
->YResolution
;
926 VideoMode
->AttributeFlags
= VIDEO_MODE_GRAPHICS
| VIDEO_MODE_COLOR
|
927 VIDEO_MODE_NO_OFF_SCREEN
;
928 if (VideoMode
->BitsPerPlane
<= 8)
929 VideoMode
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
;
930 VideoMode
->DriverSpecificAttributeFlags
= 0;
936 * Returns information about each video mode supported by the adapter.
941 PVBE_DEVICE_EXTENSION DeviceExtension
,
942 PVIDEO_MODE_INFORMATION ReturnedModes
,
943 PSTATUS_BLOCK StatusBlock
)
946 PVIDEO_MODE_INFORMATION CurrentMode
;
947 PVBE_MODEINFO CurrentVBEMode
;
949 for (CurrentModeId
= 0, CurrentMode
= ReturnedModes
,
950 CurrentVBEMode
= DeviceExtension
->ModeInfo
;
951 CurrentModeId
< DeviceExtension
->ModeCount
;
952 CurrentModeId
++, CurrentMode
++, CurrentVBEMode
++)
954 VBEQueryMode(DeviceExtension
, CurrentMode
, CurrentModeId
);
957 StatusBlock
->Information
=
958 sizeof(VIDEO_MODE_INFORMATION
) * DeviceExtension
->ModeCount
;
964 * VBEQueryCurrentMode
966 * Returns information about current video mode.
971 PVBE_DEVICE_EXTENSION DeviceExtension
,
972 PVIDEO_MODE_INFORMATION VideoModeInfo
,
973 PSTATUS_BLOCK StatusBlock
)
975 StatusBlock
->Information
= sizeof(VIDEO_MODE_INFORMATION
);
980 DeviceExtension
->CurrentMode
);
986 * VBESetColorRegisters
988 * Sets the adapter's color registers to the specified RGB values. There
989 * are code paths in this function, one generic and one for VGA compatible
990 * controllers. The latter is needed for Bochs, where the generic one isn't
995 VBESetColorRegisters(
996 PVBE_DEVICE_EXTENSION DeviceExtension
,
997 PVIDEO_CLUT ColorLookUpTable
,
998 PSTATUS_BLOCK StatusBlock
)
1000 INT10_BIOS_ARGUMENTS BiosRegisters
;
1003 ULONG OutputBuffer
[256];
1005 if (ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
> 256)
1009 * For VGA compatible adapters program the color registers directly.
1012 if (!(DeviceExtension
->VbeInfo
.Capabilities
& 2))
1014 for (Entry
= ColorLookUpTable
->FirstEntry
;
1015 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1018 VideoPortWritePortUchar((PUCHAR
)0x03c8, Entry
);
1019 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
);
1020 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
);
1021 VideoPortWritePortUchar((PUCHAR
)0x03c9, ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1029 * We can't just copy the values, because we need to swap the Red
1033 for (Entry
= ColorLookUpTable
->FirstEntry
,
1034 OutputEntry
= OutputBuffer
;
1035 Entry
< ColorLookUpTable
->NumEntries
+ ColorLookUpTable
->FirstEntry
;
1036 Entry
++, OutputEntry
++)
1039 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Red
<< 16) |
1040 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Green
<< 8) |
1041 (ColorLookUpTable
->LookupTable
[Entry
].RgbArray
.Blue
);
1044 DeviceExtension
->Int10Interface
.Int10WriteMemory(
1045 DeviceExtension
->Int10Interface
.Context
,
1046 DeviceExtension
->TrampolineMemorySegment
,
1047 DeviceExtension
->TrampolineMemoryOffset
,
1049 (OutputEntry
- OutputBuffer
) * sizeof(ULONG
));
1051 VideoPortZeroMemory(&BiosRegisters
, sizeof(BiosRegisters
));
1052 BiosRegisters
.Eax
= VBE_SET_GET_PALETTE_DATA
;
1053 BiosRegisters
.Ebx
= 0;
1054 BiosRegisters
.Ecx
= ColorLookUpTable
->NumEntries
;
1055 BiosRegisters
.Edx
= ColorLookUpTable
->FirstEntry
;
1056 BiosRegisters
.Edi
= DeviceExtension
->TrampolineMemoryOffset
;
1057 BiosRegisters
.SegEs
= DeviceExtension
->TrampolineMemorySegment
;
1058 DeviceExtension
->Int10Interface
.Int10CallBios(
1059 DeviceExtension
->Int10Interface
.Context
,
1062 return BiosRegisters
.Eax
== VBE_SUCCESS
;