2 * PROJECT: ReactOS VGA Miniport Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: win32ss/drivers/miniport/vga_new/vga.c
5 * PURPOSE: Main Standard VGA-compatible Minport Handling Code
6 * PROGRAMMERS: Copyright (c) 1992 Microsoft Corporation
7 * ReactOS Portable Systems Group
10 //---------------------------------------------------------------------------
16 //---------------------------------------------------------------------------
18 // Function declarations
20 // Functions that start with 'VGA' are entry points for the OS port driver.
26 PVOID HwDeviceExtension
,
29 PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
36 PVOID HwDeviceExtension
42 PVOID HwDeviceExtension
,
43 PVIDEO_REQUEST_PACKET RequestPacket
47 // Private function prototypes.
52 VgaQueryAvailableModes(
53 PHW_DEVICE_EXTENSION HwDeviceExtension
,
54 PVIDEO_MODE_INFORMATION ModeInformation
,
55 ULONG ModeInformationSize
,
61 VgaQueryNumberOfAvailableModes(
62 PHW_DEVICE_EXTENSION HwDeviceExtension
,
63 PVIDEO_NUM_MODES NumModes
,
71 PHW_DEVICE_EXTENSION HwDeviceExtension
,
72 PVIDEO_MODE_INFORMATION ModeInformation
,
73 ULONG ModeInformationSize
,
80 PHW_DEVICE_EXTENSION HwDeviceExtension
,
83 // eVb: 1.1 [SET MODE] - Add new output parameter for framebuffer update functionality
91 PHW_DEVICE_EXTENSION HwDeviceExtension
96 VgaInterpretCmdStream(
97 PVOID HwDeviceExtension
,
104 PHW_DEVICE_EXTENSION HwDeviceExtension
,
105 PVIDEO_PALETTE_DATA PaletteBuffer
,
106 ULONG PaletteBufferSize
112 PHW_DEVICE_EXTENSION HwDeviceExtension
,
113 PVIDEO_CLUT ClutBuffer
,
119 GetDeviceDataCallback(
120 PVOID HwDeviceExtension
,
122 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
124 ULONG IdentifierLength
,
125 PVOID ConfigurationData
,
126 ULONG ConfigurationDataLength
,
127 PVOID ComponentInformation
,
128 ULONG ComponentInformationLength
131 // eVb: 1.2 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
135 PHW_DEVICE_EXTENSION DeviceExtension
139 #if defined(ALLOC_PRAGMA)
140 #pragma alloc_text(PAGE,DriverEntry)
141 #pragma alloc_text(PAGE,VgaFindAdapter)
142 #pragma alloc_text(PAGE,VgaInitialize)
143 #pragma alloc_text(PAGE,VgaStartIO)
144 #pragma alloc_text(PAGE,VgaIsPresent)
145 #pragma alloc_text(PAGE,VgaSetColorLookup)
148 //---------------------------------------------------------------------------
150 // eVb: 1.3 [GCC] - Add NTAPI for GCC support
162 Installable driver initialization entry point.
163 This entry point is called directly by the I/O system.
167 Context1 - First context value passed by the operating system. This is
168 the value with which the miniport driver calls VideoPortInitialize().
170 Context2 - Second context value passed by the operating system. This is
171 the value with which the miniport driver calls 3VideoPortInitialize().
175 Status from VideoPortInitialize()
181 VIDEO_HW_INITIALIZATION_DATA hwInitData
;
183 ULONG initializationStatus
= (ULONG
) -1;
186 // Zero out structure.
189 VideoPortZeroMemory(&hwInitData
, sizeof(VIDEO_HW_INITIALIZATION_DATA
));
192 // Specify sizes of structure and extension.
195 hwInitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
201 hwInitData
.HwFindAdapter
= VgaFindAdapter
;
202 hwInitData
.HwInitialize
= VgaInitialize
;
203 hwInitData
.HwInterrupt
= NULL
;
204 hwInitData
.HwStartIO
= VgaStartIO
;
207 // Determine the size we require for the device extension.
210 hwInitData
.HwDeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
213 // Always start with parameters for device0 in this case.
214 // We can leave it like this since we know we will only ever find one
215 // VGA type adapter in a machine.
218 // hwInitData.StartingDeviceNumber = 0;
221 // Once all the relevant information has been stored, call the video
222 // port driver to do the initialization.
223 // For this device we will repeat this call three times, for ISA, EISA
225 // We will return the minimum of all return values.
229 // We will try the PCI bus first so that our ISA detection does'nt claim
230 // PCI cards (since it is impossible to differentiate between the two
231 // by looking at the registers).
235 // NOTE: since this driver only supports one adapter, we will return
236 // as soon as we find a device, without going on to the following buses.
237 // Normally one would call for each bus type and return the smallest
241 #if !defined(_ALPHA_)
244 // Before we can enable this on ALPHA we need to find a way to map a
245 // sparse view of a 4MB region successfully.
248 hwInitData
.AdapterInterfaceType
= PCIBus
;
250 initializationStatus
= VideoPortInitialize(Context1
,
255 if (initializationStatus
== NO_ERROR
)
257 return initializationStatus
;
262 hwInitData
.AdapterInterfaceType
= MicroChannel
;
264 initializationStatus
= VideoPortInitialize(Context1
,
270 // Return immediately instead of checkin for smallest return code.
273 if (initializationStatus
== NO_ERROR
)
275 return initializationStatus
;
279 hwInitData
.AdapterInterfaceType
= Internal
;
281 initializationStatus
= VideoPortInitialize(Context1
,
286 if (initializationStatus
== NO_ERROR
)
288 return initializationStatus
;
292 hwInitData
.AdapterInterfaceType
= Isa
;
294 initializationStatus
= VideoPortInitialize(Context1
,
299 if (initializationStatus
== NO_ERROR
)
301 return initializationStatus
;
306 hwInitData
.AdapterInterfaceType
= Eisa
;
308 status
= VideoPortInitialize(Context1
,
313 if (initializationStatus
> status
) {
314 initializationStatus
= status
;
317 return initializationStatus
;
319 } // end DriverEntry()
321 //---------------------------------------------------------------------------
325 PVOID HwDeviceExtension
,
327 PWSTR ArgumentString
,
328 PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
336 This routine is called to determine if the adapter for this driver
337 is present in the system.
338 If it is present, the function fills out some information describing
343 HwDeviceExtension - Supplies the miniport driver's adapter storage. This
344 storage is initialized to zero before this call.
346 HwContext - Supplies the context value which was passed to
347 VideoPortInitialize().
349 ArgumentString - Supplies a NULL terminated ASCII string. This string
350 originates from the user.
352 ConfigInfo - Returns the configuration information structure which is
353 filled by the miniport driver. This structure is initialized with
354 any known configuration information (such as SystemIoBusNumber) by
355 the port driver. Where possible, drivers should have one set of
356 defaults which do not require any supplied configuration information.
358 Again - Indicates if the miniport driver wants the port driver to call
359 its VIDEO_HW_FIND_ADAPTER function again with a new device extension
360 and the same config info. This is used by the miniport drivers which
361 can search for several adapters on a bus.
365 This routine must return:
367 NO_ERROR - Indicates a host adapter was found and the
368 configuration information was successfully determined.
370 ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
371 error obtaining the configuration information. If possible an error
374 ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
375 supplied configuration information.
381 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
384 // Make sure the size of the structure is at least as large as what we
385 // are expecting (check version of the config info structure).
388 if (ConfigInfo
->Length
< sizeof(VIDEO_PORT_CONFIG_INFO
)) {
390 return ERROR_INVALID_PARAMETER
;
393 // eVb: 1.4 [CIRRUS] - Remove CIRRUS-specific support
395 // Check internal VGA (MIPS and ARM systems)
398 if ((ConfigInfo
->AdapterInterfaceType
== Internal
) &&
399 (VideoPortGetDeviceData(HwDeviceExtension
,
401 &GetDeviceDataCallback
,
402 VgaAccessRange
) != NO_ERROR
))
404 return ERROR_INVALID_PARAMETER
;
408 // No interrupt information is necessary.
412 // Check to see if there is a hardware resource conflict.
414 // eVb: 1.5 [RESOURCE] - Use new function for acquiring VGA resources (I/O, memory)
415 if (VgaAcquireResources(hwDeviceExtension
) != NO_ERROR
) return ERROR_INVALID_PARAMETER
;
418 // Get logical IO port addresses.
421 if ((hwDeviceExtension
->IOAddress
=
422 VideoPortGetDeviceBase(hwDeviceExtension
,
423 VgaAccessRange
->RangeStart
,
424 VGA_MAX_IO_PORT
- VGA_BASE_IO_PORT
+ 1,
425 VgaAccessRange
->RangeInIoSpace
)) == NULL
)
427 VideoDebugPrint((0, "VgaFindAdapter - Fail to get io address\n"));
429 return ERROR_INVALID_PARAMETER
;
433 // Determine whether a VGA is present.
436 if (!VgaIsPresent(hwDeviceExtension
)) {
438 VideoDebugPrint((0, "VgaFindAdapter - VGA Failed\n"));
439 return ERROR_DEV_NOT_EXIST
;
443 // Minimum size of the buffer required to store the hardware state
444 // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
447 ConfigInfo
->HardwareStateSize
= VGA_TOTAL_STATE_SIZE
;
450 // Pass a pointer to the emulator range we are using.
452 // eVb: 1.6 [VDM] - Disable VDM for now
453 ConfigInfo
->NumEmulatorAccessEntries
= 0;
454 ConfigInfo
->EmulatorAccessEntries
= NULL
;
455 ConfigInfo
->EmulatorAccessEntriesContext
= 0;
460 // There is really no reason to have the frame buffer mapped. On an
461 // x86 we use if for save/restore (supposedly) but even then we
462 // would only need to map a 64K window, not all 16 Meg!
468 // Map the video memory into the system virtual address space so we can
469 // clear it out and use it for save and restore.
472 if ( (hwDeviceExtension
->VideoMemoryAddress
=
473 VideoPortGetDeviceBase(hwDeviceExtension
,
474 VgaAccessRange
[2].RangeStart
,
475 VgaAccessRange
[2].RangeLength
,
478 VideoDebugPrint((0, "VgaFindAdapter - Fail to get memory address\n"));
480 return ERROR_INVALID_PARAMETER
;
483 VideoDebugPrint((0, "vga mapped at %x\n", hwDeviceExtension
->VideoMemoryAddress
));
485 // eVb: 1.7 [VDM] - Disable VDM for now
486 ConfigInfo
->VdmPhysicalVideoMemoryAddress
.QuadPart
= 0;
487 ConfigInfo
->VdmPhysicalVideoMemoryLength
= 0;
490 // Indicate we do not wish to be called again for another initialization.
496 // Indicate a successful completion status.
502 } // VgaFindAdapter()
504 //---------------------------------------------------------------------------
508 PVOID HwDeviceExtension
515 This routine does one time initialization of the device.
519 HwDeviceExtension - Pointer to the miniport driver's adapter information.
528 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
531 // set up the default cursor position and type.
534 hwDeviceExtension
->CursorPosition
.Column
= 0;
535 hwDeviceExtension
->CursorPosition
.Row
= 0;
536 hwDeviceExtension
->CursorTopScanLine
= 0;
537 hwDeviceExtension
->CursorBottomScanLine
= 31;
538 hwDeviceExtension
->CursorEnable
= TRUE
;
540 // eVb: 1.8 [VBE] - Initialize VBE modes
541 InitializeModeTable(hwDeviceExtension
);
547 //---------------------------------------------------------------------------
551 PVOID HwDeviceExtension
,
552 PVIDEO_REQUEST_PACKET RequestPacket
559 This routine is the main execution routine for the miniport driver. It
560 accepts a Video Request Packet, performs the request, and then returns
561 with the appropriate status.
565 HwDeviceExtension - Pointer to the miniport driver's adapter information.
567 RequestPacket - Pointer to the video request packet. This structure
568 contains all the parameters passed to the VideoIoControl function.
572 This routine will return error codes from the various support routines
573 and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
574 buffers and ERROR_INVALID_FUNCTION for unsupported functions.
579 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
581 VIDEO_MODE videoMode
;
582 PVIDEO_MEMORY_INFORMATION memoryInformation
;
587 // Switch on the IoContolCode in the RequestPacket. It indicates which
588 // function must be performed by the driver.
590 // eVb: 1.9 [IOCTL] - Remove IOCTLs not needed yet
591 switch (RequestPacket
->IoControlCode
)
593 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY
:
595 VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n"));
597 status
= ERROR_INVALID_FUNCTION
;
601 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY
:
603 VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n"));
605 status
= ERROR_INVALID_FUNCTION
;
610 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
612 VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
614 if ( (RequestPacket
->OutputBufferLength
<
615 (RequestPacket
->StatusBlock
->Information
=
616 sizeof(VIDEO_MEMORY_INFORMATION
))) ||
617 (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
)) )
619 status
= ERROR_INSUFFICIENT_BUFFER
;
622 memoryInformation
= RequestPacket
->OutputBuffer
;
624 memoryInformation
->VideoRamBase
= ((PVIDEO_MEMORY
)
625 (RequestPacket
->InputBuffer
))->RequestedVirtualAddress
;
628 // We reserved 16 meg for the frame buffer, however, it makes
629 // no sense to map more memory than there is on the card. So
630 // only map the amount of memory we have on the card.
632 // eVb: 1.10 [CIRRUS] - On VGA, we have VRAM size since boot, use it
633 memoryInformation
->VideoRamLength
=
634 hwDeviceExtension
->PhysicalVideoMemoryLength
;
637 // If you change to using a dense space frame buffer, make this
638 // value a 4 for the ALPHA.
643 status
= VideoPortMapMemory(hwDeviceExtension
,
644 hwDeviceExtension
->PhysicalVideoMemoryBase
,
645 // eVb: 1.11 [CIRRUS] - On VGA, we have VRAM size since boot, use it
646 &memoryInformation
->VideoRamLength
,
649 &(memoryInformation
->VideoRamBase
));
651 if (status
!= NO_ERROR
) {
652 VideoDebugPrint((0, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status
));
655 memoryInformation
->FrameBufferBase
=
656 ((PUCHAR
) (memoryInformation
->VideoRamBase
)) +
657 hwDeviceExtension
->PhysicalFrameOffset
.LowPart
;
659 memoryInformation
->FrameBufferLength
=
660 hwDeviceExtension
->PhysicalFrameLength
?
661 hwDeviceExtension
->PhysicalFrameLength
:
662 memoryInformation
->VideoRamLength
;
665 VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryBase
));
666 VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryLength
));
667 VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation
->VideoRamBase
));
668 VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation
->VideoRamLength
));
670 VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension
->PhysicalFrameOffset
.LowPart
));
671 VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation
->FrameBufferBase
));
672 VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension
->PhysicalFrameLength
));
673 VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation
->FrameBufferLength
));
677 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
679 VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
681 status
= ERROR_INVALID_FUNCTION
;
686 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
688 VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
690 status
= VgaQueryAvailableModes(HwDeviceExtension
,
691 (PVIDEO_MODE_INFORMATION
)
692 RequestPacket
->OutputBuffer
,
693 RequestPacket
->OutputBufferLength
,
694 &RequestPacket
->StatusBlock
->Information
);
699 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
701 VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
703 status
= VgaQueryNumberOfAvailableModes(HwDeviceExtension
,
705 RequestPacket
->OutputBuffer
,
706 RequestPacket
->OutputBufferLength
,
707 &RequestPacket
->StatusBlock
->Information
);
712 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
714 VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
716 status
= VgaQueryCurrentMode(HwDeviceExtension
,
717 (PVIDEO_MODE_INFORMATION
) RequestPacket
->OutputBuffer
,
718 RequestPacket
->OutputBufferLength
,
719 &RequestPacket
->StatusBlock
->Information
);
724 case IOCTL_VIDEO_SET_CURRENT_MODE
:
726 VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
728 status
= VgaSetMode(HwDeviceExtension
,
729 (PVIDEO_MODE
) RequestPacket
->InputBuffer
,
730 RequestPacket
->InputBufferLength
,
731 // eVb: 1.12 [SET MODE] - Use new output parameter for framebuffer update functionality
738 case IOCTL_VIDEO_RESET_DEVICE
:
740 VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
742 videoMode
.RequestedMode
= 0;
744 VgaSetMode(HwDeviceExtension
,
745 (PVIDEO_MODE
) &videoMode
,
747 // eVb: 1.13 [SET MODE] - Use new output parameter for framebuffer update functionality
752 // Always return succcess since settings the text mode will fail on
755 // Also, failiure to set the text mode is not fatal in any way, since
756 // this operation must be followed by another set mode operation.
764 case IOCTL_VIDEO_LOAD_AND_SET_FONT
:
766 VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
768 status
= ERROR_INVALID_FUNCTION
;
773 case IOCTL_VIDEO_QUERY_CURSOR_POSITION
:
775 VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
777 status
= ERROR_INVALID_FUNCTION
;
782 case IOCTL_VIDEO_SET_CURSOR_POSITION
:
784 VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
786 status
= ERROR_INVALID_FUNCTION
;
791 case IOCTL_VIDEO_QUERY_CURSOR_ATTR
:
793 VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
795 status
= ERROR_INVALID_FUNCTION
;
800 case IOCTL_VIDEO_SET_CURSOR_ATTR
:
802 VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
804 status
= ERROR_INVALID_FUNCTION
;
809 case IOCTL_VIDEO_SET_PALETTE_REGISTERS
:
811 VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
813 status
= VgaSetPaletteReg(HwDeviceExtension
,
814 (PVIDEO_PALETTE_DATA
) RequestPacket
->InputBuffer
,
815 RequestPacket
->InputBufferLength
);
820 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
822 VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
824 status
= VgaSetColorLookup(HwDeviceExtension
,
825 (PVIDEO_CLUT
) RequestPacket
->InputBuffer
,
826 RequestPacket
->InputBufferLength
);
831 case IOCTL_VIDEO_ENABLE_VDM
:
833 VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
835 status
= ERROR_INVALID_FUNCTION
;
840 case IOCTL_VIDEO_RESTORE_HARDWARE_STATE
:
842 VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
844 status
= ERROR_INVALID_FUNCTION
;
849 case IOCTL_VIDEO_SAVE_HARDWARE_STATE
:
851 VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
853 status
= ERROR_INVALID_FUNCTION
;
857 case IOCTL_VIDEO_GET_BANK_SELECT_CODE
:
859 VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
861 status
= ERROR_INVALID_FUNCTION
;
864 case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES
:
866 PVIDEO_PUBLIC_ACCESS_RANGES portAccess
;
867 ULONG physicalPortLength
;
869 VideoDebugPrint((2, "VgaStartIO - Query Public Address Ranges\n"));
871 if (RequestPacket
->OutputBufferLength
<
872 sizeof(VIDEO_PUBLIC_ACCESS_RANGES
))
874 status
= ERROR_INSUFFICIENT_BUFFER
;
878 RequestPacket
->StatusBlock
->Information
=
879 sizeof(VIDEO_PUBLIC_ACCESS_RANGES
);
881 portAccess
= RequestPacket
->OutputBuffer
;
884 // The first public access range is the IO ports.
887 portAccess
->VirtualAddress
= (PVOID
) NULL
;
888 portAccess
->InIoSpace
= TRUE
;
889 portAccess
->MappedInIoSpace
= portAccess
->InIoSpace
;
890 physicalPortLength
= VGA_MAX_IO_PORT
- VGA_BASE_IO_PORT
+ 1;
892 status
= VideoPortMapMemory(hwDeviceExtension
,
893 VgaAccessRange
->RangeStart
,
895 &(portAccess
->MappedInIoSpace
),
896 &(portAccess
->VirtualAddress
));
897 // eVb: 1.17 [GCG] - Fix lvalue error
898 portAccess
->VirtualAddress
= (PVOID
)((ULONG_PTR
)portAccess
->VirtualAddress
- VGA_BASE_IO_PORT
);
900 VideoDebugPrint((2, "VgaStartIO - mapping ports to (%x)\n", portAccess
->VirtualAddress
));
905 case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES
:
907 VideoDebugPrint((2, "VgaStartIO - Free Public Access Ranges\n"));
909 status
= ERROR_INVALID_FUNCTION
;
913 // if we get here, an invalid IoControlCode was specified.
918 VideoDebugPrint((0, "Fell through vga startIO routine - invalid command\n"));
920 status
= ERROR_INVALID_FUNCTION
;
926 RequestPacket
->StatusBlock
->Status
= status
;
932 //---------------------------------------------------------------------------
937 //---------------------------------------------------------------------------
941 PHW_DEVICE_EXTENSION HwDeviceExtension
948 This routine returns TRUE if a VGA is present. Determining whether a VGA
949 is present is a two-step process. First, this routine walks bits through
950 the Bit Mask register, to establish that there are readable indexed
951 registers (EGAs normally don't have readable registers, and other adapters
952 are unlikely to have indexed registers). This test is done first because
953 it's a non-destructive EGA rejection test (correctly rejects EGAs, but
954 doesn't potentially mess up the screen or the accessibility of display
955 memory). Normally, this would be an adequate test, but some EGAs have
956 readable registers, so next, we check for the existence of the Chain4 bit
957 in the Memory Mode register; this bit doesn't exist in EGAs. It's
958 conceivable that there are EGAs with readable registers and a register bit
959 where Chain4 is stored, although I don't know of any; if a better test yet
960 is needed, memory could be written to in Chain4 mode, and then examined
961 plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
962 supposed to do. However, the current test should be adequate to eliminate
963 just about all EGAs, and 100% of everything else.
965 If this function fails to find a VGA, it attempts to undo any damage it
966 may have inadvertently done while testing. The underlying assumption for
967 the damage control is that if there's any non-VGA adapter at the tested
968 ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
969 other adapters that use 3C4/5 or 3CE/F, and b), if there are other
970 adapters, I certainly don't know how to restore their original states. So
971 all error recovery is oriented toward putting an EGA back in a writable
972 state, so that error messages are visible. The EGA's state on entry is
973 assumed to be text mode, so the Memory Mode register is restored to the
974 default state for text mode.
976 If a VGA is found, the VGA is returned to its original state after
985 TRUE if a VGA is present, FALSE if not.
990 UCHAR originalGCAddr
;
991 UCHAR originalSCAddr
;
992 UCHAR originalBitMask
;
993 UCHAR originalReadMap
;
994 UCHAR originalMemoryMode
;
996 BOOLEAN returnStatus
;
999 // Remember the original state of the Graphics Controller Address register.
1002 originalGCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1003 GRAPH_ADDRESS_PORT
);
1006 // Write the Read Map register with a known state so we can verify
1007 // that it isn't changed after we fool with the Bit Mask. This ensures
1008 // that we're dealing with indexed registers, since both the Read Map and
1009 // the Bit Mask are addressed at GRAPH_DATA_PORT.
1012 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1013 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1016 // If we can't read back the Graphics Address register setting we just
1017 // performed, it's not readable and this isn't a VGA.
1020 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1021 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_READ_MAP
) {
1027 // Set the Read Map register to a known state.
1030 originalReadMap
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1032 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1033 GRAPH_DATA_PORT
, READ_MAP_TEST_SETTING
);
1035 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1036 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
1039 // The Read Map setting we just performed can't be read back; not a
1040 // VGA. Restore the default Read Map state.
1043 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1044 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1050 // Remember the original setting of the Bit Mask register.
1053 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1054 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1055 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1056 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_BIT_MASK
) {
1059 // The Graphics Address register setting we just made can't be read
1060 // back; not a VGA. Restore the default Read Map state.
1063 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1064 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1065 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1066 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1071 originalBitMask
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1075 // Set up the initial test mask we'll write to and read from the Bit Mask.
1083 // Write the test mask to the Bit Mask.
1086 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1087 GRAPH_DATA_PORT
, testMask
);
1090 // Make sure the Bit Mask remembered the value.
1093 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1094 GRAPH_DATA_PORT
) != testMask
) {
1097 // The Bit Mask is not properly writable and readable; not a VGA.
1098 // Restore the Bit Mask and Read Map to their default states.
1101 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1102 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1103 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1104 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1105 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1106 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1112 // Cycle the mask for next time.
1117 } while (testMask
!= 0);
1120 // There's something readable at GRAPH_DATA_PORT; now switch back and
1121 // make sure that the Read Map register hasn't changed, to verify that
1122 // we're dealing with indexed registers.
1125 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1126 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1127 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1128 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
1131 // The Read Map is not properly writable and readable; not a VGA.
1132 // Restore the Bit Mask and Read Map to their default states, in case
1133 // this is an EGA, so subsequent writes to the screen aren't garbled.
1136 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1137 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1138 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1139 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1140 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1141 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1147 // We've pretty surely verified the existence of the Bit Mask register.
1148 // Put the Graphics Controller back to the original state.
1151 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1152 GRAPH_DATA_PORT
, originalReadMap
);
1153 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1154 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1155 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1156 GRAPH_DATA_PORT
, originalBitMask
);
1157 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1158 GRAPH_ADDRESS_PORT
, originalGCAddr
);
1161 // Now, check for the existence of the Chain4 bit.
1165 // Remember the original states of the Sequencer Address and Memory Mode
1169 originalSCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1171 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1172 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1173 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1174 SEQ_ADDRESS_PORT
) & SEQ_ADDR_MASK
) != IND_MEMORY_MODE
) {
1177 // Couldn't read back the Sequencer Address register setting we just
1183 originalMemoryMode
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1187 // Toggle the Chain4 bit and read back the result. This must be done during
1188 // sync reset, since we're changing the chaining state.
1192 // Begin sync reset.
1195 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1197 (IND_SYNC_RESET
+ (START_SYNC_RESET_VALUE
<< 8)));
1200 // Toggle the Chain4 bit.
1203 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1204 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1205 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1206 SEQ_DATA_PORT
, (UCHAR
)(originalMemoryMode
^ CHAIN4_MASK
));
1208 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1209 SEQ_DATA_PORT
) != (UCHAR
) (originalMemoryMode
^ CHAIN4_MASK
)) {
1212 // Chain4 bit not there; not a VGA.
1213 // Set text mode default for Memory Mode register.
1216 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1217 SEQ_DATA_PORT
, MEMORY_MODE_TEXT_DEFAULT
);
1222 VideoPortWritePortUshort((PUSHORT
) (HwDeviceExtension
->IOAddress
+
1224 (IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1226 returnStatus
= FALSE
;
1235 // Restore the original Memory Mode setting.
1238 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1239 SEQ_DATA_PORT
, originalMemoryMode
);
1245 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1247 (USHORT
)(IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1250 // Restore the original Sequencer Address setting.
1253 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1254 SEQ_ADDRESS_PORT
, originalSCAddr
);
1256 returnStatus
= TRUE
;
1259 return returnStatus
;
1263 //---------------------------------------------------------------------------
1267 PHW_DEVICE_EXTENSION HwDeviceExtension
,
1268 PVIDEO_PALETTE_DATA PaletteBuffer
,
1269 ULONG PaletteBufferSize
1274 Routine Description:
1276 This routine sets a specified portion of the EGA (not DAC) palette
1281 HwDeviceExtension - Pointer to the miniport driver's device extension.
1283 PaletteBuffer - Pointer to the structure containing the palette data.
1285 PaletteBufferSize - Length of the input buffer supplied by the user.
1289 NO_ERROR - information returned successfully
1291 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1293 ERROR_INVALID_PARAMETER - invalid palette size.
1301 // Check if the size of the data in the input buffer is large enough.
1304 if ((PaletteBufferSize
) < (sizeof(VIDEO_PALETTE_DATA
)) ||
1305 (PaletteBufferSize
< (sizeof(VIDEO_PALETTE_DATA
) +
1306 (sizeof(USHORT
) * (PaletteBuffer
->NumEntries
-1)) ))) {
1308 return ERROR_INSUFFICIENT_BUFFER
;
1313 // Check to see if the parameters are valid.
1316 if ( (PaletteBuffer
->FirstEntry
> VIDEO_MAX_COLOR_REGISTER
) ||
1317 (PaletteBuffer
->NumEntries
== 0) ||
1318 (PaletteBuffer
->FirstEntry
+ PaletteBuffer
->NumEntries
>
1319 VIDEO_MAX_PALETTE_REGISTER
+ 1 ) ) {
1321 return ERROR_INVALID_PARAMETER
;
1326 // Reset ATC to index mode
1329 VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1330 ATT_INITIALIZE_PORT_COLOR
);
1333 // Blast out our palette values.
1336 for (i
= 0; i
< PaletteBuffer
->NumEntries
; i
++) {
1338 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ ATT_ADDRESS_PORT
,
1339 (UCHAR
)(i
+PaletteBuffer
->FirstEntry
));
1341 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1342 ATT_DATA_WRITE_PORT
,
1343 (UCHAR
)PaletteBuffer
->Colors
[i
]);
1346 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ ATT_ADDRESS_PORT
,
1351 } // end VgaSetPaletteReg()
1353 //---------------------------------------------------------------------------
1357 PHW_DEVICE_EXTENSION HwDeviceExtension
,
1358 PVIDEO_CLUT ClutBuffer
,
1359 ULONG ClutBufferSize
1364 Routine Description:
1366 This routine sets a specified portion of the DAC color lookup table
1371 HwDeviceExtension - Pointer to the miniport driver's device extension.
1373 ClutBufferSize - Length of the input buffer supplied by the user.
1375 ClutBuffer - Pointer to the structure containing the color lookup table.
1379 NO_ERROR - information returned successfully
1381 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1383 ERROR_INVALID_PARAMETER - invalid clut size.
1388 PVIDEOMODE CurrentMode
= HwDeviceExtension
->CurrentMode
;
1392 // Check if the size of the data in the input buffer is large enough.
1395 if ( (ClutBufferSize
< sizeof(VIDEO_CLUT
) - sizeof(ULONG
)) ||
1396 (ClutBufferSize
< sizeof(VIDEO_CLUT
) +
1397 (sizeof(ULONG
) * (ClutBuffer
->NumEntries
- 1)) ) ) {
1399 return ERROR_INSUFFICIENT_BUFFER
;
1404 // Check to see if the parameters are valid.
1407 if ( (ClutBuffer
->NumEntries
== 0) ||
1408 (ClutBuffer
->FirstEntry
> VIDEO_MAX_COLOR_REGISTER
) ||
1409 (ClutBuffer
->FirstEntry
+ ClutBuffer
->NumEntries
>
1410 VIDEO_MAX_COLOR_REGISTER
+ 1) ) {
1412 return ERROR_INVALID_PARAMETER
;
1415 // eVb: 1.14 [VBE] - Add VBE color support
1420 if (CurrentMode
->bitsPerPlane
>= 8) return VbeSetColorLookup(HwDeviceExtension
, ClutBuffer
);
1423 // Path for VGA mode
1425 // eVb: 1.15 [VBE] - Add VBE support for non-VGA-compatible detected modes
1426 if (!CurrentMode
->NonVgaMode
)
1430 // Set CLUT registers directly on the hardware
1433 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1434 DAC_ADDRESS_WRITE_PORT
, (UCHAR
) ClutBuffer
->FirstEntry
);
1436 for (i
= 0; i
< ClutBuffer
->NumEntries
; i
++) {
1437 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1438 DAC_ADDRESS_WRITE_PORT
,
1439 (UCHAR
)(i
+ ClutBuffer
->FirstEntry
));
1441 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1443 ClutBuffer
->LookupTable
[i
].RgbArray
.Red
);
1445 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1447 ClutBuffer
->LookupTable
[i
].RgbArray
.Green
);
1449 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1451 ClutBuffer
->LookupTable
[i
].RgbArray
.Blue
);
1456 return ERROR_INVALID_PARAMETER
;
1458 } // end VgaSetColorLookup()
1462 GetDeviceDataCallback(
1463 PVOID HwDeviceExtension
,
1465 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
1467 ULONG IdentifierLength
,
1468 PVOID ConfigurationData
,
1469 ULONG ConfigurationDataLength
,
1470 PVOID ComponentInformation
,
1471 ULONG ComponentInformationLength
1476 Routine Description:
1478 Callback routine for the VideoPortGetDeviceData function.
1482 HwDeviceExtension - Pointer to the miniport drivers device extension.
1484 Context - Context value passed to the VideoPortGetDeviceData function.
1486 DeviceDataType - The type of data that was requested in
1487 VideoPortGetDeviceData.
1489 Identifier - Pointer to a string that contains the name of the device,
1490 as setup by the ROM or ntdetect.
1492 IdentifierLength - Length of the Identifier string.
1494 ConfigurationData - Pointer to the configuration data for the device or
1497 ConfigurationDataLength - Length of the data in the configurationData
1500 ComponentInformation - Undefined.
1502 ComponentInformationLength - Undefined.
1506 Returns NO_ERROR if the function completed properly.
1507 Returns ERROR_DEV_NOT_EXIST if we did not find the device.
1508 Returns ERROR_INVALID_PARAMETER otherwise.
1513 VideoDebugPrint((Error
, "Detected internal VGA chip on embedded board, todo\n"));
1517 } //end GetDeviceDataCallback()
1519 // eVb: 1.16 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
1522 VgaAcquireResources(
1523 PHW_DEVICE_EXTENSION DeviceExtension
1526 VP_STATUS Status
= NO_ERROR
;
1530 // Try exclusive ranges (vga + ati)
1533 Ranges
= NUM_VGA_ACCESS_RANGES
;
1534 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= FALSE
;
1535 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1538 // Not worked, try vga only
1542 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1545 // Still not, try shared ranges
1548 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1549 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);
1550 if (Status
== NO_ERROR
)
1556 VideoPortVerifyAccessRanges(DeviceExtension
, 0, 0);
1562 if (Status
== NO_ERROR
)
1565 // Worked with exclusive, also try shared
1568 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1569 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);