2 * PROJECT: ReactOS VGA Miniport Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: boot/drivers/video/miniport/vga/vga.c
5 * PURPOSE: Main Standard VGA-compatible Minport Handling Code
6 * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation
7 * ReactOS Portable Systems Group
10 //---------------------------------------------------------------------------
14 //---------------------------------------------------------------------------
16 // Function declarations
18 // Functions that start with 'VGA' are entry points for the OS port driver.
23 PVOID HwDeviceExtension
,
26 PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
32 PVOID HwDeviceExtension
37 PVOID HwDeviceExtension
,
38 PVIDEO_REQUEST_PACKET RequestPacket
42 // Private function prototypes.
46 VgaQueryAvailableModes(
47 PHW_DEVICE_EXTENSION HwDeviceExtension
,
48 PVIDEO_MODE_INFORMATION ModeInformation
,
49 ULONG ModeInformationSize
,
54 VgaQueryNumberOfAvailableModes(
55 PHW_DEVICE_EXTENSION HwDeviceExtension
,
56 PVIDEO_NUM_MODES NumModes
,
63 PHW_DEVICE_EXTENSION HwDeviceExtension
,
66 // eVb: 1.1 [SET MODE] - Add new output parameter for framebuffer update functionality
73 PHW_DEVICE_EXTENSION HwDeviceExtension
77 VgaInterpretCmdStream(
78 PVOID HwDeviceExtension
,
84 PHW_DEVICE_EXTENSION HwDeviceExtension
,
85 PVIDEO_CLUT ClutBuffer
,
90 GetDeviceDataCallback(
91 PVOID HwDeviceExtension
,
93 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
95 ULONG IdentifierLength
,
96 PVOID ConfigurationData
,
97 ULONG ConfigurationDataLength
,
98 PVOID ComponentInformation
,
99 ULONG ComponentInformationLength
102 // eVb: 1.2 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
105 PHW_DEVICE_EXTENSION DeviceExtension
109 #if defined(ALLOC_PRAGMA)
110 #pragma alloc_text(PAGE,DriverEntry)
111 #pragma alloc_text(PAGE,VgaFindAdapter)
112 #pragma alloc_text(PAGE,VgaInitialize)
113 #pragma alloc_text(PAGE,VgaStartIO)
114 #pragma alloc_text(PAGE,VgaIsPresent)
115 #pragma alloc_text(PAGE,VgaSetColorLookup)
119 //---------------------------------------------------------------------------
121 // eVb: 1.3 [GCC] - Add NTAPI for GCC support
133 Installable driver initialization entry point.
134 This entry point is called directly by the I/O system.
138 Context1 - First context value passed by the operating system. This is
139 the value with which the miniport driver calls VideoPortInitialize().
141 Context2 - Second context value passed by the operating system. This is
142 the value with which the miniport driver calls 3VideoPortInitialize().
146 Status from VideoPortInitialize()
152 VIDEO_HW_INITIALIZATION_DATA hwInitData
;
154 ULONG initializationStatus
= (ULONG
) -1;
157 // Zero out structure.
160 VideoPortZeroMemory(&hwInitData
, sizeof(VIDEO_HW_INITIALIZATION_DATA
));
163 // Specify sizes of structure and extension.
166 hwInitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
172 hwInitData
.HwFindAdapter
= VgaFindAdapter
;
173 hwInitData
.HwInitialize
= VgaInitialize
;
174 hwInitData
.HwInterrupt
= NULL
;
175 hwInitData
.HwStartIO
= VgaStartIO
;
178 // Determine the size we require for the device extension.
181 hwInitData
.HwDeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
184 // Always start with parameters for device0 in this case.
185 // We can leave it like this since we know we will only ever find one
186 // VGA type adapter in a machine.
189 // hwInitData.StartingDeviceNumber = 0;
192 // Once all the relevant information has been stored, call the video
193 // port driver to do the initialization.
194 // For this device we will repeat this call three times, for ISA, EISA
196 // We will return the minimum of all return values.
200 // We will try the PCI bus first so that our ISA detection does'nt claim
201 // PCI cards (since it is impossible to differentiate between the two
202 // by looking at the registers).
206 // NOTE: since this driver only supports one adapter, we will return
207 // as soon as we find a device, without going on to the following buses.
208 // Normally one would call for each bus type and return the smallest
212 #if !defined(_ALPHA_)
215 // Before we can enable this on ALPHA we need to find a way to map a
216 // sparse view of a 4MB region successfully.
219 hwInitData
.AdapterInterfaceType
= PCIBus
;
221 initializationStatus
= VideoPortInitialize(Context1
,
226 if (initializationStatus
== NO_ERROR
)
228 return initializationStatus
;
233 hwInitData
.AdapterInterfaceType
= MicroChannel
;
235 initializationStatus
= VideoPortInitialize(Context1
,
241 // Return immediately instead of checkin for smallest return code.
244 if (initializationStatus
== NO_ERROR
)
246 return initializationStatus
;
250 hwInitData
.AdapterInterfaceType
= Internal
;
252 initializationStatus
= VideoPortInitialize(Context1
,
257 if (initializationStatus
== NO_ERROR
)
259 return initializationStatus
;
263 hwInitData
.AdapterInterfaceType
= Isa
;
265 initializationStatus
= VideoPortInitialize(Context1
,
270 if (initializationStatus
== NO_ERROR
)
272 return initializationStatus
;
277 hwInitData
.AdapterInterfaceType
= Eisa
;
279 status
= VideoPortInitialize(Context1
,
284 if (initializationStatus
> status
) {
285 initializationStatus
= status
;
288 return initializationStatus
;
290 } // end DriverEntry()
292 //---------------------------------------------------------------------------
295 PVOID HwDeviceExtension
,
297 PWSTR ArgumentString
,
298 PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
306 This routine is called to determine if the adapter for this driver
307 is present in the system.
308 If it is present, the function fills out some information describing
313 HwDeviceExtension - Supplies the miniport driver's adapter storage. This
314 storage is initialized to zero before this call.
316 HwContext - Supplies the context value which was passed to
317 VideoPortInitialize().
319 ArgumentString - Supplies a NULL terminated ASCII string. This string
320 originates from the user.
322 ConfigInfo - Returns the configuration information structure which is
323 filled by the miniport driver. This structure is initialized with
324 any known configuration information (such as SystemIoBusNumber) by
325 the port driver. Where possible, drivers should have one set of
326 defaults which do not require any supplied configuration information.
328 Again - Indicates if the miniport driver wants the port driver to call
329 its VIDEO_HW_FIND_ADAPTER function again with a new device extension
330 and the same config info. This is used by the miniport drivers which
331 can search for several adapters on a bus.
335 This routine must return:
337 NO_ERROR - Indicates a host adapter was found and the
338 configuration information was successfully determined.
340 ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
341 error obtaining the configuration information. If possible an error
344 ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
345 supplied configuration information.
351 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
354 // Make sure the size of the structure is at least as large as what we
355 // are expecting (check version of the config info structure).
358 if (ConfigInfo
->Length
< sizeof(VIDEO_PORT_CONFIG_INFO
)) {
360 return ERROR_INVALID_PARAMETER
;
363 // eVb: 1.4 [CIRRUS] - Remove CIRRUS-specific support
365 // Check internal VGA (MIPS and ARM systems)
368 if ((ConfigInfo
->AdapterInterfaceType
== Internal
) &&
369 (VideoPortGetDeviceData(HwDeviceExtension
,
371 &GetDeviceDataCallback
,
372 VgaAccessRange
) != NO_ERROR
))
374 return ERROR_INVALID_PARAMETER
;
378 // No interrupt information is necessary.
382 // Check to see if there is a hardware resource conflict.
384 // eVb: 1.5 [RESOURCE] - Use new function for acquiring VGA resources (I/O, memory)
385 if (VgaAcquireResources(hwDeviceExtension
) != NO_ERROR
) return ERROR_INVALID_PARAMETER
;
388 // Get logical IO port addresses.
391 if ((hwDeviceExtension
->IOAddress
=
392 VideoPortGetDeviceBase(hwDeviceExtension
,
393 VgaAccessRange
->RangeStart
,
394 VGA_MAX_IO_PORT
- VGA_BASE_IO_PORT
+ 1,
395 VgaAccessRange
->RangeInIoSpace
)) == NULL
)
397 VideoDebugPrint((2, "VgaFindAdapter - Fail to get io address\n"));
399 return ERROR_INVALID_PARAMETER
;
403 // Determine whether a VGA is present.
406 if (!VgaIsPresent(hwDeviceExtension
)) {
408 VideoDebugPrint((0, "VgaFindAdapter - VGA Failed\n"));
409 return ERROR_DEV_NOT_EXIST
;
413 // Minimum size of the buffer required to store the hardware state
414 // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
417 ConfigInfo
->HardwareStateSize
= VGA_TOTAL_STATE_SIZE
;
420 // Pass a pointer to the emulator range we are using.
422 // eVb: 1.6 [VDM] - Disable VDM for now
423 ConfigInfo
->NumEmulatorAccessEntries
= 0;
424 ConfigInfo
->EmulatorAccessEntries
= NULL
;
425 ConfigInfo
->EmulatorAccessEntriesContext
= 0;
430 // There is really no reason to have the frame buffer mapped. On an
431 // x86 we use if for save/restore (supposedly) but even then we
432 // would only need to map a 64K window, not all 16 Meg!
438 // Map the video memory into the system virtual address space so we can
439 // clear it out and use it for save and restore.
442 if ( (hwDeviceExtension
->VideoMemoryAddress
=
443 VideoPortGetDeviceBase(hwDeviceExtension
,
444 VgaAccessRange
[2].RangeStart
,
445 VgaAccessRange
[2].RangeLength
,
448 VideoDebugPrint((1, "VgaFindAdapter - Fail to get memory address\n"));
450 return ERROR_INVALID_PARAMETER
;
453 VideoPortDebugPrint(0, "vga mapped at %x\n", hwDeviceExtension
->VideoMemoryAddress
);
455 // eVb: 1.7 [VDM] - Disable VDM for now
456 ConfigInfo
->VdmPhysicalVideoMemoryAddress
.QuadPart
= 0;
457 ConfigInfo
->VdmPhysicalVideoMemoryLength
= 0;
460 // Indicate we do not wish to be called again for another initialization.
466 // Indicate a successful completion status.
472 } // VgaFindAdapter()
474 //---------------------------------------------------------------------------
477 PVOID HwDeviceExtension
484 This routine does one time initialization of the device.
488 HwDeviceExtension - Pointer to the miniport driver's adapter information.
497 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
500 // set up the default cursor position and type.
503 hwDeviceExtension
->CursorPosition
.Column
= 0;
504 hwDeviceExtension
->CursorPosition
.Row
= 0;
505 hwDeviceExtension
->CursorTopScanLine
= 0;
506 hwDeviceExtension
->CursorBottomScanLine
= 31;
507 hwDeviceExtension
->CursorEnable
= TRUE
;
509 // eVb: 1.8 [VBE] - Initialize VBE modes
510 InitializeModeTable(hwDeviceExtension
);
516 //---------------------------------------------------------------------------
519 PVOID HwDeviceExtension
,
520 PVIDEO_REQUEST_PACKET RequestPacket
527 This routine is the main execution routine for the miniport driver. It
528 accepts a Video Request Packet, performs the request, and then returns
529 with the appropriate status.
533 HwDeviceExtension - Pointer to the miniport driver's adapter information.
535 RequestPacket - Pointer to the video request packet. This structure
536 contains all the parameters passed to the VideoIoControl function.
540 This routine will return error codes from the various support routines
541 and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
542 buffers and ERROR_INVALID_FUNCTION for unsupported functions.
547 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
549 VIDEO_MODE videoMode
;
550 PVIDEO_MEMORY_INFORMATION memoryInformation
;
555 // Switch on the IoContolCode in the RequestPacket. It indicates which
556 // function must be performed by the driver.
558 // eVb: 1.9 [IOCTL] - Remove IOCTLs not needed yet
559 switch (RequestPacket
->IoControlCode
)
561 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY
:
563 VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n"));
565 status
= ERROR_INVALID_FUNCTION
;
569 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY
:
571 VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n"));
573 status
= ERROR_INVALID_FUNCTION
;
578 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
580 VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
582 if ( (RequestPacket
->OutputBufferLength
<
583 (RequestPacket
->StatusBlock
->Information
=
584 sizeof(VIDEO_MEMORY_INFORMATION
))) ||
585 (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
)) )
587 status
= ERROR_INSUFFICIENT_BUFFER
;
590 memoryInformation
= RequestPacket
->OutputBuffer
;
592 memoryInformation
->VideoRamBase
= ((PVIDEO_MEMORY
)
593 (RequestPacket
->InputBuffer
))->RequestedVirtualAddress
;
596 // We reserved 16 meg for the frame buffer, however, it makes
597 // no sense to map more memory than there is on the card. So
598 // only map the amount of memory we have on the card.
600 // eVb: 1.10 [CIRRUS] - On VGA, we have VRAM size since boot, use it
601 memoryInformation
->VideoRamLength
=
602 hwDeviceExtension
->PhysicalVideoMemoryLength
;
605 // If you change to using a dense space frame buffer, make this
606 // value a 4 for the ALPHA.
611 status
= VideoPortMapMemory(hwDeviceExtension
,
612 hwDeviceExtension
->PhysicalVideoMemoryBase
,
613 // eVb: 1.11 [CIRRUS] - On VGA, we have VRAM size since boot, use it
614 &memoryInformation
->VideoRamLength
,
617 &(memoryInformation
->VideoRamBase
));
619 if (status
!= NO_ERROR
) {
620 VideoDebugPrint((0, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status
));
623 memoryInformation
->FrameBufferBase
=
624 ((PUCHAR
) (memoryInformation
->VideoRamBase
)) +
625 hwDeviceExtension
->PhysicalFrameOffset
.LowPart
;
627 memoryInformation
->FrameBufferLength
=
628 hwDeviceExtension
->PhysicalFrameLength
?
629 hwDeviceExtension
->PhysicalFrameLength
:
630 memoryInformation
->VideoRamLength
;
633 VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryBase
));
634 VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryLength
));
635 VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation
->VideoRamBase
));
636 VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation
->VideoRamLength
));
638 VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension
->PhysicalFrameOffset
.LowPart
));
639 VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation
->FrameBufferBase
));
640 VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension
->PhysicalFrameLength
));
641 VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation
->FrameBufferLength
));
645 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
647 VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
649 status
= ERROR_INVALID_FUNCTION
;
654 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
656 VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
658 status
= VgaQueryAvailableModes(HwDeviceExtension
,
659 (PVIDEO_MODE_INFORMATION
)
660 RequestPacket
->OutputBuffer
,
661 RequestPacket
->OutputBufferLength
,
662 &RequestPacket
->StatusBlock
->Information
);
667 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
669 VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
671 status
= VgaQueryNumberOfAvailableModes(HwDeviceExtension
,
673 RequestPacket
->OutputBuffer
,
674 RequestPacket
->OutputBufferLength
,
675 &RequestPacket
->StatusBlock
->Information
);
680 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
682 VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
684 status
= ERROR_INVALID_FUNCTION
;
689 case IOCTL_VIDEO_SET_CURRENT_MODE
:
691 VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
693 status
= VgaSetMode(HwDeviceExtension
,
694 (PVIDEO_MODE
) RequestPacket
->InputBuffer
,
695 RequestPacket
->InputBufferLength
,
696 // eVb: 1.12 [SET MODE] - Use new output parameter for framebuffer update functionality
703 case IOCTL_VIDEO_RESET_DEVICE
:
705 VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
707 videoMode
.RequestedMode
= 0;
709 VgaSetMode(HwDeviceExtension
,
710 (PVIDEO_MODE
) &videoMode
,
712 // eVb: 1.13 [SET MODE] - Use new output parameter for framebuffer update functionality
717 // Always return succcess since settings the text mode will fail on
720 // Also, failiure to set the text mode is not fatal in any way, since
721 // this operation must be followed by another set mode operation.
729 case IOCTL_VIDEO_LOAD_AND_SET_FONT
:
731 VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
733 status
= ERROR_INVALID_FUNCTION
;
738 case IOCTL_VIDEO_QUERY_CURSOR_POSITION
:
740 VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
742 status
= ERROR_INVALID_FUNCTION
;
747 case IOCTL_VIDEO_SET_CURSOR_POSITION
:
749 VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
751 status
= ERROR_INVALID_FUNCTION
;
756 case IOCTL_VIDEO_QUERY_CURSOR_ATTR
:
758 VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
760 status
= ERROR_INVALID_FUNCTION
;
765 case IOCTL_VIDEO_SET_CURSOR_ATTR
:
767 VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
769 status
= ERROR_INVALID_FUNCTION
;
774 case IOCTL_VIDEO_SET_PALETTE_REGISTERS
:
776 VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
778 status
= ERROR_INVALID_FUNCTION
;
783 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
785 VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
787 status
= VgaSetColorLookup(HwDeviceExtension
,
788 (PVIDEO_CLUT
) RequestPacket
->InputBuffer
,
789 RequestPacket
->InputBufferLength
);
794 case IOCTL_VIDEO_ENABLE_VDM
:
796 VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
798 status
= ERROR_INVALID_FUNCTION
;
803 case IOCTL_VIDEO_RESTORE_HARDWARE_STATE
:
805 VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
807 status
= ERROR_INVALID_FUNCTION
;
812 case IOCTL_VIDEO_SAVE_HARDWARE_STATE
:
814 VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
816 status
= ERROR_INVALID_FUNCTION
;
820 case IOCTL_VIDEO_GET_BANK_SELECT_CODE
:
822 VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
824 status
= ERROR_INVALID_FUNCTION
;
827 case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES
:
828 case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES
:
831 // if we get here, an invalid IoControlCode was specified.
836 VideoDebugPrint((0, "Fell through vga startIO routine - invalid command\n"));
838 status
= ERROR_INVALID_FUNCTION
;
844 RequestPacket
->StatusBlock
->Status
= status
;
851 //---------------------------------------------------------------------------
857 //---------------------------------------------------------------------------
860 PHW_DEVICE_EXTENSION HwDeviceExtension
867 This routine returns TRUE if a VGA is present. Determining whether a VGA
868 is present is a two-step process. First, this routine walks bits through
869 the Bit Mask register, to establish that there are readable indexed
870 registers (EGAs normally don't have readable registers, and other adapters
871 are unlikely to have indexed registers). This test is done first because
872 it's a non-destructive EGA rejection test (correctly rejects EGAs, but
873 doesn't potentially mess up the screen or the accessibility of display
874 memory). Normally, this would be an adequate test, but some EGAs have
875 readable registers, so next, we check for the existence of the Chain4 bit
876 in the Memory Mode register; this bit doesn't exist in EGAs. It's
877 conceivable that there are EGAs with readable registers and a register bit
878 where Chain4 is stored, although I don't know of any; if a better test yet
879 is needed, memory could be written to in Chain4 mode, and then examined
880 plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
881 supposed to do. However, the current test should be adequate to eliminate
882 just about all EGAs, and 100% of everything else.
884 If this function fails to find a VGA, it attempts to undo any damage it
885 may have inadvertently done while testing. The underlying assumption for
886 the damage control is that if there's any non-VGA adapter at the tested
887 ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
888 other adapters that use 3C4/5 or 3CE/F, and b), if there are other
889 adapters, I certainly don't know how to restore their original states. So
890 all error recovery is oriented toward putting an EGA back in a writable
891 state, so that error messages are visible. The EGA's state on entry is
892 assumed to be text mode, so the Memory Mode register is restored to the
893 default state for text mode.
895 If a VGA is found, the VGA is returned to its original state after
904 TRUE if a VGA is present, FALSE if not.
909 UCHAR originalGCAddr
;
910 UCHAR originalSCAddr
;
911 UCHAR originalBitMask
;
912 UCHAR originalReadMap
;
913 UCHAR originalMemoryMode
;
915 BOOLEAN returnStatus
;
918 // Remember the original state of the Graphics Controller Address register.
921 originalGCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
925 // Write the Read Map register with a known state so we can verify
926 // that it isn't changed after we fool with the Bit Mask. This ensures
927 // that we're dealing with indexed registers, since both the Read Map and
928 // the Bit Mask are addressed at GRAPH_DATA_PORT.
931 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
932 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
935 // If we can't read back the Graphics Address register setting we just
936 // performed, it's not readable and this isn't a VGA.
939 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
940 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_READ_MAP
) {
946 // Set the Read Map register to a known state.
949 originalReadMap
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
951 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
952 GRAPH_DATA_PORT
, READ_MAP_TEST_SETTING
);
954 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
955 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
958 // The Read Map setting we just performed can't be read back; not a
959 // VGA. Restore the default Read Map state.
962 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
963 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
969 // Remember the original setting of the Bit Mask register.
972 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
973 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
974 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
975 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_BIT_MASK
) {
978 // The Graphics Address register setting we just made can't be read
979 // back; not a VGA. Restore the default Read Map state.
982 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
983 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
984 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
985 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
990 originalBitMask
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
994 // Set up the initial test mask we'll write to and read from the Bit Mask.
1002 // Write the test mask to the Bit Mask.
1005 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1006 GRAPH_DATA_PORT
, testMask
);
1009 // Make sure the Bit Mask remembered the value.
1012 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1013 GRAPH_DATA_PORT
) != testMask
) {
1016 // The Bit Mask is not properly writable and readable; not a VGA.
1017 // Restore the Bit Mask and Read Map to their default states.
1020 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1021 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1022 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1023 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1024 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1025 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1031 // Cycle the mask for next time.
1036 } while (testMask
!= 0);
1039 // There's something readable at GRAPH_DATA_PORT; now switch back and
1040 // make sure that the Read Map register hasn't changed, to verify that
1041 // we're dealing with indexed registers.
1044 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1045 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1046 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1047 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
1050 // The Read Map is not properly writable and readable; not a VGA.
1051 // Restore the Bit Mask and Read Map to their default states, in case
1052 // this is an EGA, so subsequent writes to the screen aren't garbled.
1055 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1056 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1057 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1058 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1059 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1060 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1066 // We've pretty surely verified the existence of the Bit Mask register.
1067 // Put the Graphics Controller back to the original state.
1070 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1071 GRAPH_DATA_PORT
, originalReadMap
);
1072 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1073 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1074 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1075 GRAPH_DATA_PORT
, originalBitMask
);
1076 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1077 GRAPH_ADDRESS_PORT
, originalGCAddr
);
1080 // Now, check for the existence of the Chain4 bit.
1084 // Remember the original states of the Sequencer Address and Memory Mode
1088 originalSCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1090 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1091 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1092 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1093 SEQ_ADDRESS_PORT
) & SEQ_ADDR_MASK
) != IND_MEMORY_MODE
) {
1096 // Couldn't read back the Sequencer Address register setting we just
1102 originalMemoryMode
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1106 // Toggle the Chain4 bit and read back the result. This must be done during
1107 // sync reset, since we're changing the chaining state.
1111 // Begin sync reset.
1114 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1116 (IND_SYNC_RESET
+ (START_SYNC_RESET_VALUE
<< 8)));
1119 // Toggle the Chain4 bit.
1122 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1123 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1124 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1125 SEQ_DATA_PORT
, (UCHAR
)(originalMemoryMode
^ CHAIN4_MASK
));
1127 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1128 SEQ_DATA_PORT
) != (UCHAR
) (originalMemoryMode
^ CHAIN4_MASK
)) {
1131 // Chain4 bit not there; not a VGA.
1132 // Set text mode default for Memory Mode register.
1135 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1136 SEQ_DATA_PORT
, MEMORY_MODE_TEXT_DEFAULT
);
1141 VideoPortWritePortUshort((PUSHORT
) (HwDeviceExtension
->IOAddress
+
1143 (IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1145 returnStatus
= FALSE
;
1154 // Restore the original Memory Mode setting.
1157 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1158 SEQ_DATA_PORT
, originalMemoryMode
);
1164 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1166 (USHORT
)(IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1169 // Restore the original Sequencer Address setting.
1172 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1173 SEQ_ADDRESS_PORT
, originalSCAddr
);
1175 returnStatus
= TRUE
;
1178 return returnStatus
;
1183 //---------------------------------------------------------------------------
1186 PHW_DEVICE_EXTENSION HwDeviceExtension
,
1187 PVIDEO_CLUT ClutBuffer
,
1188 ULONG ClutBufferSize
1193 Routine Description:
1195 This routine sets a specified portion of the DAC color lookup table
1200 HwDeviceExtension - Pointer to the miniport driver's device extension.
1202 ClutBufferSize - Length of the input buffer supplied by the user.
1204 ClutBuffer - Pointer to the structure containing the color lookup table.
1208 NO_ERROR - information returned successfully
1210 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1212 ERROR_INVALID_PARAMETER - invalid clut size.
1217 PVIDEOMODE CurrentMode
= HwDeviceExtension
->CurrentMode
;
1221 // Check if the size of the data in the input buffer is large enough.
1224 if ( (ClutBufferSize
< sizeof(VIDEO_CLUT
) - sizeof(ULONG
)) ||
1225 (ClutBufferSize
< sizeof(VIDEO_CLUT
) +
1226 (sizeof(ULONG
) * (ClutBuffer
->NumEntries
- 1)) ) ) {
1228 return ERROR_INSUFFICIENT_BUFFER
;
1233 // Check to see if the parameters are valid.
1236 if ( (ClutBuffer
->NumEntries
== 0) ||
1237 (ClutBuffer
->FirstEntry
> VIDEO_MAX_COLOR_REGISTER
) ||
1238 (ClutBuffer
->FirstEntry
+ ClutBuffer
->NumEntries
>
1239 VIDEO_MAX_COLOR_REGISTER
+ 1) ) {
1241 return ERROR_INVALID_PARAMETER
;
1244 // eVb: 1.14 [VBE] - Add VBE color support
1249 if (CurrentMode
->bitsPerPlane
>= 8) return VbeSetColorLookup(HwDeviceExtension
, ClutBuffer
);
1252 // Path for VGA mode
1254 // eVb: 1.15 [VBE] - Add VBE support for non-VGA-compatible detected modes
1255 if (!CurrentMode
->NonVgaMode
)
1259 // Set CLUT registers directly on the hardware
1262 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1263 DAC_ADDRESS_WRITE_PORT
, (UCHAR
) ClutBuffer
->FirstEntry
);
1265 for (i
= 0; i
< ClutBuffer
->NumEntries
; i
++) {
1266 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1267 DAC_ADDRESS_WRITE_PORT
,
1268 (UCHAR
)(i
+ ClutBuffer
->FirstEntry
));
1270 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1272 ClutBuffer
->LookupTable
[i
].RgbArray
.Red
);
1274 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1276 ClutBuffer
->LookupTable
[i
].RgbArray
.Green
);
1278 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1280 ClutBuffer
->LookupTable
[i
].RgbArray
.Blue
);
1285 return ERROR_INVALID_PARAMETER
;
1287 } // end VgaSetColorLookup()
1290 GetDeviceDataCallback(
1291 PVOID HwDeviceExtension
,
1293 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
1295 ULONG IdentifierLength
,
1296 PVOID ConfigurationData
,
1297 ULONG ConfigurationDataLength
,
1298 PVOID ComponentInformation
,
1299 ULONG ComponentInformationLength
1304 Routine Description:
1306 Callback routine for the VideoPortGetDeviceData function.
1310 HwDeviceExtension - Pointer to the miniport drivers device extension.
1312 Context - Context value passed to the VideoPortGetDeviceData function.
1314 DeviceDataType - The type of data that was requested in
1315 VideoPortGetDeviceData.
1317 Identifier - Pointer to a string that contains the name of the device,
1318 as setup by the ROM or ntdetect.
1320 IdentifierLength - Length of the Identifier string.
1322 ConfigurationData - Pointer to the configuration data for the device or
1325 ConfigurationDataLength - Length of the data in the configurationData
1328 ComponentInformation - Undefined.
1330 ComponentInformationLength - Undefined.
1334 Returns NO_ERROR if the function completed properly.
1335 Returns ERROR_DEV_NOT_EXIST if we did not find the device.
1336 Returns ERROR_INVALID_PARAMETER otherwise.
1341 VideoPortDebugPrint(Error
, "Detected internal VGA chip on embedded board, todo\n");
1345 } //end GetDeviceDataCallback()
1347 // eVb: 1.16 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
1349 VgaAcquireResources(
1350 PHW_DEVICE_EXTENSION DeviceExtension
1353 VP_STATUS Status
= NO_ERROR
;
1357 // Try exclusive ranges (vga + ati)
1360 Ranges
= NUM_VGA_ACCESS_RANGES
;
1361 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= FALSE
;
1362 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1365 // Not worked, try vga only
1369 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1372 // Still not, try shared ranges
1375 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1376 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);
1377 if (Status
== NO_ERROR
)
1383 VideoPortVerifyAccessRanges(DeviceExtension
, 0, 0);
1389 if (Status
== NO_ERROR
)
1392 // Worked with exclusive, also try shared
1395 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1396 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);