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.
24 PVOID HwDeviceExtension
,
27 PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
34 PVOID HwDeviceExtension
40 PVOID HwDeviceExtension
,
41 PVIDEO_REQUEST_PACKET RequestPacket
45 // Private function prototypes.
50 VgaQueryAvailableModes(
51 PHW_DEVICE_EXTENSION HwDeviceExtension
,
52 PVIDEO_MODE_INFORMATION ModeInformation
,
53 ULONG ModeInformationSize
,
59 VgaQueryNumberOfAvailableModes(
60 PHW_DEVICE_EXTENSION HwDeviceExtension
,
61 PVIDEO_NUM_MODES NumModes
,
69 PHW_DEVICE_EXTENSION HwDeviceExtension
,
70 PVIDEO_MODE_INFORMATION ModeInformation
,
71 ULONG ModeInformationSize
,
78 PHW_DEVICE_EXTENSION HwDeviceExtension
,
81 // eVb: 1.1 [SET MODE] - Add new output parameter for framebuffer update functionality
89 PHW_DEVICE_EXTENSION HwDeviceExtension
94 VgaInterpretCmdStream(
95 PVOID HwDeviceExtension
,
102 PHW_DEVICE_EXTENSION HwDeviceExtension
,
103 PVIDEO_PALETTE_DATA PaletteBuffer
,
104 ULONG PaletteBufferSize
110 PHW_DEVICE_EXTENSION HwDeviceExtension
,
111 PVIDEO_CLUT ClutBuffer
,
117 GetDeviceDataCallback(
118 PVOID HwDeviceExtension
,
120 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
122 ULONG IdentifierLength
,
123 PVOID ConfigurationData
,
124 ULONG ConfigurationDataLength
,
125 PVOID ComponentInformation
,
126 ULONG ComponentInformationLength
129 // eVb: 1.2 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
133 PHW_DEVICE_EXTENSION DeviceExtension
137 #if defined(ALLOC_PRAGMA)
138 #pragma alloc_text(PAGE,DriverEntry)
139 #pragma alloc_text(PAGE,VgaFindAdapter)
140 #pragma alloc_text(PAGE,VgaInitialize)
141 #pragma alloc_text(PAGE,VgaStartIO)
142 #pragma alloc_text(PAGE,VgaIsPresent)
143 #pragma alloc_text(PAGE,VgaSetColorLookup)
146 //---------------------------------------------------------------------------
148 // eVb: 1.3 [GCC] - Add NTAPI for GCC support
160 Installable driver initialization entry point.
161 This entry point is called directly by the I/O system.
165 Context1 - First context value passed by the operating system. This is
166 the value with which the miniport driver calls VideoPortInitialize().
168 Context2 - Second context value passed by the operating system. This is
169 the value with which the miniport driver calls 3VideoPortInitialize().
173 Status from VideoPortInitialize()
179 VIDEO_HW_INITIALIZATION_DATA hwInitData
;
181 ULONG initializationStatus
= (ULONG
) -1;
184 // Zero out structure.
187 VideoPortZeroMemory(&hwInitData
, sizeof(VIDEO_HW_INITIALIZATION_DATA
));
190 // Specify sizes of structure and extension.
193 hwInitData
.HwInitDataSize
= sizeof(VIDEO_HW_INITIALIZATION_DATA
);
199 hwInitData
.HwFindAdapter
= VgaFindAdapter
;
200 hwInitData
.HwInitialize
= VgaInitialize
;
201 hwInitData
.HwInterrupt
= NULL
;
202 hwInitData
.HwStartIO
= VgaStartIO
;
205 // Determine the size we require for the device extension.
208 hwInitData
.HwDeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
211 // Always start with parameters for device0 in this case.
212 // We can leave it like this since we know we will only ever find one
213 // VGA type adapter in a machine.
216 // hwInitData.StartingDeviceNumber = 0;
219 // Once all the relevant information has been stored, call the video
220 // port driver to do the initialization.
221 // For this device we will repeat this call three times, for ISA, EISA
223 // We will return the minimum of all return values.
227 // We will try the PCI bus first so that our ISA detection does'nt claim
228 // PCI cards (since it is impossible to differentiate between the two
229 // by looking at the registers).
233 // NOTE: since this driver only supports one adapter, we will return
234 // as soon as we find a device, without going on to the following buses.
235 // Normally one would call for each bus type and return the smallest
239 #if !defined(_ALPHA_)
242 // Before we can enable this on ALPHA we need to find a way to map a
243 // sparse view of a 4MB region successfully.
246 hwInitData
.AdapterInterfaceType
= PCIBus
;
248 initializationStatus
= VideoPortInitialize(Context1
,
253 if (initializationStatus
== NO_ERROR
)
255 return initializationStatus
;
260 hwInitData
.AdapterInterfaceType
= MicroChannel
;
262 initializationStatus
= VideoPortInitialize(Context1
,
268 // Return immediately instead of checkin for smallest return code.
271 if (initializationStatus
== NO_ERROR
)
273 return initializationStatus
;
277 hwInitData
.AdapterInterfaceType
= Internal
;
279 initializationStatus
= VideoPortInitialize(Context1
,
284 if (initializationStatus
== NO_ERROR
)
286 return initializationStatus
;
290 hwInitData
.AdapterInterfaceType
= Isa
;
292 initializationStatus
= VideoPortInitialize(Context1
,
297 if (initializationStatus
== NO_ERROR
)
299 return initializationStatus
;
304 hwInitData
.AdapterInterfaceType
= Eisa
;
306 status
= VideoPortInitialize(Context1
,
311 if (initializationStatus
> status
) {
312 initializationStatus
= status
;
315 return initializationStatus
;
317 } // end DriverEntry()
319 //---------------------------------------------------------------------------
323 PVOID HwDeviceExtension
,
325 PWSTR ArgumentString
,
326 PVIDEO_PORT_CONFIG_INFO ConfigInfo
,
334 This routine is called to determine if the adapter for this driver
335 is present in the system.
336 If it is present, the function fills out some information describing
341 HwDeviceExtension - Supplies the miniport driver's adapter storage. This
342 storage is initialized to zero before this call.
344 HwContext - Supplies the context value which was passed to
345 VideoPortInitialize().
347 ArgumentString - Supplies a NULL terminated ASCII string. This string
348 originates from the user.
350 ConfigInfo - Returns the configuration information structure which is
351 filled by the miniport driver. This structure is initialized with
352 any known configuration information (such as SystemIoBusNumber) by
353 the port driver. Where possible, drivers should have one set of
354 defaults which do not require any supplied configuration information.
356 Again - Indicates if the miniport driver wants the port driver to call
357 its VIDEO_HW_FIND_ADAPTER function again with a new device extension
358 and the same config info. This is used by the miniport drivers which
359 can search for several adapters on a bus.
363 This routine must return:
365 NO_ERROR - Indicates a host adapter was found and the
366 configuration information was successfully determined.
368 ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
369 error obtaining the configuration information. If possible an error
372 ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
373 supplied configuration information.
379 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
382 // Make sure the size of the structure is at least as large as what we
383 // are expecting (check version of the config info structure).
386 if (ConfigInfo
->Length
< sizeof(VIDEO_PORT_CONFIG_INFO
)) {
388 return ERROR_INVALID_PARAMETER
;
391 // eVb: 1.4 [CIRRUS] - Remove CIRRUS-specific support
393 // Check internal VGA (MIPS and ARM systems)
396 if ((ConfigInfo
->AdapterInterfaceType
== Internal
) &&
397 (VideoPortGetDeviceData(HwDeviceExtension
,
399 &GetDeviceDataCallback
,
400 VgaAccessRange
) != NO_ERROR
))
402 return ERROR_INVALID_PARAMETER
;
406 // No interrupt information is necessary.
410 // Check to see if there is a hardware resource conflict.
412 // eVb: 1.5 [RESOURCE] - Use new function for acquiring VGA resources (I/O, memory)
413 if (VgaAcquireResources(hwDeviceExtension
) != NO_ERROR
) return ERROR_INVALID_PARAMETER
;
416 // Get logical IO port addresses.
419 if ((hwDeviceExtension
->IOAddress
=
420 VideoPortGetDeviceBase(hwDeviceExtension
,
421 VgaAccessRange
->RangeStart
,
422 VGA_MAX_IO_PORT
- VGA_BASE_IO_PORT
+ 1,
423 VgaAccessRange
->RangeInIoSpace
)) == NULL
)
425 VideoDebugPrint((0, "VgaFindAdapter - Fail to get io address\n"));
427 return ERROR_INVALID_PARAMETER
;
431 // Determine whether a VGA is present.
434 if (!VgaIsPresent(hwDeviceExtension
)) {
436 VideoDebugPrint((0, "VgaFindAdapter - VGA Failed\n"));
437 return ERROR_DEV_NOT_EXIST
;
441 // Minimum size of the buffer required to store the hardware state
442 // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
445 ConfigInfo
->HardwareStateSize
= VGA_TOTAL_STATE_SIZE
;
448 // Pass a pointer to the emulator range we are using.
450 // eVb: 1.6 [VDM] - Disable VDM for now
451 ConfigInfo
->NumEmulatorAccessEntries
= 0;
452 ConfigInfo
->EmulatorAccessEntries
= NULL
;
453 ConfigInfo
->EmulatorAccessEntriesContext
= 0;
458 // There is really no reason to have the frame buffer mapped. On an
459 // x86 we use if for save/restore (supposedly) but even then we
460 // would only need to map a 64K window, not all 16 Meg!
466 // Map the video memory into the system virtual address space so we can
467 // clear it out and use it for save and restore.
470 if ( (hwDeviceExtension
->VideoMemoryAddress
=
471 VideoPortGetDeviceBase(hwDeviceExtension
,
472 VgaAccessRange
[2].RangeStart
,
473 VgaAccessRange
[2].RangeLength
,
476 VideoDebugPrint((0, "VgaFindAdapter - Fail to get memory address\n"));
478 return ERROR_INVALID_PARAMETER
;
481 VideoDebugPrint((0, "vga mapped at %x\n", hwDeviceExtension
->VideoMemoryAddress
));
483 // eVb: 1.7 [VDM] - Disable VDM for now
484 ConfigInfo
->VdmPhysicalVideoMemoryAddress
.QuadPart
= 0;
485 ConfigInfo
->VdmPhysicalVideoMemoryLength
= 0;
488 // Indicate we do not wish to be called again for another initialization.
494 // Indicate a successful completion status.
500 } // VgaFindAdapter()
502 //---------------------------------------------------------------------------
506 PVOID HwDeviceExtension
513 This routine does one time initialization of the device.
517 HwDeviceExtension - Pointer to the miniport driver's adapter information.
526 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
529 // set up the default cursor position and type.
532 hwDeviceExtension
->CursorPosition
.Column
= 0;
533 hwDeviceExtension
->CursorPosition
.Row
= 0;
534 hwDeviceExtension
->CursorTopScanLine
= 0;
535 hwDeviceExtension
->CursorBottomScanLine
= 31;
536 hwDeviceExtension
->CursorEnable
= TRUE
;
538 // eVb: 1.8 [VBE] - Initialize VBE modes
539 InitializeModeTable(hwDeviceExtension
);
545 //---------------------------------------------------------------------------
549 PVOID HwDeviceExtension
,
550 PVIDEO_REQUEST_PACKET RequestPacket
557 This routine is the main execution routine for the miniport driver. It
558 accepts a Video Request Packet, performs the request, and then returns
559 with the appropriate status.
563 HwDeviceExtension - Pointer to the miniport driver's adapter information.
565 RequestPacket - Pointer to the video request packet. This structure
566 contains all the parameters passed to the VideoIoControl function.
570 This routine will return error codes from the various support routines
571 and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
572 buffers and ERROR_INVALID_FUNCTION for unsupported functions.
577 PHW_DEVICE_EXTENSION hwDeviceExtension
= HwDeviceExtension
;
579 VIDEO_MODE videoMode
;
580 PVIDEO_MEMORY_INFORMATION memoryInformation
;
585 // Switch on the IoContolCode in the RequestPacket. It indicates which
586 // function must be performed by the driver.
588 // eVb: 1.9 [IOCTL] - Remove IOCTLs not needed yet
589 switch (RequestPacket
->IoControlCode
)
591 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY
:
593 VideoDebugPrint((2, "VgaStartIO - ShareVideoMemory\n"));
595 status
= ERROR_INVALID_FUNCTION
;
599 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY
:
601 VideoDebugPrint((2, "VgaStartIO - UnshareVideoMemory\n"));
603 status
= ERROR_INVALID_FUNCTION
;
608 case IOCTL_VIDEO_MAP_VIDEO_MEMORY
:
610 VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
612 if ( (RequestPacket
->OutputBufferLength
<
613 (RequestPacket
->StatusBlock
->Information
=
614 sizeof(VIDEO_MEMORY_INFORMATION
))) ||
615 (RequestPacket
->InputBufferLength
< sizeof(VIDEO_MEMORY
)) )
617 status
= ERROR_INSUFFICIENT_BUFFER
;
620 memoryInformation
= RequestPacket
->OutputBuffer
;
622 memoryInformation
->VideoRamBase
= ((PVIDEO_MEMORY
)
623 (RequestPacket
->InputBuffer
))->RequestedVirtualAddress
;
626 // We reserved 16 meg for the frame buffer, however, it makes
627 // no sense to map more memory than there is on the card. So
628 // only map the amount of memory we have on the card.
630 // eVb: 1.10 [CIRRUS] - On VGA, we have VRAM size since boot, use it
631 memoryInformation
->VideoRamLength
=
632 hwDeviceExtension
->PhysicalVideoMemoryLength
;
635 // If you change to using a dense space frame buffer, make this
636 // value a 4 for the ALPHA.
641 status
= VideoPortMapMemory(hwDeviceExtension
,
642 hwDeviceExtension
->PhysicalVideoMemoryBase
,
643 // eVb: 1.11 [CIRRUS] - On VGA, we have VRAM size since boot, use it
644 &memoryInformation
->VideoRamLength
,
647 &(memoryInformation
->VideoRamBase
));
649 if (status
!= NO_ERROR
) {
650 VideoDebugPrint((0, "VgaStartIO - IOCTL_VIDEO_MAP_VIDEO_MEMORY failed VideoPortMapMemory (%x)\n", status
));
653 memoryInformation
->FrameBufferBase
=
654 ((PUCHAR
) (memoryInformation
->VideoRamBase
)) +
655 hwDeviceExtension
->PhysicalFrameOffset
.LowPart
;
657 memoryInformation
->FrameBufferLength
=
658 hwDeviceExtension
->PhysicalFrameLength
?
659 hwDeviceExtension
->PhysicalFrameLength
:
660 memoryInformation
->VideoRamLength
;
663 VideoDebugPrint((2, "physical VideoMemoryBase %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryBase
));
664 VideoDebugPrint((2, "physical VideoMemoryLength %08lx\n", hwDeviceExtension
->PhysicalVideoMemoryLength
));
665 VideoDebugPrint((2, "VideoMemoryBase %08lx\n", memoryInformation
->VideoRamBase
));
666 VideoDebugPrint((2, "VideoMemoryLength %08lx\n", memoryInformation
->VideoRamLength
));
668 VideoDebugPrint((2, "physical framebuf offset %08lx\n", hwDeviceExtension
->PhysicalFrameOffset
.LowPart
));
669 VideoDebugPrint((2, "framebuf base %08lx\n", memoryInformation
->FrameBufferBase
));
670 VideoDebugPrint((2, "physical framebuf len %08lx\n", hwDeviceExtension
->PhysicalFrameLength
));
671 VideoDebugPrint((2, "framebuf length %08lx\n", memoryInformation
->FrameBufferLength
));
675 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY
:
677 VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
679 status
= ERROR_INVALID_FUNCTION
;
684 case IOCTL_VIDEO_QUERY_AVAIL_MODES
:
686 VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
688 status
= VgaQueryAvailableModes(HwDeviceExtension
,
689 (PVIDEO_MODE_INFORMATION
)
690 RequestPacket
->OutputBuffer
,
691 RequestPacket
->OutputBufferLength
,
692 &RequestPacket
->StatusBlock
->Information
);
697 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES
:
699 VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
701 status
= VgaQueryNumberOfAvailableModes(HwDeviceExtension
,
703 RequestPacket
->OutputBuffer
,
704 RequestPacket
->OutputBufferLength
,
705 &RequestPacket
->StatusBlock
->Information
);
710 case IOCTL_VIDEO_QUERY_CURRENT_MODE
:
712 VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
714 status
= VgaQueryCurrentMode(HwDeviceExtension
,
715 (PVIDEO_MODE_INFORMATION
) RequestPacket
->OutputBuffer
,
716 RequestPacket
->OutputBufferLength
,
717 &RequestPacket
->StatusBlock
->Information
);
722 case IOCTL_VIDEO_SET_CURRENT_MODE
:
724 VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
726 status
= VgaSetMode(HwDeviceExtension
,
727 (PVIDEO_MODE
) RequestPacket
->InputBuffer
,
728 RequestPacket
->InputBufferLength
,
729 // eVb: 1.12 [SET MODE] - Use new output parameter for framebuffer update functionality
736 case IOCTL_VIDEO_RESET_DEVICE
:
738 VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
740 videoMode
.RequestedMode
= 0;
742 VgaSetMode(HwDeviceExtension
,
743 (PVIDEO_MODE
) &videoMode
,
745 // eVb: 1.13 [SET MODE] - Use new output parameter for framebuffer update functionality
750 // Always return succcess since settings the text mode will fail on
753 // Also, failiure to set the text mode is not fatal in any way, since
754 // this operation must be followed by another set mode operation.
762 case IOCTL_VIDEO_LOAD_AND_SET_FONT
:
764 VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
766 status
= ERROR_INVALID_FUNCTION
;
771 case IOCTL_VIDEO_QUERY_CURSOR_POSITION
:
773 VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
775 status
= ERROR_INVALID_FUNCTION
;
780 case IOCTL_VIDEO_SET_CURSOR_POSITION
:
782 VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
784 status
= ERROR_INVALID_FUNCTION
;
789 case IOCTL_VIDEO_QUERY_CURSOR_ATTR
:
791 VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
793 status
= ERROR_INVALID_FUNCTION
;
798 case IOCTL_VIDEO_SET_CURSOR_ATTR
:
800 VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
802 status
= ERROR_INVALID_FUNCTION
;
807 case IOCTL_VIDEO_SET_PALETTE_REGISTERS
:
809 VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
811 status
= VgaSetPaletteReg(HwDeviceExtension
,
812 (PVIDEO_PALETTE_DATA
) RequestPacket
->InputBuffer
,
813 RequestPacket
->InputBufferLength
);
818 case IOCTL_VIDEO_SET_COLOR_REGISTERS
:
820 VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
822 status
= VgaSetColorLookup(HwDeviceExtension
,
823 (PVIDEO_CLUT
) RequestPacket
->InputBuffer
,
824 RequestPacket
->InputBufferLength
);
829 case IOCTL_VIDEO_ENABLE_VDM
:
831 VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
833 status
= ERROR_INVALID_FUNCTION
;
838 case IOCTL_VIDEO_RESTORE_HARDWARE_STATE
:
840 VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
842 status
= ERROR_INVALID_FUNCTION
;
847 case IOCTL_VIDEO_SAVE_HARDWARE_STATE
:
849 VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
851 status
= ERROR_INVALID_FUNCTION
;
855 case IOCTL_VIDEO_GET_BANK_SELECT_CODE
:
857 VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
859 status
= ERROR_INVALID_FUNCTION
;
862 case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES
:
864 PVIDEO_PUBLIC_ACCESS_RANGES portAccess
;
865 ULONG physicalPortLength
;
867 VideoDebugPrint((2, "VgaStartIO - Query Public Address Ranges\n"));
869 if (RequestPacket
->OutputBufferLength
<
870 sizeof(VIDEO_PUBLIC_ACCESS_RANGES
))
872 status
= ERROR_INSUFFICIENT_BUFFER
;
876 RequestPacket
->StatusBlock
->Information
=
877 sizeof(VIDEO_PUBLIC_ACCESS_RANGES
);
879 portAccess
= RequestPacket
->OutputBuffer
;
882 // The first public access range is the IO ports.
885 portAccess
->VirtualAddress
= (PVOID
) NULL
;
886 portAccess
->InIoSpace
= TRUE
;
887 portAccess
->MappedInIoSpace
= portAccess
->InIoSpace
;
888 physicalPortLength
= VGA_MAX_IO_PORT
- VGA_BASE_IO_PORT
+ 1;
890 status
= VideoPortMapMemory(hwDeviceExtension
,
891 VgaAccessRange
->RangeStart
,
893 &(portAccess
->MappedInIoSpace
),
894 &(portAccess
->VirtualAddress
));
895 // eVb: 1.17 [GCG] - Fix lvalue error
896 portAccess
->VirtualAddress
= (PVOID
)((ULONG_PTR
)portAccess
->VirtualAddress
- VGA_BASE_IO_PORT
);
898 VideoDebugPrint((2, "VgaStartIO - mapping ports to (%x)\n", portAccess
->VirtualAddress
));
903 case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES
:
905 VideoDebugPrint((2, "VgaStartIO - Free Public Access Ranges\n"));
907 status
= ERROR_INVALID_FUNCTION
;
911 // if we get here, an invalid IoControlCode was specified.
916 VideoDebugPrint((0, "Fell through vga startIO routine - invalid command\n"));
918 status
= ERROR_INVALID_FUNCTION
;
924 RequestPacket
->StatusBlock
->Status
= status
;
930 //---------------------------------------------------------------------------
935 //---------------------------------------------------------------------------
939 PHW_DEVICE_EXTENSION HwDeviceExtension
946 This routine returns TRUE if a VGA is present. Determining whether a VGA
947 is present is a two-step process. First, this routine walks bits through
948 the Bit Mask register, to establish that there are readable indexed
949 registers (EGAs normally don't have readable registers, and other adapters
950 are unlikely to have indexed registers). This test is done first because
951 it's a non-destructive EGA rejection test (correctly rejects EGAs, but
952 doesn't potentially mess up the screen or the accessibility of display
953 memory). Normally, this would be an adequate test, but some EGAs have
954 readable registers, so next, we check for the existence of the Chain4 bit
955 in the Memory Mode register; this bit doesn't exist in EGAs. It's
956 conceivable that there are EGAs with readable registers and a register bit
957 where Chain4 is stored, although I don't know of any; if a better test yet
958 is needed, memory could be written to in Chain4 mode, and then examined
959 plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
960 supposed to do. However, the current test should be adequate to eliminate
961 just about all EGAs, and 100% of everything else.
963 If this function fails to find a VGA, it attempts to undo any damage it
964 may have inadvertently done while testing. The underlying assumption for
965 the damage control is that if there's any non-VGA adapter at the tested
966 ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
967 other adapters that use 3C4/5 or 3CE/F, and b), if there are other
968 adapters, I certainly don't know how to restore their original states. So
969 all error recovery is oriented toward putting an EGA back in a writable
970 state, so that error messages are visible. The EGA's state on entry is
971 assumed to be text mode, so the Memory Mode register is restored to the
972 default state for text mode.
974 If a VGA is found, the VGA is returned to its original state after
983 TRUE if a VGA is present, FALSE if not.
988 UCHAR originalGCAddr
;
989 UCHAR originalSCAddr
;
990 UCHAR originalBitMask
;
991 UCHAR originalReadMap
;
992 UCHAR originalMemoryMode
;
994 BOOLEAN returnStatus
;
997 // Remember the original state of the Graphics Controller Address register.
1000 originalGCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1001 GRAPH_ADDRESS_PORT
);
1004 // Write the Read Map register with a known state so we can verify
1005 // that it isn't changed after we fool with the Bit Mask. This ensures
1006 // that we're dealing with indexed registers, since both the Read Map and
1007 // the Bit Mask are addressed at GRAPH_DATA_PORT.
1010 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1011 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1014 // If we can't read back the Graphics Address register setting we just
1015 // performed, it's not readable and this isn't a VGA.
1018 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1019 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_READ_MAP
) {
1025 // Set the Read Map register to a known state.
1028 originalReadMap
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1030 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1031 GRAPH_DATA_PORT
, READ_MAP_TEST_SETTING
);
1033 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1034 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
1037 // The Read Map setting we just performed can't be read back; not a
1038 // VGA. Restore the default Read Map state.
1041 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1042 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1048 // Remember the original setting of the Bit Mask register.
1051 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1052 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1053 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1054 GRAPH_ADDRESS_PORT
) & GRAPH_ADDR_MASK
) != IND_BIT_MASK
) {
1057 // The Graphics Address register setting we just made can't be read
1058 // back; not a VGA. Restore the default Read Map state.
1061 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1062 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1063 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1064 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1069 originalBitMask
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1073 // Set up the initial test mask we'll write to and read from the Bit Mask.
1081 // Write the test mask to the Bit Mask.
1084 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1085 GRAPH_DATA_PORT
, testMask
);
1088 // Make sure the Bit Mask remembered the value.
1091 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1092 GRAPH_DATA_PORT
) != testMask
) {
1095 // The Bit Mask is not properly writable and readable; not a VGA.
1096 // Restore the Bit Mask and Read Map to their default states.
1099 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1100 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1101 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1102 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1103 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1104 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1110 // Cycle the mask for next time.
1115 } while (testMask
!= 0);
1118 // There's something readable at GRAPH_DATA_PORT; now switch back and
1119 // make sure that the Read Map register hasn't changed, to verify that
1120 // we're dealing with indexed registers.
1123 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1124 GRAPH_ADDRESS_PORT
, IND_READ_MAP
);
1125 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1126 GRAPH_DATA_PORT
) != READ_MAP_TEST_SETTING
) {
1129 // The Read Map is not properly writable and readable; not a VGA.
1130 // Restore the Bit Mask and Read Map to their default states, in case
1131 // this is an EGA, so subsequent writes to the screen aren't garbled.
1134 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1135 GRAPH_DATA_PORT
, READ_MAP_DEFAULT
);
1136 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1137 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1138 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1139 GRAPH_DATA_PORT
, BIT_MASK_DEFAULT
);
1145 // We've pretty surely verified the existence of the Bit Mask register.
1146 // Put the Graphics Controller back to the original state.
1149 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1150 GRAPH_DATA_PORT
, originalReadMap
);
1151 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1152 GRAPH_ADDRESS_PORT
, IND_BIT_MASK
);
1153 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1154 GRAPH_DATA_PORT
, originalBitMask
);
1155 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1156 GRAPH_ADDRESS_PORT
, originalGCAddr
);
1159 // Now, check for the existence of the Chain4 bit.
1163 // Remember the original states of the Sequencer Address and Memory Mode
1167 originalSCAddr
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1169 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1170 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1171 if ((VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1172 SEQ_ADDRESS_PORT
) & SEQ_ADDR_MASK
) != IND_MEMORY_MODE
) {
1175 // Couldn't read back the Sequencer Address register setting we just
1181 originalMemoryMode
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1185 // Toggle the Chain4 bit and read back the result. This must be done during
1186 // sync reset, since we're changing the chaining state.
1190 // Begin sync reset.
1193 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1195 (IND_SYNC_RESET
+ (START_SYNC_RESET_VALUE
<< 8)));
1198 // Toggle the Chain4 bit.
1201 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1202 SEQ_ADDRESS_PORT
, IND_MEMORY_MODE
);
1203 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1204 SEQ_DATA_PORT
, (UCHAR
)(originalMemoryMode
^ CHAIN4_MASK
));
1206 if (VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1207 SEQ_DATA_PORT
) != (UCHAR
) (originalMemoryMode
^ CHAIN4_MASK
)) {
1210 // Chain4 bit not there; not a VGA.
1211 // Set text mode default for Memory Mode register.
1214 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1215 SEQ_DATA_PORT
, MEMORY_MODE_TEXT_DEFAULT
);
1220 VideoPortWritePortUshort((PUSHORT
) (HwDeviceExtension
->IOAddress
+
1222 (IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1224 returnStatus
= FALSE
;
1233 // Restore the original Memory Mode setting.
1236 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1237 SEQ_DATA_PORT
, originalMemoryMode
);
1243 VideoPortWritePortUshort((PUSHORT
)(HwDeviceExtension
->IOAddress
+
1245 (USHORT
)(IND_SYNC_RESET
+ (END_SYNC_RESET_VALUE
<< 8)));
1248 // Restore the original Sequencer Address setting.
1251 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1252 SEQ_ADDRESS_PORT
, originalSCAddr
);
1254 returnStatus
= TRUE
;
1257 return returnStatus
;
1261 //---------------------------------------------------------------------------
1265 PHW_DEVICE_EXTENSION HwDeviceExtension
,
1266 PVIDEO_PALETTE_DATA PaletteBuffer
,
1267 ULONG PaletteBufferSize
1272 Routine Description:
1274 This routine sets a specified portion of the EGA (not DAC) palette
1279 HwDeviceExtension - Pointer to the miniport driver's device extension.
1281 PaletteBuffer - Pointer to the structure containing the palette data.
1283 PaletteBufferSize - Length of the input buffer supplied by the user.
1287 NO_ERROR - information returned successfully
1289 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1291 ERROR_INVALID_PARAMETER - invalid palette size.
1299 // Check if the size of the data in the input buffer is large enough.
1302 if ((PaletteBufferSize
) < (sizeof(VIDEO_PALETTE_DATA
)) ||
1303 (PaletteBufferSize
< (sizeof(VIDEO_PALETTE_DATA
) +
1304 (sizeof(USHORT
) * (PaletteBuffer
->NumEntries
-1)) ))) {
1306 return ERROR_INSUFFICIENT_BUFFER
;
1311 // Check to see if the parameters are valid.
1314 if ( (PaletteBuffer
->FirstEntry
> VIDEO_MAX_COLOR_REGISTER
) ||
1315 (PaletteBuffer
->NumEntries
== 0) ||
1316 (PaletteBuffer
->FirstEntry
+ PaletteBuffer
->NumEntries
>
1317 VIDEO_MAX_PALETTE_REGISTER
+ 1 ) ) {
1319 return ERROR_INVALID_PARAMETER
;
1324 // Reset ATC to index mode
1327 VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
1328 ATT_INITIALIZE_PORT_COLOR
);
1331 // Blast out our palette values.
1334 for (i
= 0; i
< PaletteBuffer
->NumEntries
; i
++) {
1336 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ ATT_ADDRESS_PORT
,
1337 (UCHAR
)(i
+PaletteBuffer
->FirstEntry
));
1339 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1340 ATT_DATA_WRITE_PORT
,
1341 (UCHAR
)PaletteBuffer
->Colors
[i
]);
1344 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ ATT_ADDRESS_PORT
,
1349 } // end VgaSetPaletteReg()
1351 //---------------------------------------------------------------------------
1355 PHW_DEVICE_EXTENSION HwDeviceExtension
,
1356 PVIDEO_CLUT ClutBuffer
,
1357 ULONG ClutBufferSize
1362 Routine Description:
1364 This routine sets a specified portion of the DAC color lookup table
1369 HwDeviceExtension - Pointer to the miniport driver's device extension.
1371 ClutBufferSize - Length of the input buffer supplied by the user.
1373 ClutBuffer - Pointer to the structure containing the color lookup table.
1377 NO_ERROR - information returned successfully
1379 ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
1381 ERROR_INVALID_PARAMETER - invalid clut size.
1386 PVIDEOMODE CurrentMode
= HwDeviceExtension
->CurrentMode
;
1390 // Check if the size of the data in the input buffer is large enough.
1393 if ( (ClutBufferSize
< sizeof(VIDEO_CLUT
) - sizeof(ULONG
)) ||
1394 (ClutBufferSize
< sizeof(VIDEO_CLUT
) +
1395 (sizeof(ULONG
) * (ClutBuffer
->NumEntries
- 1)) ) ) {
1397 return ERROR_INSUFFICIENT_BUFFER
;
1402 // Check to see if the parameters are valid.
1405 if ( (ClutBuffer
->NumEntries
== 0) ||
1406 (ClutBuffer
->FirstEntry
> VIDEO_MAX_COLOR_REGISTER
) ||
1407 (ClutBuffer
->FirstEntry
+ ClutBuffer
->NumEntries
>
1408 VIDEO_MAX_COLOR_REGISTER
+ 1) ) {
1410 return ERROR_INVALID_PARAMETER
;
1413 // eVb: 1.14 [VBE] - Add VBE color support
1418 if (CurrentMode
->bitsPerPlane
>= 8) return VbeSetColorLookup(HwDeviceExtension
, ClutBuffer
);
1421 // Path for VGA mode
1423 // eVb: 1.15 [VBE] - Add VBE support for non-VGA-compatible detected modes
1424 if (!CurrentMode
->NonVgaMode
)
1428 // Set CLUT registers directly on the hardware
1431 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1432 DAC_ADDRESS_WRITE_PORT
, (UCHAR
) ClutBuffer
->FirstEntry
);
1434 for (i
= 0; i
< ClutBuffer
->NumEntries
; i
++) {
1435 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1436 DAC_ADDRESS_WRITE_PORT
,
1437 (UCHAR
)(i
+ ClutBuffer
->FirstEntry
));
1439 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1441 ClutBuffer
->LookupTable
[i
].RgbArray
.Red
);
1443 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1445 ClutBuffer
->LookupTable
[i
].RgbArray
.Green
);
1447 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+
1449 ClutBuffer
->LookupTable
[i
].RgbArray
.Blue
);
1454 return ERROR_INVALID_PARAMETER
;
1456 } // end VgaSetColorLookup()
1460 GetDeviceDataCallback(
1461 PVOID HwDeviceExtension
,
1463 VIDEO_DEVICE_DATA_TYPE DeviceDataType
,
1465 ULONG IdentifierLength
,
1466 PVOID ConfigurationData
,
1467 ULONG ConfigurationDataLength
,
1468 PVOID ComponentInformation
,
1469 ULONG ComponentInformationLength
1474 Routine Description:
1476 Callback routine for the VideoPortGetDeviceData function.
1480 HwDeviceExtension - Pointer to the miniport drivers device extension.
1482 Context - Context value passed to the VideoPortGetDeviceData function.
1484 DeviceDataType - The type of data that was requested in
1485 VideoPortGetDeviceData.
1487 Identifier - Pointer to a string that contains the name of the device,
1488 as setup by the ROM or ntdetect.
1490 IdentifierLength - Length of the Identifier string.
1492 ConfigurationData - Pointer to the configuration data for the device or
1495 ConfigurationDataLength - Length of the data in the configurationData
1498 ComponentInformation - Undefined.
1500 ComponentInformationLength - Undefined.
1504 Returns NO_ERROR if the function completed properly.
1505 Returns ERROR_DEV_NOT_EXIST if we did not find the device.
1506 Returns ERROR_INVALID_PARAMETER otherwise.
1511 VideoDebugPrint((Error
, "Detected internal VGA chip on embedded board, todo\n"));
1515 } //end GetDeviceDataCallback()
1517 // eVb: 1.16 [RESOURCE] - Add new function for acquiring VGA resources (I/O, memory)
1520 VgaAcquireResources(
1521 PHW_DEVICE_EXTENSION DeviceExtension
1524 VP_STATUS Status
= NO_ERROR
;
1528 // Try exclusive ranges (vga + ati)
1531 Ranges
= NUM_VGA_ACCESS_RANGES
;
1532 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= FALSE
;
1533 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1536 // Not worked, try vga only
1540 if (VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
) != NO_ERROR
)
1543 // Still not, try shared ranges
1546 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1547 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);
1548 if (Status
== NO_ERROR
)
1554 VideoPortVerifyAccessRanges(DeviceExtension
, 0, 0);
1560 if (Status
== NO_ERROR
)
1563 // Worked with exclusive, also try shared
1566 for (i
= 0; i
< Ranges
; i
++) VgaAccessRange
[i
].RangeShareable
= TRUE
;
1567 Status
= VideoPortVerifyAccessRanges(DeviceExtension
, Ranges
, VgaAccessRange
);