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
,
64 PVIDEO_MODE_INFORMATION ModeInformation
,
65 ULONG ModeInformationSize
,
71 PHW_DEVICE_EXTENSION HwDeviceExtension
,
74 // eVb: 1.1 [SET MODE] - Add new output parameter for framebuffer update functionality
81 PHW_DEVICE_EXTENSION HwDeviceExtension
85 VgaInterpretCmdStream(
86 PVOID HwDeviceExtension
,
92 PHW_DEVICE_EXTENSION HwDeviceExtension
,
93 PVIDEO_PALETTE_DATA PaletteBuffer
,
94 ULONG PaletteBufferSize
99 PHW_DEVICE_EXTENSION HwDeviceExtension
,
100 PVIDEO_CLUT ClutBuffer
,
105 GetDeviceDataCallback(
106 PVOID HwDeviceExtension
,
108 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
110 ULONG IdentifierLength
,
111 PVOID ConfigurationData
,
112 ULONG ConfigurationDataLength
,
113 PVOID ComponentInformation
,
114 ULONG ComponentInformationLength
117 // eVb: 1.2 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
120 PHW_DEVICE_EXTENSION DeviceExtension
124 #if defined(ALLOC_PRAGMA)
125 #pragma alloc_text(PAGE,DriverEntry)
126 #pragma alloc_text(PAGE,VgaFindAdapter)
127 #pragma alloc_text(PAGE,VgaInitialize)
128 #pragma alloc_text(PAGE,VgaStartIO)
129 #pragma alloc_text(PAGE,VgaIsPresent)
130 #pragma alloc_text(PAGE,VgaSetColorLookup)
134 //---------------------------------------------------------------------------
136 // eVb: 1.3 [GCC] - Add NTAPI for GCC support
148 Installable driver initialization entry point.
149 This entry point is called directly by the I/O system.
153 Context1 - First context value passed by the operating system. This is
154 the value with which the miniport driver calls VideoPortInitialize().
156 Context2 - Second context value passed by the operating system. This is
157 the value with which the miniport driver calls 3VideoPortInitialize().
161 Status from VideoPortInitialize()
167 VIDEO_HW_INITIALIZATION_DATA hwInitData
;
169 ULONG initializationStatus
= (ULONG
) -1;
172 // Zero out structure.
175 VideoPortZeroMemory(&hwInitData
, sizeof(VIDEO_HW_INITIALIZATION_DATA
));
178 // Specify sizes of structure and extension.
181 hwInitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
187 hwInitData
.HwFindAdapter
= VgaFindAdapter
;
188 hwInitData
.HwInitialize
= VgaInitialize
;
189 hwInitData
.HwInterrupt
= NULL
;
190 hwInitData
.HwStartIO
= VgaStartIO
;
193 // Determine the size we require for the device extension.
196 hwInitData
.HwDeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
199 // Always start with parameters for device0 in this case.
200 // We can leave it like this since we know we will only ever find one
201 // VGA type adapter in a machine.
204 // hwInitData.StartingDeviceNumber = 0;
207 // Once all the relevant information has been stored, call the video
208 // port driver to do the initialization.
209 // For this device we will repeat this call three times, for ISA, EISA
211 // We will return the minimum of all return values.
215 // We will try the PCI bus first so that our ISA detection does'nt claim
216 // PCI cards (since it is impossible to differentiate between the two
217 // by looking at the registers).
221 // NOTE: since this driver only supports one adapter, we will return
222 // as soon as we find a device, without going on to the following buses.
223 // Normally one would call for each bus type and return the smallest
227 #if !defined(_ALPHA_)
230 // Before we can enable this on ALPHA we need to find a way to map a
231 // sparse view of a 4MB region successfully.
234 hwInitData
.AdapterInterfaceType
= PCIBus
;
236 initializationStatus
= VideoPortInitialize(Context1
,
241 if (initializationStatus
== NO_ERROR
)
243 return initializationStatus
;
248 hwInitData
.AdapterInterfaceType
= MicroChannel
;
250 initializationStatus
= VideoPortInitialize(Context1
,
256 // Return immediately instead of checkin for smallest return code.
259 if (initializationStatus
== NO_ERROR
)
261 return initializationStatus
;
265 hwInitData
.AdapterInterfaceType
= Internal
;
267 initializationStatus
= VideoPortInitialize(Context1
,
272 if (initializationStatus
== NO_ERROR
)
274 return initializationStatus
;
278 hwInitData
.AdapterInterfaceType
= Isa
;
280 initializationStatus
= VideoPortInitialize(Context1
,
285 if (initializationStatus
== NO_ERROR
)
287 return initializationStatus
;
292 hwInitData
.AdapterInterfaceType
= Eisa
;
294 status
= VideoPortInitialize(Context1
,
299 if (initializationStatus
> status
) {
300 initializationStatus
= status
;
303 return initializationStatus
;
305 } // end DriverEntry()
307 //---------------------------------------------------------------------------
310 PVOID HwDeviceExtension
,
312 PWSTR ArgumentString
,
313 PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
321 This routine is called to determine if the adapter for this driver
322 is present in the system.
323 If it is present, the function fills out some information describing
328 HwDeviceExtension - Supplies the miniport driver's adapter storage. This
329 storage is initialized to zero before this call.
331 HwContext - Supplies the context value which was passed to
332 VideoPortInitialize().
334 ArgumentString - Supplies a NULL terminated ASCII string. This string
335 originates from the user.
337 ConfigInfo - Returns the configuration information structure which is
338 filled by the miniport driver. This structure is initialized with
339 any known configuration information (such as SystemIoBusNumber) by
340 the port driver. Where possible, drivers should have one set of
341 defaults which do not require any supplied configuration information.
343 Again - Indicates if the miniport driver wants the port driver to call
344 its VIDEO_HW_FIND_ADAPTER function again with a new device extension
345 and the same config info. This is used by the miniport drivers which
346 can search for several adapters on a bus.
350 This routine must return:
352 NO_ERROR - Indicates a host adapter was found and the
353 configuration information was successfully determined.
355 ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
356 error obtaining the configuration information. If possible an error
359 ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
360 supplied configuration information.
366 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
369 // Make sure the size of the structure is at least as large as what we
370 // are expecting (check version of the config info structure).
373 if (ConfigInfo
->Length
< sizeof(VIDEO_PORT_CONFIG_INFO
)) {
375 return ERROR_INVALID_PARAMETER
;
378 // eVb: 1.4 [CIRRUS] - Remove CIRRUS-specific support
380 // Check internal VGA (MIPS and ARM systems)
383 if ((ConfigInfo
->AdapterInterfaceType
== Internal
) &&
384 (VideoPortGetDeviceData(HwDeviceExtension
,
386 &GetDeviceDataCallback
,
387 VgaAccessRange
) != NO_ERROR
))
389 return ERROR_INVALID_PARAMETER
;
393 // No interrupt information is necessary.
397 // Check to see if there is a hardware resource conflict.
399 // eVb: 1.5 [RESOURCE] - Use new function for acquiring VGA resources (I/O, memory)
400 if (VgaAcquireResources(hwDeviceExtension
) != NO_ERROR
) return ERROR_INVALID_PARAMETER
;
403 // Get logical IO port addresses.
406 if ((hwDeviceExtension
->IOAddress
=
407 VideoPortGetDeviceBase(hwDeviceExtension
,
408 VgaAccessRange
->RangeStart
,
409 VGA_MAX_IO_PORT
- VGA_BASE_IO_PORT
+ 1,
410 VgaAccessRange
->RangeInIoSpace
)) == NULL
)
412 VideoDebugPrint((0, "VgaFindAdapter - Fail to get io address\n"));
414 return ERROR_INVALID_PARAMETER
;
418 // Determine whether a VGA is present.
421 if (!VgaIsPresent(hwDeviceExtension
)) {
423 VideoDebugPrint((0, "VgaFindAdapter - VGA Failed\n"));
424 return ERROR_DEV_NOT_EXIST
;
428 // Minimum size of the buffer required to store the hardware state
429 // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
432 ConfigInfo
->HardwareStateSize
= VGA_TOTAL_STATE_SIZE
;
435 // Pass a pointer to the emulator range we are using.
437 // eVb: 1.6 [VDM] - Disable VDM for now
438 ConfigInfo
->NumEmulatorAccessEntries
= 0;
439 ConfigInfo
->EmulatorAccessEntries
= NULL
;
440 ConfigInfo
->EmulatorAccessEntriesContext
= 0;
445 // There is really no reason to have the frame buffer mapped. On an
446 // x86 we use if for save/restore (supposedly) but even then we
447 // would only need to map a 64K window, not all 16 Meg!
453 // Map the video memory into the system virtual address space so we can
454 // clear it out and use it for save and restore.
457 if ( (hwDeviceExtension
->VideoMemoryAddress
=
458 VideoPortGetDeviceBase(hwDeviceExtension
,
459 VgaAccessRange
[2].RangeStart
,
460 VgaAccessRange
[2].RangeLength
,
463 VideoDebugPrint((0, "VgaFindAdapter - Fail to get memory address\n"));
465 return ERROR_INVALID_PARAMETER
;
468 VideoPortDebugPrint(0, "vga mapped at %x\n", hwDeviceExtension
->VideoMemoryAddress
);
470 // eVb: 1.7 [VDM] - Disable VDM for now
471 ConfigInfo
->VdmPhysicalVideoMemoryAddress
.QuadPart
= 0;
472 ConfigInfo
->VdmPhysicalVideoMemoryLength
= 0;
475 // Indicate we do not wish to be called again for another initialization.
481 // Indicate a successful completion status.
487 } // VgaFindAdapter()
489 //---------------------------------------------------------------------------
492 PVOID HwDeviceExtension
499 This routine does one time initialization of the device.
503 HwDeviceExtension - Pointer to the miniport driver's adapter information.
512 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
515 // set up the default cursor position and type.
518 hwDeviceExtension
->CursorPosition
.Column
= 0;
519 hwDeviceExtension
->CursorPosition
.Row
= 0;
520 hwDeviceExtension
->CursorTopScanLine
= 0;
521 hwDeviceExtension
->CursorBottomScanLine
= 31;
522 hwDeviceExtension
->CursorEnable
= TRUE
;
524 // eVb: 1.8 [VBE] - Initialize VBE modes
525 InitializeModeTable(hwDeviceExtension
);
531 //---------------------------------------------------------------------------
534 PVOID HwDeviceExtension
,
535 PVIDEO_REQUEST_PACKET RequestPacket
542 This routine is the main execution routine for the miniport driver. It
543 accepts a Video Request Packet, performs the request, and then returns
544 with the appropriate status.
548 HwDeviceExtension - Pointer to the miniport driver's adapter information.
550 RequestPacket - Pointer to the video request packet. This structure
551 contains all the parameters passed to the VideoIoControl function.
555 This routine will return error codes from the various support routines
556 and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
557 buffers and ERROR_INVALID_FUNCTION for unsupported functions.
562 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
564 VIDEO_MODE videoMode
;
565 PVIDEO_MEMORY_INFORMATION memoryInformation
;
570 // Switch on the IoContolCode in the RequestPacket. It indicates which
571 // function must be performed by the driver.
573 // eVb: 1.9 [IOCTL] - Remove IOCTLs not needed yet
574 switch (RequestPacket
->IoControlCode
)
576 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY
:
578 VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n"));
580 status
= ERROR_INVALID_FUNCTION
;
584 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY
:
586 VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n"));
588 status
= ERROR_INVALID_FUNCTION
;
593 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
595 VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
597 if ( (RequestPacket
->OutputBufferLength
<
598 (RequestPacket
->StatusBlock
->Information
=
599 sizeof(VIDEO_MEMORY_INFORMATION
))) ||
600 (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
)) )
602 status
= ERROR_INSUFFICIENT_BUFFER
;
605 memoryInformation
= RequestPacket
->OutputBuffer
;
607 memoryInformation
->VideoRamBase
= ((PVIDEO_MEMORY
)
608 (RequestPacket
->InputBuffer
))->RequestedVirtualAddress
;
611 // We reserved 16 meg for the frame buffer, however, it makes
612 // no sense to map more memory than there is on the card. So
613 // only map the amount of memory we have on the card.
615 // eVb: 1.10 [CIRRUS] - On VGA, we have VRAM size since boot, use it
616 memoryInformation
->VideoRamLength
=
617 hwDeviceExtension
->PhysicalVideoMemoryLength
;
620 // If you change to using a dense space frame buffer, make this
621 // value a 4 for the ALPHA.
626 status
= VideoPortMapMemory(hwDeviceExtension
,
627 hwDeviceExtension
->PhysicalVideoMemoryBase
,
628 // eVb: 1.11 [CIRRUS] - On VGA, we have VRAM size since boot, use it
629 &memoryInformation
->VideoRamLength
,
632 &(memoryInformation
->VideoRamBase
));
634 if (status
!= NO_ERROR
) {
635 VideoDebugPrint((0, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status
));
638 memoryInformation
->FrameBufferBase
=
639 ((PUCHAR
) (memoryInformation
->VideoRamBase
)) +
640 hwDeviceExtension
->PhysicalFrameOffset
.LowPart
;
642 memoryInformation
->FrameBufferLength
=
643 hwDeviceExtension
->PhysicalFrameLength
?
644 hwDeviceExtension
->PhysicalFrameLength
:
645 memoryInformation
->VideoRamLength
;
648 VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryBase
));
649 VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryLength
));
650 VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation
->VideoRamBase
));
651 VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation
->VideoRamLength
));
653 VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension
->PhysicalFrameOffset
.LowPart
));
654 VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation
->FrameBufferBase
));
655 VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension
->PhysicalFrameLength
));
656 VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation
->FrameBufferLength
));
660 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
662 VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
664 status
= ERROR_INVALID_FUNCTION
;
669 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
671 VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
673 status
= VgaQueryAvailableModes(HwDeviceExtension
,
674 (PVIDEO_MODE_INFORMATION
)
675 RequestPacket
->OutputBuffer
,
676 RequestPacket
->OutputBufferLength
,
677 &RequestPacket
->StatusBlock
->Information
);
682 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
684 VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
686 status
= VgaQueryNumberOfAvailableModes(HwDeviceExtension
,
688 RequestPacket
->OutputBuffer
,
689 RequestPacket
->OutputBufferLength
,
690 &RequestPacket
->StatusBlock
->Information
);
695 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
697 VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
699 status
= VgaQueryCurrentMode(HwDeviceExtension
,
700 (PVIDEO_MODE_INFORMATION
) RequestPacket
->OutputBuffer
,
701 RequestPacket
->OutputBufferLength
,
702 &RequestPacket
->StatusBlock
->Information
);
707 case IOCTL_VIDEO_SET_CURRENT_MODE
:
709 VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
711 status
= VgaSetMode(HwDeviceExtension
,
712 (PVIDEO_MODE
) RequestPacket
->InputBuffer
,
713 RequestPacket
->InputBufferLength
,
714 // eVb: 1.12 [SET MODE] - Use new output parameter for framebuffer update functionality
721 case IOCTL_VIDEO_RESET_DEVICE
:
723 VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
725 videoMode
.RequestedMode
= 0;
727 VgaSetMode(HwDeviceExtension
,
728 (PVIDEO_MODE
) &videoMode
,
730 // eVb: 1.13 [SET MODE] - Use new output parameter for framebuffer update functionality
735 // Always return succcess since settings the text mode will fail on
738 // Also, failiure to set the text mode is not fatal in any way, since
739 // this operation must be followed by another set mode operation.
747 case IOCTL_VIDEO_LOAD_AND_SET_FONT
:
749 VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
751 status
= ERROR_INVALID_FUNCTION
;
756 case IOCTL_VIDEO_QUERY_CURSOR_POSITION
:
758 VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
760 status
= ERROR_INVALID_FUNCTION
;
765 case IOCTL_VIDEO_SET_CURSOR_POSITION
:
767 VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
769 status
= ERROR_INVALID_FUNCTION
;
774 case IOCTL_VIDEO_QUERY_CURSOR_ATTR
:
776 VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
778 status
= ERROR_INVALID_FUNCTION
;
783 case IOCTL_VIDEO_SET_CURSOR_ATTR
:
785 VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
787 status
= ERROR_INVALID_FUNCTION
;
792 case IOCTL_VIDEO_SET_PALETTE_REGISTERS
:
794 VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
796 status
= VgaSetPaletteReg(HwDeviceExtension
,
797 (PVIDEO_PALETTE_DATA
) RequestPacket
->InputBuffer
,
798 RequestPacket
->InputBufferLength
);
803 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
805 VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
807 status
= VgaSetColorLookup(HwDeviceExtension
,
808 (PVIDEO_CLUT
) RequestPacket
->InputBuffer
,
809 RequestPacket
->InputBufferLength
);
814 case IOCTL_VIDEO_ENABLE_VDM
:
816 VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
818 status
= ERROR_INVALID_FUNCTION
;
823 case IOCTL_VIDEO_RESTORE_HARDWARE_STATE
:
825 VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
827 status
= ERROR_INVALID_FUNCTION
;
832 case IOCTL_VIDEO_SAVE_HARDWARE_STATE
:
834 VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
836 status
= ERROR_INVALID_FUNCTION
;
840 case IOCTL_VIDEO_GET_BANK_SELECT_CODE
:
842 VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
844 status
= ERROR_INVALID_FUNCTION
;
847 case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES
:
849 PVIDEO_PUBLIC_ACCESS_RANGES portAccess
;
850 ULONG physicalPortLength
;
852 VideoDebugPrint((2, "VgaStartIO - Query Public Address Ranges\n"));
854 if (RequestPacket
->OutputBufferLength
<
855 sizeof(VIDEO_PUBLIC_ACCESS_RANGES
))
857 status
= ERROR_INSUFFICIENT_BUFFER
;
861 RequestPacket
->StatusBlock
->Information
=
862 sizeof(VIDEO_PUBLIC_ACCESS_RANGES
);
864 portAccess
= RequestPacket
->OutputBuffer
;
867 // The first public access range is the IO ports.
870 portAccess
->VirtualAddress
= (PVOID
) NULL
;
871 portAccess
->InIoSpace
= TRUE
;
872 portAccess
->MappedInIoSpace
= portAccess
->InIoSpace
;
873 physicalPortLength
= VGA_MAX_IO_PORT
- VGA_BASE_IO_PORT
+ 1;
875 status
= VideoPortMapMemory(hwDeviceExtension
,
876 VgaAccessRange
->RangeStart
,
878 &(portAccess
->MappedInIoSpace
),
879 &(portAccess
->VirtualAddress
));
880 // eVb: 1.17 [GCG] - Fix lvalue error
881 portAccess
->VirtualAddress
= (PVOID
)((ULONG_PTR
)portAccess
->VirtualAddress
- VGA_BASE_IO_PORT
);
883 VideoDebugPrint((2, "VgaStartIO - mapping ports to (%x)\n", portAccess
->VirtualAddress
));
888 case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES
:
890 VideoDebugPrint((2, "VgaStartIO - Free Public Access Ranges\n"));
892 status
= ERROR_INVALID_FUNCTION
;
896 // if we get here, an invalid IoControlCode was specified.
901 VideoDebugPrint((0, "Fell through vga startIO routine - invalid command\n"));
903 status
= ERROR_INVALID_FUNCTION
;
909 RequestPacket
->StatusBlock
->Status
= status
;
916 //---------------------------------------------------------------------------
922 //---------------------------------------------------------------------------
925 PHW_DEVICE_EXTENSION HwDeviceExtension
932 This routine returns TRUE if a VGA is present. Determining whether a VGA
933 is present is a two-step process. First, this routine walks bits through
934 the Bit Mask register, to establish that there are readable indexed
935 registers (EGAs normally don't have readable registers, and other adapters
936 are unlikely to have indexed registers). This test is done first because
937 it's a non-destructive EGA rejection test (correctly rejects EGAs, but
938 doesn't potentially mess up the screen or the accessibility of display
939 memory). Normally, this would be an adequate test, but some EGAs have
940 readable registers, so next, we check for the existence of the Chain4 bit
941 in the Memory Mode register; this bit doesn't exist in EGAs. It's
942 conceivable that there are EGAs with readable registers and a register bit
943 where Chain4 is stored, although I don't know of any; if a better test yet
944 is needed, memory could be written to in Chain4 mode, and then examined
945 plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
946 supposed to do. However, the current test should be adequate to eliminate
947 just about all EGAs, and 100% of everything else.
949 If this function fails to find a VGA, it attempts to undo any damage it
950 may have inadvertently done while testing. The underlying assumption for
951 the damage control is that if there's any non-VGA adapter at the tested
952 ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
953 other adapters that use 3C4/5 or 3CE/F, and b), if there are other
954 adapters, I certainly don't know how to restore their original states. So
955 all error recovery is oriented toward putting an EGA back in a writable
956 state, so that error messages are visible. The EGA's state on entry is
957 assumed to be text mode, so the Memory Mode register is restored to the
958 default state for text mode.
960 If a VGA is found, the VGA is returned to its original state after
969 TRUE if a VGA is present, FALSE if not.
974 UCHAR originalGCAddr
;
975 UCHAR originalSCAddr
;
976 UCHAR originalBitMask
;
977 UCHAR originalReadMap
;
978 UCHAR originalMemoryMode
;
980 BOOLEAN returnStatus
;
983 // Remember the original state of the Graphics Controller Address register.
986 originalGCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
990 // Write the Read Map register with a known state so we can verify
991 // that it isn't changed after we fool with the Bit Mask. This ensures
992 // that we're dealing with indexed registers, since both the Read Map and
993 // the Bit Mask are addressed at GRAPH_DATA_PORT.
996 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
997 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1000 // If we can't read back the Graphics Address register setting we just
1001 // performed, it's not readable and this isn't a VGA.
1004 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1005 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_READ_MAP
) {
1011 // Set the Read Map register to a known state.
1014 originalReadMap
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1016 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1017 GRAPH_DATA_PORT
, READ_MAP_TEST_SETTING
);
1019 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1020 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
1023 // The Read Map setting we just performed can't be read back; not a
1024 // VGA. Restore the default Read Map state.
1027 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1028 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1034 // Remember the original setting of the Bit Mask register.
1037 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1038 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1039 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1040 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_BIT_MASK
) {
1043 // The Graphics Address register setting we just made can't be read
1044 // back; not a VGA. Restore the default Read Map state.
1047 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1048 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1049 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1050 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1055 originalBitMask
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1059 // Set up the initial test mask we'll write to and read from the Bit Mask.
1067 // Write the test mask to the Bit Mask.
1070 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1071 GRAPH_DATA_PORT
, testMask
);
1074 // Make sure the Bit Mask remembered the value.
1077 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1078 GRAPH_DATA_PORT
) != testMask
) {
1081 // The Bit Mask is not properly writable and readable; not a VGA.
1082 // Restore the Bit Mask and Read Map to their default states.
1085 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1086 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1087 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1088 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1089 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1090 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1096 // Cycle the mask for next time.
1101 } while (testMask
!= 0);
1104 // There's something readable at GRAPH_DATA_PORT; now switch back and
1105 // make sure that the Read Map register hasn't changed, to verify that
1106 // we're dealing with indexed registers.
1109 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1110 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1111 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1112 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
1115 // The Read Map is not properly writable and readable; not a VGA.
1116 // Restore the Bit Mask and Read Map to their default states, in case
1117 // this is an EGA, so subsequent writes to the screen aren't garbled.
1120 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1121 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1122 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1123 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1124 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1125 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1131 // We've pretty surely verified the existence of the Bit Mask register.
1132 // Put the Graphics Controller back to the original state.
1135 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1136 GRAPH_DATA_PORT
, originalReadMap
);
1137 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1138 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1139 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1140 GRAPH_DATA_PORT
, originalBitMask
);
1141 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1142 GRAPH_ADDRESS_PORT
, originalGCAddr
);
1145 // Now, check for the existence of the Chain4 bit.
1149 // Remember the original states of the Sequencer Address and Memory Mode
1153 originalSCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1155 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1156 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1157 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1158 SEQ_ADDRESS_PORT
) & SEQ_ADDR_MASK
) != IND_MEMORY_MODE
) {
1161 // Couldn't read back the Sequencer Address register setting we just
1167 originalMemoryMode
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1171 // Toggle the Chain4 bit and read back the result. This must be done during
1172 // sync reset, since we're changing the chaining state.
1176 // Begin sync reset.
1179 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1181 (IND_SYNC_RESET
+ (START_SYNC_RESET_VALUE
<< 8)));
1184 // Toggle the Chain4 bit.
1187 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1188 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1189 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1190 SEQ_DATA_PORT
, (UCHAR
)(originalMemoryMode
^ CHAIN4_MASK
));
1192 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1193 SEQ_DATA_PORT
) != (UCHAR
) (originalMemoryMode
^ CHAIN4_MASK
)) {
1196 // Chain4 bit not there; not a VGA.
1197 // Set text mode default for Memory Mode register.
1200 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1201 SEQ_DATA_PORT
, MEMORY_MODE_TEXT_DEFAULT
);
1206 VideoPortWritePortUshort((PUSHORT
) (HwDeviceExtension
->IOAddress
+
1208 (IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1210 returnStatus
= FALSE
;
1219 // Restore the original Memory Mode setting.
1222 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1223 SEQ_DATA_PORT
, originalMemoryMode
);
1229 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1231 (USHORT
)(IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1234 // Restore the original Sequencer Address setting.
1237 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1238 SEQ_ADDRESS_PORT
, originalSCAddr
);
1240 returnStatus
= TRUE
;
1243 return returnStatus
;
1248 //---------------------------------------------------------------------------
1251 PHW_DEVICE_EXTENSION HwDeviceExtension
,
1252 PVIDEO_PALETTE_DATA PaletteBuffer
,
1253 ULONG PaletteBufferSize
1258 Routine Description:
1260 This routine sets a specified portion of the EGA (not DAC) palette
1265 HwDeviceExtension - Pointer to the miniport driver's device extension.
1267 PaletteBuffer - Pointer to the structure containing the palette data.
1269 PaletteBufferSize - Length of the input buffer supplied by the user.
1273 NO_ERROR - information returned successfully
1275 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1277 ERROR_INVALID_PARAMETER - invalid palette size.
1285 // Check if the size of the data in the input buffer is large enough.
1288 if ((PaletteBufferSize
) < (sizeof(VIDEO_PALETTE_DATA
)) ||
1289 (PaletteBufferSize
< (sizeof(VIDEO_PALETTE_DATA
) +
1290 (sizeof(USHORT
) * (PaletteBuffer
->NumEntries
-1)) ))) {
1292 return ERROR_INSUFFICIENT_BUFFER
;
1297 // Check to see if the parameters are valid.
1300 if ( (PaletteBuffer
->FirstEntry
> VIDEO_MAX_COLOR_REGISTER
) ||
1301 (PaletteBuffer
->NumEntries
== 0) ||
1302 (PaletteBuffer
->FirstEntry
+ PaletteBuffer
->NumEntries
>
1303 VIDEO_MAX_PALETTE_REGISTER
+ 1 ) ) {
1305 return ERROR_INVALID_PARAMETER
;
1310 // Reset ATC to index mode
1313 VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1314 ATT_INITIALIZE_PORT_COLOR
);
1317 // Blast out our palette values.
1320 for (i
= 0; i
< PaletteBuffer
->NumEntries
; i
++) {
1322 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ ATT_ADDRESS_PORT
,
1323 (UCHAR
)(i
+PaletteBuffer
->FirstEntry
));
1325 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1326 ATT_DATA_WRITE_PORT
,
1327 (UCHAR
)PaletteBuffer
->Colors
[i
]);
1330 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ ATT_ADDRESS_PORT
,
1335 } // end VgaSetPaletteReg()
1338 //---------------------------------------------------------------------------
1341 PHW_DEVICE_EXTENSION HwDeviceExtension
,
1342 PVIDEO_CLUT ClutBuffer
,
1343 ULONG ClutBufferSize
1348 Routine Description:
1350 This routine sets a specified portion of the DAC color lookup table
1355 HwDeviceExtension - Pointer to the miniport driver's device extension.
1357 ClutBufferSize - Length of the input buffer supplied by the user.
1359 ClutBuffer - Pointer to the structure containing the color lookup table.
1363 NO_ERROR - information returned successfully
1365 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1367 ERROR_INVALID_PARAMETER - invalid clut size.
1372 PVIDEOMODE CurrentMode
= HwDeviceExtension
->CurrentMode
;
1376 // Check if the size of the data in the input buffer is large enough.
1379 if ( (ClutBufferSize
< sizeof(VIDEO_CLUT
) - sizeof(ULONG
)) ||
1380 (ClutBufferSize
< sizeof(VIDEO_CLUT
) +
1381 (sizeof(ULONG
) * (ClutBuffer
->NumEntries
- 1)) ) ) {
1383 return ERROR_INSUFFICIENT_BUFFER
;
1388 // Check to see if the parameters are valid.
1391 if ( (ClutBuffer
->NumEntries
== 0) ||
1392 (ClutBuffer
->FirstEntry
> VIDEO_MAX_COLOR_REGISTER
) ||
1393 (ClutBuffer
->FirstEntry
+ ClutBuffer
->NumEntries
>
1394 VIDEO_MAX_COLOR_REGISTER
+ 1) ) {
1396 return ERROR_INVALID_PARAMETER
;
1399 // eVb: 1.14 [VBE] - Add VBE color support
1404 if (CurrentMode
->bitsPerPlane
>= 8) return VbeSetColorLookup(HwDeviceExtension
, ClutBuffer
);
1407 // Path for VGA mode
1409 // eVb: 1.15 [VBE] - Add VBE support for non-VGA-compatible detected modes
1410 if (!CurrentMode
->NonVgaMode
)
1414 // Set CLUT registers directly on the hardware
1417 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1418 DAC_ADDRESS_WRITE_PORT
, (UCHAR
) ClutBuffer
->FirstEntry
);
1420 for (i
= 0; i
< ClutBuffer
->NumEntries
; i
++) {
1421 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1422 DAC_ADDRESS_WRITE_PORT
,
1423 (UCHAR
)(i
+ ClutBuffer
->FirstEntry
));
1425 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1427 ClutBuffer
->LookupTable
[i
].RgbArray
.Red
);
1429 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1431 ClutBuffer
->LookupTable
[i
].RgbArray
.Green
);
1433 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1435 ClutBuffer
->LookupTable
[i
].RgbArray
.Blue
);
1440 return ERROR_INVALID_PARAMETER
;
1442 } // end VgaSetColorLookup()
1445 GetDeviceDataCallback(
1446 PVOID HwDeviceExtension
,
1448 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
1450 ULONG IdentifierLength
,
1451 PVOID ConfigurationData
,
1452 ULONG ConfigurationDataLength
,
1453 PVOID ComponentInformation
,
1454 ULONG ComponentInformationLength
1459 Routine Description:
1461 Callback routine for the VideoPortGetDeviceData function.
1465 HwDeviceExtension - Pointer to the miniport drivers device extension.
1467 Context - Context value passed to the VideoPortGetDeviceData function.
1469 DeviceDataType - The type of data that was requested in
1470 VideoPortGetDeviceData.
1472 Identifier - Pointer to a string that contains the name of the device,
1473 as setup by the ROM or ntdetect.
1475 IdentifierLength - Length of the Identifier string.
1477 ConfigurationData - Pointer to the configuration data for the device or
1480 ConfigurationDataLength - Length of the data in the configurationData
1483 ComponentInformation - Undefined.
1485 ComponentInformationLength - Undefined.
1489 Returns NO_ERROR if the function completed properly.
1490 Returns ERROR_DEV_NOT_EXIST if we did not find the device.
1491 Returns ERROR_INVALID_PARAMETER otherwise.
1496 VideoPortDebugPrint(Error
, "Detected internal VGA chip on embedded board, todo\n");
1500 } //end GetDeviceDataCallback()
1502 // eVb: 1.16 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
1504 VgaAcquireResources(
1505 PHW_DEVICE_EXTENSION DeviceExtension
1508 VP_STATUS Status
= NO_ERROR
;
1512 // Try exclusive ranges (vga + ati)
1515 Ranges
= NUM_VGA_ACCESS_RANGES
;
1516 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= FALSE
;
1517 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1520 // Not worked, try vga only
1524 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1527 // Still not, try shared ranges
1530 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1531 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);
1532 if (Status
== NO_ERROR
)
1538 VideoPortVerifyAccessRanges(DeviceExtension
, 0, 0);
1544 if (Status
== NO_ERROR
)
1547 // Worked with exclusive, also try shared
1550 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1551 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);