mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3235 lines
120 KiB
3235 lines
120 KiB
/************************************************************************/
|
|
/* */
|
|
/* ATIMP.C */
|
|
/* */
|
|
/* Copyright (c) 1992, ATI Technologies Inc. */
|
|
/************************************************************************/
|
|
|
|
// Brades: Changes to be merged into Rob's source
|
|
//
|
|
// 904 -- frame address stored in dar[0]. we are rgistering our LFB addres
|
|
// in DriverIORanges, but assigning to frameaddress.
|
|
// Is this used, or needed????
|
|
|
|
/********************** PolyTron RCS Utilities
|
|
|
|
$Revision: 1.43 $
|
|
$Date: 15 May 1996 16:29:52 $
|
|
$Author: RWolff $
|
|
$Log: S:/source/wnt/ms11/miniport/archive/atimp.c_v $
|
|
*
|
|
* Rev 1.43 15 May 1996 16:29:52 RWolff
|
|
* Added workaround for Alpha hang on PCI bus greater than 0, now reports
|
|
* failure of mode set on Mach 64.
|
|
*
|
|
* Rev 1.42 01 May 1996 14:07:52 RWolff
|
|
* Calls new routine DenseOnAlpha() to determine dense space support rather
|
|
* than assuming all PCI cards support dense space.
|
|
*
|
|
* Rev 1.41 23 Apr 1996 17:16:38 RWolff
|
|
* Now reports 1M cards with SDRAM (needs special alignment in display
|
|
* driver), separated "internal DAC cursor double buffering needed"
|
|
* from "this is a CT".
|
|
*
|
|
* Rev 1.40 15 Mar 1996 16:27:08 RWolff
|
|
* IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES now only frees the I/O mapped
|
|
* registers in NT 4.0 and above. This is because the mapped values for
|
|
* the permanent and test screens use the same virtual address, and
|
|
* in 3.51 VideoPortUnmapMemory() refuses to unmap them.
|
|
*
|
|
* Rev 1.39 12 Mar 1996 17:41:50 RWolff
|
|
* Made IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES work under new source
|
|
* stream display driver, removed debug print statements from ATIMPResetHw()
|
|
* since this routine can't call pageable routines and debug print
|
|
* statements are pageable.
|
|
*
|
|
* Rev 1.38 29 Jan 1996 16:53:30 RWolff
|
|
* Now uses VideoPortInt10() rather than no-BIOS code on PPC, removed
|
|
* dead code.
|
|
*
|
|
* Rev 1.37 23 Jan 1996 11:41:10 RWolff
|
|
* Eliminated level 3 warnings, added debug print statements.
|
|
*
|
|
* Rev 1.36 22 Dec 1995 14:51:42 RWolff
|
|
* Added support for Mach 64 GT internal DAC, switched to TARGET_BUILD
|
|
* to identify the NT version for which the driver is being built.
|
|
*
|
|
* Rev 1.35 23 Nov 1995 11:24:40 RWolff
|
|
* Added multihead support.
|
|
*
|
|
* Rev 1.34 17 Nov 1995 13:41:02 RWolff
|
|
* Temporary fallback until problem with VideoPortGetBaseAddress() is
|
|
* resolved. This should have gone in as branch revision 1.33.1.0, but
|
|
* the @#$%^&* configuration doesn't allow branches.
|
|
*
|
|
* Rev 1.33 27 Oct 1995 14:20:06 RWolff
|
|
* Fixes to bring up NT 3.51 on PPC, no longer makes mapped LFB part of
|
|
* hardware device extension.
|
|
*
|
|
* Rev 1.32 08 Sep 1995 16:36:04 RWolff
|
|
* Added support for AT&T 408 DAC (STG1703 equivalent).
|
|
*
|
|
* Rev 1.31 28 Aug 1995 16:37:36 RWolff
|
|
* No longer restores memory size on x86 boxes in ATIMPResetHw(). This
|
|
* is a fix for EPR 7839 - the restoration is not necessary on x86
|
|
* machines, but on some non-x86 boxes the memory size is not restored
|
|
* on a warm boot, so we must do it to allow the use of modes needing
|
|
* more than 1M after booting out of a 4BPP mode.
|
|
*
|
|
* Rev 1.30 24 Aug 1995 15:39:42 RWolff
|
|
* Changed detection of block I/O cards to match Microsoft's standard for
|
|
* plug-and-play, now reports CT and VT ASICs to the display driver.
|
|
*
|
|
* Rev 1.29 03 Aug 1995 16:22:42 RWOLFF
|
|
* Reverted to old bus ordering (PCI last) for non-Alpha machines under
|
|
* NT 3.5. Using the new ordering (PCI first) on an x86 under 3.5
|
|
* resulted in the display applet rejecting attempts to test 16 and 24 BPP
|
|
* on a Mach 32 (PCI or ISA) in a PCI machine.
|
|
*
|
|
* Rev 1.28 02 Jun 1995 14:19:14 RWOLFF
|
|
* Rearranged bus test order to put PCI first, added CT internal to
|
|
* DACs supported in no-BIOS version.
|
|
*
|
|
* Rev 1.27 31 Mar 1995 11:55:18 RWOLFF
|
|
* Changed from all-or-nothing debug print statements to thresholds
|
|
* depending on importance of the message.
|
|
*
|
|
* Rev 1.26 08 Mar 1995 11:33:18 ASHANMUG
|
|
* The pitch in 24bpp should be the pitch in engine pixels and not true pixels
|
|
*
|
|
* Rev 1.25 27 Feb 1995 17:51:50 RWOLFF
|
|
* Now reports (Mach 64 only) whether I/O space is packed (relocatable)
|
|
* or not, reports number of lines of offscreen memory for 4BPP as if
|
|
* the card has 1M of video memory, since we set the card to 1M for
|
|
* this depth.
|
|
*
|
|
* Rev 1.24 24 Feb 1995 12:24:40 RWOLFF
|
|
* Now adds text banding to the ATIModeInformation->ModeFlags bits
|
|
* that are filled in.
|
|
*
|
|
* Rev 1.23 20 Feb 1995 18:03:30 RWOLFF
|
|
* Reporting of screen tearing on 2M boundary is now DAC-independant, added
|
|
* 1600x1200 16BPP to modes which experience this tearing.
|
|
*
|
|
* Rev 1.22 03 Feb 1995 15:13:50 RWOLFF
|
|
* Added packets to support DCI.
|
|
*
|
|
* Rev 1.21 30 Jan 1995 12:16:24 RWOLFF
|
|
* Made definition of IBM DAC special cursor flag consistent with
|
|
* similar flag for TVP DAC.
|
|
*
|
|
* Rev 1.20 18 Jan 1995 15:38:46 RWOLFF
|
|
* Now looks for Mach64 before looking for our older accelerators, Chrontel
|
|
* DAC is now supported as a separate type rather than being lumped in
|
|
* with STG1702.
|
|
*
|
|
* Rev 1.19 11 Jan 1995 13:54:00 RWOLFF
|
|
* ATIMPResetHw() now restores the memory size on Mach64 cards. This is
|
|
* a fix for a problem that showed up on the DEC Alpha, but may affect
|
|
* other platforms as well. In 4BPP modes, we must tell the card that it
|
|
* has only 1M of memory, but on a warm boot, the x86 emulation did not
|
|
* re-initialize the memory size, so until the next cold boot, only modes
|
|
* available in 1M were listed.
|
|
*
|
|
* Rev 1.18 04 Jan 1995 11:59:28 RWOLFF
|
|
* ATIMPFindAdapter() will only detect ATI cards on the first invocation,
|
|
* to avoid the same card being detected once per bus and causing problems
|
|
* when Windows NT thinks it's multiple cards.
|
|
*
|
|
* Rev 1.17 23 Dec 1994 10:48:10 ASHANMUG
|
|
* ALPHA/Chrontel-DAC
|
|
*
|
|
* Rev 1.16 18 Nov 1994 11:36:52 RWOLFF
|
|
* Now checks for PCI bus, cleaned up temporary debug print statements,
|
|
* fixed non-x86 Mach 64 handling, added support for Power PC and
|
|
* STG1703 DAC.
|
|
*
|
|
* Rev 1.15 31 Aug 1994 16:14:00 RWOLFF
|
|
* IOCTL_VIDEO_ATI_GET_VERSION packet now reports TVP3026 DAC (different
|
|
* cursor handling needed in display driver),
|
|
* IOCTL_VIDEO_ATI_GET_MODE_INFORMATION now reports 1152x864 24BPP as
|
|
* having screen tearing at end of first 2M bank.
|
|
*
|
|
* Rev 1.14 22 Jul 1994 17:47:50 RWOLFF
|
|
* Merged with Richard's non-x86 code stream.
|
|
*
|
|
* Rev 1.13 20 Jul 1994 13:04:06 RWOLFF
|
|
* Changes required to support multiple I/O base addresses for Mach 64
|
|
* accelerator registers, ATIMPInitialize() now leaves the adapter in
|
|
* a state where an INT 10 can switch it to a VGA mode (fix for
|
|
* showstopper bug on Landtrain machines), calls new routine
|
|
* FillInRegistry() so the video applet can get information about
|
|
* the graphics card.
|
|
*
|
|
* Rev 1.12 30 Jun 1994 18:11:36 RWOLFF
|
|
* Changes to allow the new method of checking for aperture conflict.
|
|
*
|
|
* Rev 1.11 15 Jun 1994 11:04:24 RWOLFF
|
|
* In IOCTL_VIDEO_ATI_GET_VERSION, now only sets
|
|
* RequestPacket->StatusBlock->Information if the buffer is big enough.
|
|
*
|
|
* Rev 1.10 20 May 1994 19:18:00 RWOLFF
|
|
* IOCTL_VIDEO_ATI_GET_VERSION old format packet now returns the highest
|
|
* pixel depth for a given resolution even if it isn't the last mode
|
|
* table for the resolution.
|
|
*
|
|
* Rev 1.9 20 May 1994 13:57:40 RWOLFF
|
|
* Ajith's change: now saves in the query structure the bus type reported by NT.
|
|
*
|
|
* Rev 1.8 12 May 1994 11:04:24 RWOLFF
|
|
* Now forces OEM handling on DEC ALPHA machines.
|
|
*
|
|
* Rev 1.7 04 May 1994 19:25:40 RWOLFF
|
|
* Fixes for hanging and corrupting screen when display applet run.
|
|
*
|
|
* Rev 1.6 28 Apr 1994 10:59:56 RWOLFF
|
|
* Moved mode-independent bug/feature flags to IOCTL_VIDEO_ATI_GET_VERSION
|
|
* packet from IOCTL_VIDEO_ATI_GET_MODE_INFORMATION packet.
|
|
*
|
|
* Rev 1.5 27 Apr 1994 13:54:42 RWOLFF
|
|
* IOCTL_VIDEO_ATI_GET_MODE_INFORMATION packet now reports whether MIO bug
|
|
* is present on Mach 32 cards.
|
|
*
|
|
* Rev 1.4 31 Mar 1994 15:05:00 RWOLFF
|
|
* Added DPMS support, brought ATIMPResetHw() up to latest specs, added
|
|
* debugging code.
|
|
*
|
|
* Rev 1.3 14 Mar 1994 16:32:20 RWOLFF
|
|
* Added ATIMPResetHw() function, fix for 2M boundary tearing, replaced
|
|
* VCS logfile comments that were omitted in an earlier checkin.
|
|
*
|
|
* Rev 1.2 03 Mar 1994 12:36:56 ASHANMUG
|
|
* Make pageable
|
|
*
|
|
* Rev 1.1 07 Feb 1994 13:56:18 RWOLFF
|
|
* Added alloc_text() pragmas to allow miniport to be swapped out when
|
|
* not needed, removed LookForSubstitute() since miniport is no longer
|
|
* supposed to check whether mode has been substituted, no longer logs
|
|
* a message when the miniport aborts due to no ATI card being found,
|
|
* removed unused routine ATIMPQueryPointerCapabilities().
|
|
*
|
|
* Rev 1.0 31 Jan 1994 10:52:34 RWOLFF
|
|
* Initial revision.
|
|
|
|
Rev 1.6 14 Jan 1994 15:14:08 RWOLFF
|
|
Removed commented-out code, packet announcements now all controlled by
|
|
DEBUG_SWITCH, device reset for old cards now done by a single call,
|
|
new format for IOCTL_VIDEO_ATI_GET_VERSION packet, reports block write
|
|
capability in IOCTL_VIDEO_ATI_GET_MODE_INFORMATION packet, added
|
|
1600x1200 support.
|
|
|
|
Rev 1.5 30 Nov 1993 18:10:04 RWOLFF
|
|
Moved query of card capabilities (once type of card is known) from
|
|
ATIMPFindAdapter() to ATIMPInitialize() because query for Mach 64 needs
|
|
to use VideoPortInt10(), which can't be used in ATIMPFindAdapter().
|
|
|
|
Rev 1.4 05 Nov 1993 13:22:12 RWOLFF
|
|
Added initial Mach64 code (currently inactive).
|
|
|
|
Rev 1.3 08 Oct 1993 11:00:24 RWOLFF
|
|
Removed code specific to a particular family of ATI accelerators.
|
|
|
|
Rev 1.2 24 Sep 1993 11:49:46 RWOLFF
|
|
Removed cursor-specific IOCTLs (handled in display driver), now selects
|
|
24BPP colour order best suited to the DAC being used instead of forcing
|
|
BGR.
|
|
|
|
Rev 1.1 03 Sep 1993 14:20:46 RWOLFF
|
|
Partway through CX isolation.
|
|
|
|
Rev 1.0 16 Aug 1993 13:27:50 Robert_Wolff
|
|
Initial revision.
|
|
|
|
Rev 1.23 06 Jul 1993 15:46:14 RWOLFF
|
|
Got rid of mach32_split_fixup special handling. This code was to support
|
|
a non-production hardware combination.
|
|
|
|
Rev 1.22 10 Jun 1993 15:58:32 RWOLFF
|
|
Reading from registry now uses a static buffer rather than a dynamically
|
|
allocated one (originated by Andre Vachon at Microsoft).
|
|
|
|
Rev 1.21 07 Jun 1993 11:43:16 BRADES
|
|
Rev 6 split transfer fixup.
|
|
|
|
Rev 1.19 18 May 1993 14:04:00 RWOLFF
|
|
Removed reference to obsolete header TTY.H, calls to wait_for_idle()
|
|
no longer pass hardware device extension, since it's a global variable.
|
|
|
|
Rev 1.18 12 May 1993 16:30:36 RWOLFF
|
|
Now writes error messages to event log rather than blue screen,
|
|
initializes "special handling" variables determined from BIOS
|
|
to default values on cards with no BIOS. This revision contains
|
|
code for experimental far call support, but it's "#if 0"ed out.
|
|
|
|
Rev 1.17 10 May 1993 16:35:12 RWOLFF
|
|
LookForSubstitute() now recognizes all cases of colour depth not
|
|
supported by the DAC, unusable linear frame buffer now falls back
|
|
to LFB disabled operation rather than aborting the miniport, removed
|
|
unused variables and unnecessary passing of hardware device extension
|
|
as a parameter.
|
|
|
|
Rev 1.16 30 Apr 1993 17:58:50 BRADES
|
|
ATIMP startio assign QueryPtr once at start of function.
|
|
uses aVideoAddress virtual table for IO port addresses.
|
|
|
|
Rev 1.15 30 Apr 1993 16:33:42 RWOLFF
|
|
Updated to use NT build 438 initialization data structure.
|
|
Registry read buffer is now dynamically allocated to fit data requested
|
|
rather than being a fixed "hope it's big enough" size.
|
|
|
|
Rev 1.14 21 Apr 1993 17:22:06 RWOLFF
|
|
Now uses AMACH.H instead of 68800.H/68801.H.
|
|
Accelerator detection now checks only for functionality, not our BIOS
|
|
signature string which may not be present in OEM versions. Query
|
|
structure now indicates whether extended BIOS functions and/or
|
|
EEPROM are present. Added ability to switch between graphics and
|
|
text modes using absolute far calls in BIOS. Removed handling
|
|
of obsolete DriverOverride registry field.
|
|
|
|
Rev 1.13 14 Apr 1993 18:30:22 RWOLFF
|
|
24BPP is now done as BGR (supported by both TI and Brooktree DACs)
|
|
rather than RGB (only supported by TI DACs).
|
|
|
|
Rev 1.12 08 Apr 1993 16:53:18 RWOLFF
|
|
Revision level as checked in at Microsoft.
|
|
|
|
Rev 1.9 25 Mar 1993 11:10:38 RWOLFF
|
|
Cleaned up compile warnings, now returns failure if no EEPROM is present.
|
|
|
|
Rev 1.8 16 Mar 1993 17:15:16 BRADES
|
|
get_cursor uses screen_pitch instead of x_size.
|
|
|
|
Rev 1.7 16 Mar 1993 17:04:58 BRADES
|
|
Change ATI video to graphics message
|
|
|
|
Rev 1.6 15 Mar 1993 22:20:30 BRADES
|
|
use m_screen_pitch for the # pixels per display lines
|
|
|
|
Rev 1.5 08 Mar 1993 19:23:44 BRADES
|
|
update memory sizing to 256 increments, clean code.
|
|
|
|
Rev 1.4 10 Feb 1993 13:01:28 Robert_Wolff
|
|
IOCTL_VIDEO_MAP_VIDEO_MEMORY no longer assumes frame buffer length
|
|
is equal to video memory size (linear aperture present). It can now
|
|
accept 64k (uses VGA aperture) and 0 (no aperture available).
|
|
|
|
Rev 1.3 06 Feb 1993 12:55:52 Robert_Wolff
|
|
Now sets VIDEO_MODE_INFORMATION.ScreenStride to bytes per line (as listed
|
|
in the documentation). In the October beta, it had to be pixels per line.
|
|
|
|
Rev 1.2 05 Feb 1993 22:12:36 Robert_Wolff
|
|
Adjusted MessageDelay() to compensate for short_delay() no longer being
|
|
optimized out of existence.
|
|
|
|
Rev 1.1 05 Feb 1993 16:15:28 Robert_Wolff
|
|
Made it compatible with the new DDK, registry calls now use VideoPort
|
|
functions rather than RTL functions. This version will work with the
|
|
framebuffer driver.
|
|
|
|
Rev 1.0 02 Feb 1993 13:36:50 Robert_Wolff
|
|
Initial revision.
|
|
|
|
Rev 1.2 26 Jan 1993 10:28:30 Robert_Wolff
|
|
Now fills in Number<colour>Bits fields in VIDEO_MODE_INFORMATION structure.
|
|
|
|
Rev 1.1 25 Jan 1993 13:31:52 Robert_Wolff
|
|
Re-enabled forcing of shared VGA/accelerator memory for Mach 32
|
|
cards with no aperture enabled.
|
|
|
|
Rev 1.0 22 Jan 1993 16:44:42 Robert_Wolff
|
|
Initial revision.
|
|
|
|
Rev 1.26 21 Jan 1993 17:59:24 Robert_Wolff
|
|
Eliminated multiple definition link warnings, updated comments
|
|
in LookForSubstitute().
|
|
|
|
Rev 1.25 20 Jan 1993 17:47:48 Robert_Wolff
|
|
Now checks optional DriverOverride field in registry, and forces
|
|
use of appropriate (engine, framebuffer, or VGAWonder) driver
|
|
if the field is present and nonzero. If field is missing or zero,
|
|
former behaviour is used.
|
|
IOCTL_VIDEO_ATI_GET_VERSION packet now also returns the maximum
|
|
pixel depth available at each resolution.
|
|
Added mode substitution case for 16 BPP selected when using the
|
|
engine-only (fixed 8 BPP colour depth) driver.
|
|
|
|
Rev 1.24 15 Jan 1993 15:12:26 Robert_Wolff
|
|
Added IOCTL_VIDEO_ATI_GET_VERSION packet in ATIMPStartIO() to
|
|
return version number of the miniport.
|
|
|
|
Rev 1.23 14 Jan 1993 17:49:40 Robert_Wolff
|
|
Removed reference to blank screen in message printed before query
|
|
structure filled in, moved printing of this message and the "Done."
|
|
terminator so all checking for video cards is between them.
|
|
|
|
Rev 1.22 14 Jan 1993 10:37:28 Robert_Wolff
|
|
Re-inserted "fail if VGAWonder but no ATI accelerator" check due
|
|
to lack of VGAWONDER .DLL file in late January driver package.
|
|
|
|
Rev 1.21 13 Jan 1993 13:31:04 Robert_Wolff
|
|
Added support for the Corsair and other machines which don't store
|
|
their aperture location in the EEPROM, single miniport now handles
|
|
VGAWonder in addition to accelerators.
|
|
|
|
Rev 1.20 07 Jan 1993 18:20:34 Robert_Wolff
|
|
Now checks to see if aperture is configured but unusable, and
|
|
forces the use of the engine-only driver if this is the case.
|
|
Added message to let users know that the black screen during
|
|
EEPROM read is normal.
|
|
|
|
Rev 1.19 06 Jan 1993 11:04:36 Robert_Wolff
|
|
BIOS locations C0000-DFFFF now mapped as one block, cleaned up warnings.
|
|
|
|
Rev 1.18 04 Jan 1993 14:39:50 Robert_Wolff
|
|
Added card type as a parameter to setmode().
|
|
|
|
Rev 1.17 24 Dec 1992 14:41:20 Chris_Brady
|
|
fixup warnings
|
|
|
|
Rev 1.16 15 Dec 1992 13:34:46 Robert_Wolff
|
|
Writing of MEM_CFG when forcing 4M aperture now preserves all but
|
|
the aperture size bits. This allows operation on Corsair as well
|
|
as standard versions of the Mach 32 card.
|
|
|
|
Rev 1.15 11 Dec 1992 14:45:44 Robert_Wolff
|
|
Now forces the use of the FRAMEBUF driver if a 2M aperture is configured.
|
|
|
|
Rev 1.14 11 Dec 1992 09:47:34 Robert_Wolff
|
|
Now sets the "don't show the substitution message" flag no matter what
|
|
the status of the first call to LookForSubstitute() was (sub, no sub,
|
|
or error), rather than only when a substitution was made and the message
|
|
was displayed.
|
|
|
|
Rev 1.13 10 Dec 1992 14:24:16 Robert_Wolff
|
|
Shortened mode substitution messages in LookForSubstitute(), messages
|
|
are now displayed only on the first call to this routine, to avoid
|
|
delays in switching back to graphics mode from a full-screen DOS box.
|
|
|
|
Rev 1.12 09 Dec 1992 14:18:38 Robert_Wolff
|
|
Eliminated uninitialized pointer in IOCTL_VIDEO_SET_CURRENT_MODE
|
|
packet, moved initialization of QueryPtr and FirstMode pointers
|
|
to before the switch on packet type, rather than being in all
|
|
packets where the pointers are used. This should prevent similar
|
|
problems if other packets are changed to use the pointers, and
|
|
eliminates redundant code.
|
|
|
|
Rev 1.11 09 Dec 1992 10:35:04 Robert_Wolff
|
|
Added user-level "blue-screen" messages for fatal errors, checks BIOS
|
|
revision to catch Mach 8 cards that can't do 1280x1024, forces the
|
|
use of the engine-only driver if no aperture is configured, memory
|
|
boundary and hardware cursor stuff is now done only for Mach 32 cards
|
|
(since they're only available on Mach 32), sets split pixel mode for
|
|
Mach 8 in 1280x1024, added mode substitution message for Mach 8 when
|
|
registry is configured for 16 BPP or higher.
|
|
|
|
Rev 1.10 01 Dec 1992 17:00:18 Robert_Wolff
|
|
"I-beam" text insertion cursor no longer has left side filled with a
|
|
solid black block.
|
|
|
|
Rev 1.9 30 Nov 1992 17:34:38 Robert_Wolff
|
|
Now allows 1M aperture if configured video mode uses less than 1M
|
|
of video memory, prints message to user if Windows NT decides
|
|
to use a video mode other than the one configured in the registry.
|
|
|
|
Rev 1.8 27 Nov 1992 18:40:24 Chris_Brady
|
|
VGA Wonder detect looks for signature in a range.
|
|
Graphics Ultra Pro Microchannel version moved it.
|
|
|
|
Rev 1.7 25 Nov 1992 09:47:36 Robert_Wolff
|
|
Now tells GetCapMach32() to assume the VGA boundary is set to shared,
|
|
since we will set it to this value later, and we don't want to lose
|
|
access to modes which require some of the memory currently assigned
|
|
to the VGA. Added delay in IOCTL_VIDEO_SET_CURRENT_MODE case of
|
|
ATIMPStartIO() after calculating the hardware cursor offset. This delay
|
|
may not be needed, but I didn't want to remove it since this is the
|
|
source for the driver sent to QA and I wanted it to be rebuildable.
|
|
|
|
Rev 1.6 20 Nov 1992 16:04:30 Robert_Wolff
|
|
Now reads query information from Mach 8 cards instead of only
|
|
from Mach 32 cards. Mach 8 cards still cause ATIMPFindAdapter()
|
|
to return ERROR_INVALID_PARAMETER, since until we get an engine-only
|
|
driver, we can't use a card that doesn't support an aperture.
|
|
|
|
Rev 1.5 19 Nov 1992 09:53:36 GRACE
|
|
after setting a mode do a wait for idle to let the pixel clock settle before
|
|
using engine to draw.
|
|
|
|
Rev 1.4 17 Nov 1992 14:07:52 GRACE
|
|
changed framelength to reflect the size of memory on the board not the
|
|
aperture size.
|
|
In the StartIO section, only set up QueryPtr and FirstMode when necessary
|
|
|
|
Rev 1.3 12 Nov 1992 09:23:02 GRACE
|
|
removed the struct definition for DeviceExtension to a68.h
|
|
Not using DevInitATIMP, DevSetCursorShape, DevSetCursorPos or DevCursorOff.
|
|
DevCursorOff changed to a define that turns cursor off with an OUTP.
|
|
Also removed some excess junk that is left from the video program.
|
|
|
|
Rev 1.2 06 Nov 1992 19:12:48 Robert_Wolff
|
|
Fixed signed/unsigned bug in multiple calls to VideoPortInitialize().
|
|
Now requests access to I/O ports and ROM addresses used for VGA-style
|
|
EEPROM reads, and gets information about installed modes from the
|
|
Mach32 card.
|
|
|
|
NOTE: This is a checkpoint for further changes. Due to incompatibilities
|
|
between the old (hardcoded resolution) code in other modules and the
|
|
new (read from the card) code here, this revision will not produce a
|
|
working driver.
|
|
|
|
Rev 1.1 05 Nov 1992 12:02:18 Robert_Wolff
|
|
Now reads query structure and mode tables from the MACH32 card
|
|
rather than using hardcoded values for aperture size/location
|
|
and supported modes.
|
|
|
|
Rev 1.0 02 Nov 1992 20:47:58 Chris_Brady
|
|
Initial revision.
|
|
|
|
|
|
End of PolyTron RCS section *****************/
|
|
|
|
#ifdef DOC
|
|
|
|
DESCRIPTION
|
|
ATI Windows NT Miniport driver for the Mach 64, Mach32, and Mach8
|
|
families.
|
|
This file will select the appropriate functions depending on the
|
|
computer configuration.
|
|
|
|
OTHER FILES
|
|
???
|
|
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "dderror.h"
|
|
#include "devioctl.h"
|
|
#include "miniport.h"
|
|
|
|
#include "ntddvdeo.h"
|
|
#include "video.h"
|
|
#include "stdtyp.h"
|
|
|
|
#include "amach1.h"
|
|
#include "vidlog.h"
|
|
|
|
/*
|
|
* To avoid multiple definition errors, pre-initialized variables
|
|
* in ATIMP.H are initialized if INCLUDE_ATIMP is defined, but
|
|
* are declared external if it is not defined. For consistency,
|
|
* define this value here rather than in other files which also include
|
|
* ATIMP.H so the variables are initialized by the source file with
|
|
* the same root name as the header file.
|
|
*/
|
|
#define INCLUDE_ATIMP
|
|
#include "detect_m.h"
|
|
#include "amachcx.h"
|
|
#include "atimp.h"
|
|
#include "atint.h"
|
|
#include "atioem.h"
|
|
#include "cvtddc.h"
|
|
#include "dpms.h"
|
|
#include "eeprom.h"
|
|
#include "init_cx.h"
|
|
#include "init_m.h"
|
|
#include "modes_m.h"
|
|
#include "query_cx.h"
|
|
#include "query_m.h"
|
|
#include "services.h"
|
|
#include "setup_cx.h"
|
|
#include "setup_m.h"
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
/*
|
|
* Initially assume we have not yet found a non-block card, and
|
|
* have found no block relocatable cards.
|
|
*/
|
|
BOOL FoundNonBlockCard = FALSE;
|
|
USHORT NumBlockCardsFound = 0;
|
|
|
|
/*------------------------------------------------------------------------
|
|
*
|
|
* Function Prototypes
|
|
*
|
|
* Functions that start with 'ATIMP' are entry points for the OS port driver.
|
|
*/
|
|
|
|
ULONG
|
|
DriverEntry (
|
|
PVOID Context1,
|
|
PVOID Context2
|
|
);
|
|
|
|
VP_STATUS
|
|
ATIMPFindAdapter(
|
|
PVOID HwDeviceExtension,
|
|
PVOID HwContext,
|
|
PWSTR ArgumentString,
|
|
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
|
|
PUCHAR Again
|
|
);
|
|
|
|
BOOLEAN
|
|
ATIMPInitialize(
|
|
PVOID HwDeviceExtension
|
|
);
|
|
|
|
BOOLEAN
|
|
ATIMPStartIO(
|
|
PVOID HwDeviceExtension,
|
|
PVIDEO_REQUEST_PACKET RequestPacket
|
|
);
|
|
|
|
BOOLEAN
|
|
ATIMPResetHw(
|
|
IN PVOID HwDeviceExtension,
|
|
IN ULONG Columns,
|
|
IN ULONG Rows
|
|
);
|
|
|
|
//
|
|
// New entry points added for NT 5.0.
|
|
//
|
|
|
|
#if (TARGET_BUILD >= 500)
|
|
|
|
//
|
|
// Routine to set a desired DPMS power management state.
|
|
//
|
|
VP_STATUS
|
|
ATIMPSetPower50(
|
|
PHW_DEVICE_EXTENSION phwDeviceExtension,
|
|
ULONG HwDeviceId,
|
|
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
|
|
);
|
|
|
|
//
|
|
// Routine to retrieve possible DPMS power management states.
|
|
//
|
|
VP_STATUS
|
|
ATIMPGetPower50(
|
|
PHW_DEVICE_EXTENSION phwDeviceExtension,
|
|
ULONG HwDeviceId,
|
|
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
|
|
);
|
|
|
|
//
|
|
// Routine to retrieve the Enhanced Display ID structure via DDC
|
|
//
|
|
ULONG
|
|
ATIMPGetVideoChildDescriptor(
|
|
PVOID pHwDeviceExtension,
|
|
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
|
|
PVIDEO_CHILD_TYPE pChildType,
|
|
PVOID pvChildDescriptor,
|
|
PULONG pHwId,
|
|
PULONG pUnused
|
|
);
|
|
#endif // TARGET_BUILD >= 500
|
|
|
|
|
|
//
|
|
// Routine to set the DPMS power management state.
|
|
//
|
|
BOOLEAN
|
|
SetDisplayPowerState(
|
|
PHW_DEVICE_EXTENSION phwDeviceExtension,
|
|
VIDEO_POWER_STATE VideoPowerState
|
|
);
|
|
|
|
//
|
|
// Routine to retrieve the current DPMS power management state.
|
|
//
|
|
VIDEO_POWER_STATE
|
|
GetDisplayPowerState(
|
|
PHW_DEVICE_EXTENSION phwDeviceExtension
|
|
);
|
|
|
|
|
|
/* */
|
|
UCHAR RegistryBuffer[REGISTRY_BUFFER_SIZE]; /* Last value retrieved from the registry */
|
|
ULONG RegistryBufferLength = 0; /* Size of last retrieved value */
|
|
|
|
/*
|
|
* Allow miniport to be swapped out when not needed.
|
|
*
|
|
* ATIMPResetHw() must be in the non-paged pool.
|
|
*
|
|
*/
|
|
#if defined (ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE_COM, DriverEntry)
|
|
#pragma alloc_text(PAGE_COM, ATIMPFindAdapter)
|
|
#pragma alloc_text(PAGE_COM, ATIMPInitialize)
|
|
#pragma alloc_text(PAGE_COM, ATIMPStartIO)
|
|
#if (TARGET_BUILD >= 500)
|
|
#pragma alloc_text(PAGE_COM, ATIMPSetPower50)
|
|
#pragma alloc_text(PAGE_COM, ATIMPGetPower50)
|
|
#pragma alloc_text(PAGE_COM, ATIMPGetVideoChildDescriptor)
|
|
#endif // TARGET_BUILD >= 500
|
|
#pragma alloc_text(PAGE_COM, RegistryParameterCallback)
|
|
#endif
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
ULONG
|
|
DriverEntry (
|
|
PVOID Context1,
|
|
PVOID Context2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Installable driver initialization entry point.
|
|
This entry point is called directly by the I/O system.
|
|
|
|
Arguments:
|
|
|
|
Context1 - First context value passed by the operating system. This is
|
|
the value with which the miniport driver calls VideoPortInitialize().
|
|
|
|
Context2 - Second context value passed by the operating system. This is
|
|
the value with which the miniport driver calls VideoPortInitialize().
|
|
|
|
Return Value:
|
|
|
|
Status from VideoPortInitialize()
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
VIDEO_HW_INITIALIZATION_DATA hwInitData;
|
|
/*
|
|
* Most recently returned and lowest received so far return values
|
|
* from VideoPortInitialize().
|
|
*
|
|
* BUGBUG: According to the docs and include files, these should
|
|
* be of type VP_STATUS (maps to long). When tracing
|
|
* through the code, however, I saw that a failed call
|
|
* to VideoPortInitialize() due to submitting the wrong
|
|
* bus type yields a code of 0xC00000C0 while one which
|
|
* succeeds yields 0x00000000. When following the format
|
|
* of the NTSTATUS (maps to unsigned long) type, these are
|
|
* STATUS_DEVICE_DOES_NOT_EXIST and STATUS_SUCCESS respectively.
|
|
* The docs on VideoPortInitialize() say to return the smallest
|
|
* returned value if multiple calls are made (consistent with
|
|
* the NTSTATUS format where the 2 most significant bits are
|
|
* 00 for success, 01 for information, 10 for warning, and
|
|
* 11 for error, since the multiple calls would be for mutually
|
|
* exclusive bus types), presumably to return the best possible
|
|
* outcome (fail only if we can't find any supported bus).
|
|
*
|
|
* If we use the VP_STATUS type as recommended, error conditions
|
|
* will be seen as smaller than success, since they are negative
|
|
* numbers (MSB set) and success is positive (MSB clear). Use
|
|
* unsigned long values to avoid this problem.
|
|
*/
|
|
ULONG ThisInitStatus;
|
|
ULONG LowestInitStatus;
|
|
|
|
|
|
VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
|
|
hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
|
|
/*
|
|
* Set entry points.
|
|
*/
|
|
hwInitData.HwFindAdapter = ATIMPFindAdapter;
|
|
hwInitData.HwInitialize = ATIMPInitialize;
|
|
hwInitData.HwInterrupt = NULL;
|
|
hwInitData.HwStartIO = ATIMPStartIO;
|
|
hwInitData.HwResetHw = ATIMPResetHw;
|
|
|
|
#if (TARGET_BUILD >= 500)
|
|
|
|
//
|
|
// Set new entry points added for NT 5.0.
|
|
//
|
|
|
|
//
|
|
// We can only enable these for a PnP driver, and this is not
|
|
// a pnp driver. At least at the moment.
|
|
//
|
|
|
|
hwInitData.HwSetPowerState = ATIMPSetPower50;
|
|
hwInitData.HwGetPowerState = ATIMPGetPower50;
|
|
hwInitData.HwGetVideoChildDescriptor = ATIMPGetVideoChildDescriptor;
|
|
|
|
#endif // TARGET_BUILD >= 500
|
|
|
|
|
|
hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
|
|
|
|
/*
|
|
* Call VideoPortInitialize() once for each type of interface we support.
|
|
* As documented in the DDK, return the lowest status value returned
|
|
* by this function.
|
|
*
|
|
* The DEC Alpha requires the new ordering (PCI first) in both
|
|
* 3.5 and 3.51, while the x86 requires the new ordering in 3.51
|
|
* and the old ordering in 3.5. I haven't built a new miniport
|
|
* for either Power PC or MIPS since implementing the new order,
|
|
* so for now assume that they require the old order.
|
|
*
|
|
* On the x86, using the new order in 3.5 will result in the
|
|
* IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES packet failing on
|
|
* the Mach 32 in PCI systems, which leaves 16 and 24 BPP
|
|
* listed as available in the video applet but being rejected
|
|
* when they are tested.
|
|
*/
|
|
#if !defined(_ALPHA_) && !defined(IOCTL_VIDEO_SHARE_VIDEO_MEMORY)
|
|
hwInitData.AdapterInterfaceType = Eisa;
|
|
LowestInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
|
|
hwInitData.AdapterInterfaceType = Isa;
|
|
ThisInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
if (ThisInitStatus < LowestInitStatus)
|
|
LowestInitStatus = ThisInitStatus;
|
|
|
|
hwInitData.AdapterInterfaceType = MicroChannel;
|
|
ThisInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
if (ThisInitStatus < LowestInitStatus)
|
|
LowestInitStatus = ThisInitStatus;
|
|
|
|
hwInitData.AdapterInterfaceType = PCIBus;
|
|
ThisInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
if (ThisInitStatus < LowestInitStatus)
|
|
LowestInitStatus = ThisInitStatus;
|
|
#else
|
|
hwInitData.AdapterInterfaceType = PCIBus;
|
|
LowestInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
|
|
hwInitData.AdapterInterfaceType = Eisa;
|
|
ThisInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
if (ThisInitStatus < LowestInitStatus)
|
|
LowestInitStatus = ThisInitStatus;
|
|
|
|
hwInitData.AdapterInterfaceType = Isa;
|
|
ThisInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
if (ThisInitStatus < LowestInitStatus)
|
|
LowestInitStatus = ThisInitStatus;
|
|
|
|
hwInitData.AdapterInterfaceType = MicroChannel;
|
|
ThisInitStatus = (ULONG) VideoPortInitialize(Context1, Context2, &hwInitData, NULL);
|
|
if (ThisInitStatus < LowestInitStatus)
|
|
LowestInitStatus = ThisInitStatus;
|
|
#endif
|
|
|
|
return LowestInitStatus;
|
|
|
|
} /* end DriverEntry() */
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
VP_STATUS
|
|
ATIMPFindAdapter(
|
|
PVOID HwDeviceExtension,
|
|
PVOID HwContext,
|
|
PWSTR ArgumentString,
|
|
PVIDEO_PORT_CONFIG_INFO ConfigInfo,
|
|
PUCHAR Again
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This routine is the main execution entry point for the miniport driver.
|
|
It accepts a Video Request Packet, performs the request, and then
|
|
returns with the appropriate status.
|
|
|
|
Arguments:
|
|
HwDeviceExtension - Supplies the miniport driver's adapter storage. This
|
|
storage is initialized to zero before this call.
|
|
|
|
HwContext - Supplies the context value which was passed to
|
|
VideoPortInitialize().
|
|
|
|
ArgumentString - Suuplies a NYLL terminated ASCII string. This string
|
|
originates from the user.
|
|
|
|
ConfigInfo - Returns the configuration information structure which is
|
|
filled by the miniport driver . This structure is initialized with
|
|
any knwon configuration information (such as SystemIoBusNumber) by
|
|
the port driver. Where possible, drivers should have one set of
|
|
defaults which do not require any supplied configuration information.
|
|
|
|
Again - Indicates if the miniport driver wants the port driver to call
|
|
its VIDEO_HW_FIND_ADAPTER function again with a new device extension
|
|
and the same config info. This is used by the miniport drivers which
|
|
can search for several adapters on a bus.
|
|
|
|
Return Value:
|
|
|
|
This routine must return:
|
|
|
|
NO_ERROR - Indicates a host adapter was found and the
|
|
configuration information was successfully determined.
|
|
|
|
ERROR_INVALID_PARAMETER - Indicates a host adapter was found but there was an
|
|
error obtaining the configuration information. If possible an error
|
|
should be logged.
|
|
|
|
ERROR_INVALID_PARAMETER - Indicates the supplied configuration was invalid.
|
|
|
|
ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
|
|
supplied configuration information.
|
|
|
|
--*/
|
|
|
|
{
|
|
VP_STATUS status;
|
|
struct query_structure *QueryPtr; /* Query information for the card */
|
|
phwDeviceExtension = HwDeviceExtension;
|
|
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI: FindAdapter\n"));
|
|
|
|
/*
|
|
* On systems with multiple buses (i.e. any PCI/ISA system), this
|
|
* routine will be called once for each bus, and each invocation
|
|
* will detect the ATI card. To keep Windows NT from thinking that
|
|
* there are multiple cards, check to see if we have found an ATI
|
|
* card on a previous invocation, and if we have, report that there
|
|
* is no ATI card.
|
|
*/
|
|
if (ConfigInfo->AdapterInterfaceType == PCIBus)
|
|
{
|
|
|
|
VIDEO_ACCESS_RANGE AccessRange3C0 = { 0x3C0, 0, 1, 1, 1, 1};
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "PCI bus\n"));
|
|
#if defined(ALPHA) || defined(_ALPHA_)
|
|
/*
|
|
* On the DEC Alpha, our card detection runs into trouble
|
|
* on all but the first (bridged to ISA/EISA, supports
|
|
* VGA BIOS emulation) PCI bus.
|
|
*/
|
|
if (ConfigInfo->SystemIoBusNumber > 0)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "Alpha, not first PCI bus - skipping\n"));
|
|
return ERROR_DEV_NOT_EXIST;
|
|
}
|
|
#endif
|
|
//
|
|
// AndreVa.
|
|
// Since we have a PnP driver, all detection is done throught the
|
|
// inf - no slot searching.
|
|
// Fix code that is lower in DetectMach64 later.
|
|
//
|
|
// For now, just make sure the card is enabled and fail if it's not,
|
|
// so we don't any a different card via the searching mechanism.
|
|
// This only happens if you have a disabled ATI card on the motherboard
|
|
// and an active one in a slot
|
|
//
|
|
|
|
if (NO_ERROR != VideoPortVerifyAccessRanges(HwDeviceExtension,
|
|
1,
|
|
&AccessRange3C0))
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI: PCI FindAdapter called for Disabled card\n"));
|
|
*Again = 0; /* We don't want to be called again */
|
|
return ERROR_DEV_NOT_EXIST;
|
|
}
|
|
|
|
}
|
|
else if (ConfigInfo->AdapterInterfaceType == Isa)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "ISA bus\n"));
|
|
}
|
|
else if (ConfigInfo->AdapterInterfaceType == Eisa)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "EISA bus\n"));
|
|
}
|
|
else if (ConfigInfo->AdapterInterfaceType == MicroChannel)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "MicroChannel bus\n"));
|
|
}
|
|
|
|
if ((FoundNonBlockCard == TRUE) || (NumBlockCardsFound == ATI_MAX_BLOCK_CARDS))
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI: FindAdapter already found maximum number of supported cards\n"));
|
|
*Again = 0; /* We don't want to be called again */
|
|
return ERROR_DEV_NOT_EXIST;
|
|
}
|
|
|
|
/*
|
|
* Get a formatted pointer into the query section of HwDeviceExtension.
|
|
* The CardInfo[] field is an unformatted buffer.
|
|
*/
|
|
QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
/*
|
|
* Save the bus type reported by NT
|
|
*/
|
|
QueryPtr->q_system_bus_type = ConfigInfo->AdapterInterfaceType;
|
|
|
|
|
|
/*
|
|
* Initially we don't know whether or not block write mode is available.
|
|
*/
|
|
QueryPtr->q_BlockWrite = BLOCK_WRITE_UNKNOWN;
|
|
|
|
/*
|
|
* Make sure the size of the structure is at least as large as what we
|
|
* are expecting (check version of the config info structure).
|
|
* If this test fails, it's an unrecoverable error, so we don't want
|
|
* to be called again.
|
|
*/
|
|
if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO))
|
|
{
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_SMALL_BUFFER, 1);
|
|
*Again = 0;
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
/********************************************************************/
|
|
/* Find out which of our accelerators, if any, is present. */
|
|
/********************************************************************/
|
|
|
|
|
|
/*
|
|
* Look for an ATI accelerator card. This test does not require
|
|
* information retrieved from the BIOS or the EEPROM (which may not
|
|
* be present in some versions of our cards).
|
|
*
|
|
* Initially assume that we are looking for a Mach 64 accelerator,
|
|
* since the test for this family is less destructive (doesn't
|
|
* black out the screen on DEC Alpha machines) than the test for
|
|
* one of our 8514/A-compatible accelerators.
|
|
*
|
|
* Don't report failure if we are unable to map the I/O ranges
|
|
* used by the Mach 64 accelerators, since if we are dealing with
|
|
* one of our 8514/A-compatible accelerators this is irrelevant.
|
|
*
|
|
* CompatIORangesUsable_cx() calls DetectMach64() when it's checking
|
|
* to see which base address to use for the accelerator registers,
|
|
* so if this calll succeeds we know that a Mach 64 is present.
|
|
* If the call fails, there is no need to unmap the I/O ranges
|
|
* it has mapped, since it always cleans up after itself when it
|
|
* finds that a particular base address is not being used for a
|
|
* Mach 64. As a result, a failed call will not leave any addresses
|
|
* mapped, since no available base address was used by a Mach 64.
|
|
*/
|
|
if ((status = CompatIORangesUsable_cx(ConfigInfo->AdapterInterfaceType)) == NO_ERROR)
|
|
{
|
|
phwDeviceExtension->ModelNumber = MACH64_ULTRA;
|
|
}
|
|
else if (NumBlockCardsFound == 0)
|
|
{
|
|
/*
|
|
* There is no Mach 64 present, so look for one of our
|
|
* 8514/A-compatible accelerators (Mach 8 and Mach 32).
|
|
* The check on NumBlockCardsFound is to catch the case
|
|
* where we found a relocatable card on a previous bus
|
|
* type, so we won't have dropped out due to FoundNonBlockCard
|
|
* being TRUE but CompatIORangesUsable_cx() won't find
|
|
* a Mach 64 on this bus type.
|
|
*/
|
|
|
|
/*
|
|
* Since we don't use PCI detection, don't look for these cards
|
|
* on the PCI bus, except for the Mach 32 PCI AX
|
|
*/
|
|
if (ConfigInfo->AdapterInterfaceType == PCIBus)
|
|
{
|
|
PCI_COMMON_CONFIG ConfigData;
|
|
ULONG RetVal;
|
|
|
|
RetVal = VideoPortGetBusData(phwDeviceExtension,
|
|
PCIConfiguration,
|
|
0,
|
|
&ConfigData,
|
|
0,
|
|
PCI_COMMON_HDR_LENGTH);
|
|
|
|
/*
|
|
* If we received an error return, skip to the
|
|
* next possible slot.
|
|
*/
|
|
if ((RetVal == PCI_COMMON_HDR_LENGTH) &&
|
|
(ConfigData.VendorID == 0x1002) &&
|
|
(ConfigData.DeviceID == 0x4158))
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "FOUND PnP Mach 32 AX card found\n"));
|
|
}
|
|
else
|
|
{
|
|
*Again = 0;
|
|
return ERROR_DEV_NOT_EXIST;
|
|
}
|
|
}
|
|
|
|
/* If we can't map the I/O base addresses used by these cards,
|
|
* then there is no ATI accelerator present. Unmap any of
|
|
* the ranges which may have been mapped, then report failure.
|
|
*
|
|
* In the event of failure to find a Mach 8 or Mach 32,
|
|
* report that we don't want to be called again for the
|
|
* current bus, but don't set LookForAnotherCard to zero.
|
|
* This is because there may still be a block relocatable
|
|
* card on a subsequent bus.
|
|
*/
|
|
status = CompatIORangesUsable_m();
|
|
if (status != NO_ERROR)
|
|
{
|
|
UnmapIORanges_m();
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_CANT_MAP, 2);
|
|
*Again = 0;
|
|
return status;
|
|
}
|
|
|
|
#if !defined (i386) && !defined (_i386_)
|
|
/*
|
|
* ALPHA - The miniport will have to perform the ROM Bios functions
|
|
* that are normally done on bootup in x86 machines.
|
|
* For now we will initialize them the way they are specifically
|
|
* on this card that we are currently using.
|
|
*/
|
|
AlphaInit_m();
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Check which of our 8514/A-accelerators is present. If we
|
|
* can't find one, unmap the I/O ranges and report failure.
|
|
*
|
|
* Don't log an error, because NT tries all the miniports
|
|
* on initial setup to see which card is installed, and failure
|
|
* to find an ATI card is a normal condition if another brand
|
|
* of accelerator is present.
|
|
*
|
|
*/
|
|
phwDeviceExtension->ModelNumber = WhichATIAccelerator_m();
|
|
if (phwDeviceExtension->ModelNumber == NO_ATI_ACCEL)
|
|
{
|
|
UnmapIORanges_m();
|
|
*Again = 0;
|
|
return ERROR_DEV_NOT_EXIST;
|
|
}
|
|
|
|
/*
|
|
* We have found a Mach 8 or Mach 32. None of these cards are
|
|
* block relocatable, so we must not look for another card
|
|
* (since we don't support a mix of block and non-block
|
|
* cards).
|
|
*/
|
|
FoundNonBlockCard = TRUE;
|
|
LookForAnotherCard = 0;
|
|
|
|
} /* endif (no Mach 64) */
|
|
else
|
|
{
|
|
/*
|
|
* A relocatable Mach 64 was found on a previous bus type.
|
|
* Since we can't handle a mix of relocatable and fixed
|
|
* base cards, we have skipped the Mach 32 search (the
|
|
* Mach 64 search doesn't look for fixed base cards if
|
|
* a relocatable card has already been found), and must
|
|
* report that no ATI cards were found.
|
|
*/
|
|
*Again = 0;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Skipping 8514/A-compatible test because block cards found\n"));
|
|
return ERROR_DEV_NOT_EXIST;
|
|
}
|
|
|
|
/*
|
|
* We have found one of our accelerators, so check for the
|
|
* BIOS signature string.
|
|
*/
|
|
QueryPtr->q_bios = (char *) Get_BIOS_Seg();
|
|
|
|
/*
|
|
* If we can't find the signature string, we can't access either
|
|
* the EEPROM (if present) or the extended BIOS functions. Since
|
|
* the special handling functions (extended Mach 32 aperture calculation
|
|
* and Mach 8 ignore 1280x1024) depend on BIOS data, assume that
|
|
* they don't apply.
|
|
*
|
|
* If we found the signature string, check whether the EEPROM
|
|
* and extended BIOS functions are available.
|
|
*/
|
|
|
|
#if !defined (i386) && !defined (_i386_)
|
|
/*
|
|
* If we are using a Mach 64, we always use the extended BIOS
|
|
* functions (either emulated x86 in the firmware, or an approximation
|
|
* of the BIOS functions accessed through the same interface as
|
|
* the BIOS functions would use). For this reason, we must have
|
|
* the BIOS as non-FALSE. Since all searches that depend on the
|
|
* q_bios field being a valid address are Mach 8/32 specific,
|
|
* we can just set it to TRUE for Mach 64. For Mach 8 and 32,
|
|
* still assume that we don't have a BIOS.
|
|
*/
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "Non-x86 machine with Mach64, assuming BIOS is available\n"));
|
|
QueryPtr->q_bios = (PUCHAR)TRUE;
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "Non-x86 machine with Mach8/Mach32, forcing no-BIOS handling\n"));
|
|
QueryPtr->q_bios = FALSE;
|
|
}
|
|
#endif
|
|
|
|
if (QueryPtr->q_bios == FALSE)
|
|
{
|
|
QueryPtr->q_eeprom = FALSE;
|
|
QueryPtr->q_ext_bios_fcn = FALSE;
|
|
QueryPtr->q_m32_aper_calc = FALSE;
|
|
QueryPtr->q_ignore1280 = FALSE;
|
|
}
|
|
else{
|
|
/*
|
|
* Get additional data required by the graphics card being used.
|
|
*/
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
GetExtraData_m();
|
|
}
|
|
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
/*
|
|
* Mach 64 cards always have extended BIOS functions
|
|
* available. The EEPROM (normally present) is irrelevant,
|
|
* since we can query the card's status using the BIOS.
|
|
*/
|
|
QueryPtr->q_ext_bios_fcn = TRUE;
|
|
}
|
|
|
|
|
|
} /* BIOS signature string found */
|
|
|
|
/*
|
|
* We must map the VGA aperture (graphics, colour text, and mono
|
|
* text) into the VDM's address space to use VideoPortInt10()
|
|
* (function is only available on 80x86).
|
|
*/
|
|
#ifdef i386
|
|
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x000A0000;
|
|
ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
|
|
ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00020000;
|
|
#else
|
|
ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0x00000000;
|
|
ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
|
|
ConfigInfo->VdmPhysicalVideoMemoryLength = 0x00000000;
|
|
#endif
|
|
|
|
/*
|
|
* If we get this far, we have enough information to be able to set
|
|
* the video mode we want. ATI accelerator cards need the
|
|
* Emulator entries and state size cleared
|
|
*/
|
|
ConfigInfo->NumEmulatorAccessEntries = 0;
|
|
ConfigInfo->EmulatorAccessEntries = NULL;
|
|
ConfigInfo->EmulatorAccessEntriesContext = 0;
|
|
|
|
ConfigInfo->HardwareStateSize = 0;
|
|
|
|
/*
|
|
* Setting *Again to 0 tells Windows NT not to call us again for
|
|
* the same bus, while setting it to 1 indicates that we want to
|
|
* look for another card on the current bus. LookForAnotherCard
|
|
* will have been set to 0 if we have found the maximum number
|
|
* of block-relocatable cards or a single non-relocatable card.
|
|
*/
|
|
*Again = LookForAnotherCard;
|
|
|
|
/*
|
|
* Since ATIMPFindAdapter() is called before ATIMPInitialize(),
|
|
* this card has not yet had ATIMPInitialize() called.
|
|
*/
|
|
phwDeviceExtension->CardInitialized = FALSE;
|
|
|
|
return NO_ERROR;
|
|
|
|
} /* end ATIMPFindAdapter() */
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
/***************************************************************************
|
|
*
|
|
* BOOLEAN ATIMPInitialize(HwDeviceExtension);
|
|
*
|
|
* PVOID HwDeviceExtension; Pointer to the miniport's device extension.
|
|
*
|
|
* DESCRIPTION:
|
|
* Query the capabilities of the graphics card, then initialize it. This
|
|
* routine is called once an adapter has been found and all the required
|
|
* data structures for it have been created.
|
|
*
|
|
* We can't query the capabilities of the card in ATIMPFindAdapter()
|
|
* because some families of card use VideoPortInt10() in the query
|
|
* routine, and this system service will fail if called in ATIMPFindAdapter().
|
|
*
|
|
* RETURN VALUE:
|
|
* TRUE if we are able to obtain the query information for the card
|
|
* FALSE if we can't query the card's capabilities.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* phwDeviceExtension This global variable is set in every entry point routine.
|
|
*
|
|
* CALLED BY:
|
|
* This is one of the entry point routines for Windows NT.
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOLEAN ATIMPInitialize(PVOID HwDeviceExtension)
|
|
{
|
|
struct st_mode_table *CrtTable; /* Pointer to current mode */
|
|
struct query_structure *QueryPtr; /* Query information for the card */
|
|
VP_STATUS QueryStatus;
|
|
phwDeviceExtension = HwDeviceExtension;
|
|
|
|
/*
|
|
* We only need to keep track of which I/O base address is involved
|
|
* in multi-headed setups. In some single-headed setups, the
|
|
* additional data is not available.
|
|
*/
|
|
if (NumBlockCardsFound >= 2)
|
|
VideoDebugPrint((DEBUG_NORMAL, "\nATIMPInitialize() called for base address 0x%X\n\n", phwDeviceExtension->BaseIOAddress));
|
|
else
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPInitialize: start\n"));
|
|
|
|
/*
|
|
* This function should only be called once for any card. Since
|
|
* we have no way of knowing whether or not the display driver
|
|
* will make multiple calls to the IOCTL_VIDEO_ATI_INIT_AUX_CARD
|
|
* packet, we must ensure that only the first call for any card
|
|
* actually does anything.
|
|
*/
|
|
if (phwDeviceExtension->CardInitialized != FALSE)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "This card already initialized, no further action needed\n"));
|
|
return TRUE;
|
|
}
|
|
phwDeviceExtension->CardInitialized = TRUE;
|
|
|
|
/*
|
|
* Get a formatted pointer into the query section of HwDeviceExtension,
|
|
* and another pointer to the first mode table. The CardInfo[] field
|
|
* is an unformatted buffer.
|
|
*/
|
|
QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
CrtTable = (struct st_mode_table *)QueryPtr;
|
|
((struct query_structure *)CrtTable)++;
|
|
|
|
/*
|
|
* Indicate that the next IOCTL_VIDEO_SET_CURRENT_MODE call
|
|
* is the first. On the first call, video memory is cleared.
|
|
* On subsequent calls, the palette is re-initialized but
|
|
* video memory is not cleared.
|
|
*/
|
|
phwDeviceExtension->ReInitializing = FALSE;
|
|
|
|
/*
|
|
* ASSERT: We are dealing with an ATI accelerator card
|
|
* whose model is known, and we know whether or not
|
|
* any special handling is needed for the card.
|
|
*
|
|
* Fill in the query structure for the card, using a method
|
|
* appropriate to the card type.
|
|
*/
|
|
switch(phwDeviceExtension->ModelNumber)
|
|
{
|
|
case _8514_ULTRA:
|
|
VideoDebugPrint((DEBUG_NORMAL, "8514/ULTRA found\n"));
|
|
QueryStatus = Query8514Ultra(QueryPtr);
|
|
break;
|
|
|
|
case GRAPHICS_ULTRA:
|
|
VideoDebugPrint((DEBUG_NORMAL, "Mach 8 combo found\n"));
|
|
QueryStatus = QueryGUltra(QueryPtr);
|
|
break;
|
|
|
|
case MACH32_ULTRA:
|
|
VideoDebugPrint((DEBUG_NORMAL, "Mach 32 found\n"));
|
|
QueryStatus = QueryMach32(QueryPtr, TRUE);
|
|
if (QueryStatus == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_SMALL_BUFFER, 3);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case MACH64_ULTRA:
|
|
VideoDebugPrint((DEBUG_NORMAL, "Mach 64 found\n"));
|
|
QueryStatus = QueryMach64(QueryPtr);
|
|
if (QueryStatus == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "QueryMach64() failed due to small buffer\n"));
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_SMALL_BUFFER, 4);
|
|
return FALSE;
|
|
}
|
|
else if (QueryStatus != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "QueryMach64() failed due to unknown cause\n"));
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_QUERY_FAIL, 5);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* If we have access to the extended BIOS functions, we can
|
|
* use them to switch into the desired video mode. If we don't
|
|
* have access to these functions, but were able to read
|
|
* the EEPROM, we can switch into the desired mode by writing
|
|
* CRT parameters directly to the accelerator registers.
|
|
*
|
|
* If we don't have access to the extended BIOS functions, and
|
|
* we couldn't find an EEPROM, attempt to retrieve the CRT
|
|
* parameters based on the contents of the ATIOEM field in
|
|
* the registry. If we can't do this, then we don't have enough
|
|
* information to be able to set the video mode we want.
|
|
*/
|
|
if (!QueryPtr->q_ext_bios_fcn && !QueryPtr->q_eeprom)
|
|
{
|
|
QueryStatus = OEMGetParms(QueryPtr);
|
|
if (QueryStatus != NO_ERROR)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
phwDeviceExtension->VideoRamSize = QueryPtr->q_memory_size * QUARTER_MEG;
|
|
|
|
// Subtract the amount of memory reserved for the VGA.
|
|
phwDeviceExtension->VideoRamSize -= (QueryPtr->q_VGA_boundary * QUARTER_MEG);
|
|
|
|
phwDeviceExtension->PhysicalFrameAddress.HighPart = 0;
|
|
phwDeviceExtension->PhysicalFrameAddress.LowPart = QueryPtr->q_aperture_addr*ONE_MEG;
|
|
|
|
/*
|
|
* If the linear aperture is available, the frame buffer size
|
|
* is equal to the amount of accelerator-accessible video memory.
|
|
*/
|
|
if (QueryPtr->q_aperture_cfg)
|
|
{
|
|
phwDeviceExtension->FrameLength = phwDeviceExtension->VideoRamSize;
|
|
VideoDebugPrint((DEBUG_DETAIL, "LFB size = 0x%X bytes\n", phwDeviceExtension->FrameLength));
|
|
}
|
|
|
|
/*
|
|
* Call the hardware-specific initialization routine for the
|
|
* card we are using.
|
|
*/
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
/*
|
|
* If the LFB is not usable, set up the LFB configuration
|
|
* variables to show that there is no linear frame buffer.
|
|
* The decision as to whether to use the 64k VGA aperture
|
|
* or go with the graphics engine only is made in the
|
|
* IOCTL_VIDEO_MAP_VIDEO_MEMORY packet.
|
|
*/
|
|
if (QueryPtr->q_aperture_cfg)
|
|
{
|
|
if (IsApertureConflict_m(QueryPtr))
|
|
{
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_LFB_CONFLICT, 7);
|
|
QueryPtr->q_aperture_cfg = 0;
|
|
phwDeviceExtension->FrameLength = 0;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* On Mach 32 cards that can use memory mapped registers,
|
|
* map them in. We already know that we are dealing with
|
|
* a Mach 32, since this is the only card in the family
|
|
* of 8514/A-compatible ATI accelerators that can use
|
|
* a linear framebuffer.
|
|
*/
|
|
if ((QueryPtr->q_asic_rev == CI_68800_6) || (QueryPtr->q_asic_rev == CI_68800_AX))
|
|
{
|
|
CompatMMRangesUsable_m();
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* On Mach 32 cards with the aperture disabled (either as configured
|
|
* or because a conflict was detected), try to claim the VGA aperture.
|
|
* If we can't (unlikely), report failure, since some of our Mach 32
|
|
* chips run into trouble in engine-only (neither linear nor paged
|
|
* aperture available) mode.
|
|
*/
|
|
if ((phwDeviceExtension->ModelNumber == MACH32_ULTRA) &&
|
|
(QueryPtr->q_aperture_cfg == 0) &&
|
|
(QueryPtr->q_VGA_type == 1))
|
|
{
|
|
if (IsVGAConflict_m())
|
|
return FALSE;
|
|
}
|
|
|
|
Initialize_m();
|
|
|
|
/*
|
|
* This routine must leave the card in a state where an INT 10
|
|
* can set it to a VGA mode. Only the Mach 8 and Mach 32 need
|
|
* a special setup (the Mach 64 can always be set into VGA mode
|
|
* by an INT 10).
|
|
*/
|
|
ResetDevice_m();
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
/*
|
|
* If the LFB is not usable, set up the LFB configuration
|
|
* variables to show that there is no linear frame buffer.
|
|
*/
|
|
if (QueryPtr->q_aperture_cfg)
|
|
{
|
|
if (IsApertureConflict_cx(QueryPtr))
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "Found LFB conflict, must use VGA aperture instead\n"));
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_LFB_CONFLICT, 8);
|
|
QueryPtr->q_aperture_cfg = 0;
|
|
phwDeviceExtension->FrameLength = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
phwDeviceExtension->FrameLength = 0;
|
|
}
|
|
|
|
/*
|
|
* Mach 64 drawing registers only exist in memory mapped form.
|
|
* If the linear aperture is not available, they will be
|
|
* available through the VGA aperture (unlike Mach 32,
|
|
* where memory mapped registers are only in the linear
|
|
* aperture). If memory mapped registers are unavailable,
|
|
* we can't run.
|
|
*/
|
|
QueryStatus = CompatMMRangesUsable_cx();
|
|
if (QueryStatus != NO_ERROR)
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "Can't use memory-mapped registers, aborting\n"));
|
|
VideoPortLogError(HwDeviceExtension, NULL, VID_CANT_MAP, 9);
|
|
return FALSE;
|
|
}
|
|
Initialize_cx();
|
|
|
|
} /* end if (Mach 64) */
|
|
|
|
/*
|
|
* Initialize the monitor parameters.
|
|
*/
|
|
phwDeviceExtension->ModeIndex = 0;
|
|
|
|
/*
|
|
* Set CrtTable to point to the mode table associated with the
|
|
* selected mode.
|
|
*
|
|
* When a pointer to a structure is incremented by an integer,
|
|
* the integer represents the number of structure-sized blocks
|
|
* to skip over, not the number of bytes to skip over.
|
|
*/
|
|
CrtTable += phwDeviceExtension->ModeIndex;
|
|
QueryPtr->q_desire_x = CrtTable->m_x_size;
|
|
QueryPtr->q_desire_y = CrtTable->m_y_size;
|
|
QueryPtr->q_pix_depth = CrtTable->m_pixel_depth;
|
|
|
|
|
|
#if (TARGET_BUILD >= 350)
|
|
/*
|
|
* In Windows NT 3.5 and higher, fill in regsistry fields used
|
|
* by the display applet to report card specifics to the user.
|
|
*/
|
|
FillInRegistry(QueryPtr);
|
|
#endif
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "End of ATIMPInitialize()\n"));
|
|
|
|
return TRUE;
|
|
|
|
} /* end ATIMPInitialize() */
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
BOOLEAN
|
|
ATIMPStartIO(
|
|
PVOID HwDeviceExtension,
|
|
PVIDEO_REQUEST_PACKET RequestPacket
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the main execution routine for the miniport driver. It
|
|
accepts a Video Request Packet, performs the request, and then returns
|
|
with the appropriate status.
|
|
|
|
Arguments:
|
|
|
|
HwDeviceExtension - Supplies a pointer to the miniport's device extension.
|
|
|
|
RequestPacket - Pointer to the video request packet. This structure
|
|
contains all the parameters passed to the VideoIoControl function.
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
VP_STATUS status;
|
|
PVIDEO_NUM_MODES NumModes;
|
|
PVERSION_NT VersionInformation;
|
|
PENH_VERSION_NT EnhVersionInformation;
|
|
PATI_MODE_INFO ATIModeInformation;
|
|
PVIDEO_CLUT clutBuffer;
|
|
PVIDEO_MEMORY MappedMemory;
|
|
|
|
UCHAR ModesLookedAt; /* Number of mode tables we have already examined */
|
|
short LastXRes; /* X-resolution of last mode table examined */
|
|
short ResolutionsDone; /* Number of resolutions we have finished with */
|
|
ULONG ulScratch; /* Temporary variable */
|
|
|
|
int i;
|
|
ULONG *pSrc;
|
|
|
|
struct query_structure *QueryPtr; /* Query information for the card */
|
|
struct st_mode_table *FirstMode; /* Pointer to first mode table */
|
|
struct st_mode_table *CrtTable; /* Pointer to current mode */
|
|
|
|
phwDeviceExtension = HwDeviceExtension;
|
|
|
|
/*
|
|
* We only need to keep track of which I/O base address is involved
|
|
* in multi-headed setups. In some single-headed setups, the
|
|
* additional data is not available.
|
|
*/
|
|
if (NumBlockCardsFound >= 2)
|
|
VideoDebugPrint((DEBUG_NORMAL, "\nATIMPStartIO() called for base address 0x%X\n\n", phwDeviceExtension->BaseIOAddress));
|
|
|
|
// * Get a formatted pointer into the query section of HwDeviceExtension.
|
|
QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
|
|
//
|
|
// Switch on the IoControlCode in the RequestPacket. It indicates which
|
|
// function must be performed by the driver.
|
|
//
|
|
switch (RequestPacket->IoControlCode)
|
|
{
|
|
case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - MapVideoMemory\n"));
|
|
|
|
if ( (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information =
|
|
sizeof(VIDEO_MEMORY_INFORMATION))) ||
|
|
(RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) )
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Map the video memory in the manner appropriate to the
|
|
* card we are using.
|
|
*/
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
status = MapVideoMemory_m(RequestPacket, QueryPtr);
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
status = MapVideoMemory_cx(RequestPacket, QueryPtr);
|
|
}
|
|
else // handling a case which should never
|
|
{ // happen: unknown ModelNumber
|
|
VideoDebugPrint((DEBUG_ERROR, "ati.sys ATIMPStartIO: Unknown ModelNumber\n"));
|
|
ASSERT(FALSE);
|
|
status = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
break;
|
|
|
|
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - UnMapVideoMemory\n"));
|
|
|
|
if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY))
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Note that in MapVideoMemory_m, the VP routine VideoMapMemory
|
|
// is not called, so don't try to call unmap here!
|
|
//
|
|
|
|
if ((QueryPtr->q_aperture_cfg == 0) &&
|
|
!((phwDeviceExtension->ModelNumber == MACH32_ULTRA) &&
|
|
(QueryPtr->q_VGA_type == 1)))
|
|
status = NO_ERROR;
|
|
else
|
|
{
|
|
status = NO_ERROR;
|
|
if ( ((PVIDEO_MEMORY)(RequestPacket->InputBuffer))->RequestedVirtualAddress != NULL )
|
|
{
|
|
status = VideoPortUnmapMemory(phwDeviceExtension,
|
|
((PVIDEO_MEMORY) (RequestPacket->InputBuffer))->RequestedVirtualAddress, 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - QueryPublicAccessRanges\n"));
|
|
|
|
// HACKHACK - This is a temporary hack for ALPHA until we really
|
|
// decide how to do this.
|
|
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
status = QueryPublicAccessRanges_m(RequestPacket);
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
status = QueryPublicAccessRanges_cx(RequestPacket);
|
|
}
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - FreePublicAccessRanges\n"));
|
|
|
|
if (RequestPacket->InputBufferLength < 2 * sizeof(VIDEO_MEMORY))
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "Received length %d, need length %d\n", RequestPacket->InputBufferLength, sizeof(VIDEO_PUBLIC_ACCESS_RANGES)));
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
status = NO_ERROR;
|
|
MappedMemory = RequestPacket->InputBuffer;
|
|
|
|
if (MappedMemory->RequestedVirtualAddress != NULL)
|
|
{
|
|
#if (TARGET_BUILD >= 400)
|
|
/*
|
|
* This packet will be called as part of the cleanup
|
|
* for the test of a new graphics mode. The packet
|
|
* IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES will have
|
|
* generated the same virtual address for the test
|
|
* screen as was generated for the main Windows session.
|
|
*
|
|
* In NT 3.51 (and presumably earlier versions), the
|
|
* call to VideoPortUnmapMemory() will refuse to release
|
|
* the mapping, while in NT 4.0 (and presumably subsequent
|
|
* versions) it will release the mapping. This is probably
|
|
* due to the routine being able to distinguish between
|
|
* the test and permanent screens in 4.0, but not being
|
|
* able to disginguish between them (and therefore refusing
|
|
* to free resources which it thinks are currently in use
|
|
* by the permanent screen) in 3.51.
|
|
*
|
|
* Freeing resources will be necessary if "on-the-fly"
|
|
* mode switching is added to Windows NT, but this will
|
|
* almost certainly not be added to 3.51 (if it is added,
|
|
* it would be to the then-current version). Since we
|
|
* don't really need to free the mapped I/O ranges under
|
|
* 3.51 (under the old display driver source stream, this
|
|
* packet didn't get called), let 3.51 and earlier think
|
|
* that the resources were freed successfully to avoid
|
|
* generating an error condition, and only attempt to
|
|
* unmap the I/O registers under NT 4.0 and later.
|
|
*/
|
|
status = VideoPortUnmapMemory(phwDeviceExtension,
|
|
MappedMemory->RequestedVirtualAddress,
|
|
0);
|
|
#endif
|
|
VideoDebugPrint((DEBUG_DETAIL, "VideoPortUnmapMemory() returned 0x%X\n", status));
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "Address was NULL, no need to unmap\n"));
|
|
}
|
|
|
|
/*
|
|
* We have just unmapped the I/O mapped registers. Since our
|
|
* memory-mapped registers are contained in the block which
|
|
* is mapped by IOCTL_VIDEO_MAP_VIDEO_MEMORY, they will have
|
|
* already been freed by IOCTL_VIDEO_UNMAP_VIDEO_MEMORY, so
|
|
* there is no need to free them here.
|
|
*/
|
|
break;
|
|
|
|
case IOCTL_VIDEO_QUERY_CURRENT_MODE:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - QueryCurrentModes\n"));
|
|
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
status = QueryCurrentMode_m(RequestPacket, QueryPtr);
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
status = QueryCurrentMode_cx(RequestPacket, QueryPtr);
|
|
}
|
|
break;
|
|
|
|
case IOCTL_VIDEO_QUERY_AVAIL_MODES:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - QueryAvailableModes\n"));
|
|
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
status = QueryAvailModes_m(RequestPacket, QueryPtr);
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
status = QueryAvailModes_cx(RequestPacket, QueryPtr);
|
|
}
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - QueryNumAvailableModes\n"));
|
|
|
|
/*
|
|
* Find out the size of the data to be put in the buffer and
|
|
* return that in the status information
|
|
*/
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information = sizeof(VIDEO_NUM_MODES)) )
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else{
|
|
NumModes = (PVIDEO_NUM_MODES)RequestPacket->OutputBuffer;
|
|
NumModes->NumModes = QueryPtr->q_number_modes;
|
|
NumModes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
|
|
status = NO_ERROR;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_VIDEO_SET_CURRENT_MODE:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - SetCurrentMode\n"));
|
|
|
|
/*
|
|
* Verify that the mode we've been asked to set is less
|
|
* than or equal to the highest mode number for which we
|
|
* have a mode table (mode number is zero-based, so highest
|
|
* mode number is 1 less than number of modes).
|
|
*/
|
|
if (((PVIDEO_MODE)(RequestPacket->InputBuffer))->RequestedMode
|
|
>= QueryPtr->q_number_modes)
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
phwDeviceExtension->ModeIndex = *(ULONG *)(RequestPacket->InputBuffer);
|
|
|
|
CrtTable = (struct st_mode_table *)QueryPtr;
|
|
((struct query_structure *)CrtTable)++;
|
|
|
|
CrtTable += phwDeviceExtension->ModeIndex;
|
|
|
|
// * Set resolution and pixel depth of new current mode.
|
|
QueryPtr->q_desire_x = CrtTable->m_x_size;
|
|
QueryPtr->q_desire_y = CrtTable->m_y_size;
|
|
QueryPtr->q_pix_depth = CrtTable->m_pixel_depth;
|
|
QueryPtr->q_screen_pitch = CrtTable->m_screen_pitch;
|
|
|
|
/*
|
|
* If we are using the extended BIOS functions to switch modes,
|
|
* do it now. The Mach 32 uses the extended BIOS functions to
|
|
* read in the CRT parameters for a direct-register mode switch,
|
|
* rather than using a BIOS mode switch.
|
|
*/
|
|
if ((QueryPtr->q_ext_bios_fcn) && (phwDeviceExtension->ModelNumber != MACH32_ULTRA))
|
|
{
|
|
/*
|
|
* Do the mode switch through the BIOS.
|
|
*/
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
status = SetCurrentMode_cx(QueryPtr, CrtTable);
|
|
}
|
|
}
|
|
else{
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
SetCurrentMode_m(QueryPtr, CrtTable);
|
|
status = NO_ERROR;
|
|
}
|
|
} /* end if (not using BIOS call for mode switch) */
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - SetPaletteRegs\n"));
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case IOCTL_VIDEO_SET_COLOR_REGISTERS:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - SetColorRegs\n"));
|
|
|
|
CrtTable = (struct st_mode_table *)QueryPtr;
|
|
((struct query_structure *)CrtTable)++;
|
|
|
|
clutBuffer = RequestPacket->InputBuffer;
|
|
phwDeviceExtension->ReInitializing = TRUE;
|
|
|
|
/*
|
|
* Check if the size of the data in the input
|
|
* buffer is large enough.
|
|
*/
|
|
if ( (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) - sizeof(ULONG))
|
|
|| (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) +
|
|
(sizeof(ULONG) * (clutBuffer->NumEntries - 1)) ) )
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
CrtTable += phwDeviceExtension->ModeIndex;
|
|
if (CrtTable->m_pixel_depth <= 8)
|
|
{
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == MACH32_ULTRA))
|
|
{
|
|
SetPalette_m((PULONG)clutBuffer->LookupTable,
|
|
clutBuffer->FirstEntry,
|
|
clutBuffer->NumEntries);
|
|
}
|
|
else if(phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
SetPalette_cx((PULONG)clutBuffer->LookupTable,
|
|
clutBuffer->FirstEntry,
|
|
clutBuffer->NumEntries);
|
|
}
|
|
status = NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* Remember the most recent palette we were given so we
|
|
* can re-initialize it in subsequent calls to the
|
|
* IOCTL_VIDEO_SET_CURRENT_MODE packet.
|
|
*/
|
|
phwDeviceExtension->FirstEntry = clutBuffer->FirstEntry;
|
|
phwDeviceExtension->NumEntries = clutBuffer->NumEntries;
|
|
|
|
pSrc = (ULONG *) clutBuffer->LookupTable;
|
|
|
|
for (i = clutBuffer->FirstEntry; i < (int) clutBuffer->NumEntries; i++)
|
|
{
|
|
/*
|
|
* Save palette colours.
|
|
*/
|
|
phwDeviceExtension->Clut[i] = *pSrc;
|
|
pSrc++;
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case IOCTL_VIDEO_RESET_DEVICE:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - RESET_DEVICE\n"));
|
|
|
|
/*
|
|
* If we are using the extended BIOS functions to switch modes,
|
|
* do it now. The Mach 32 uses the extended BIOS functions to
|
|
* read in the CRT parameters for a direct-register mode switch,
|
|
* rather than using a BIOS mode switch.
|
|
*/
|
|
if ((QueryPtr->q_ext_bios_fcn) && (phwDeviceExtension->ModelNumber != MACH32_ULTRA))
|
|
{
|
|
/*
|
|
* Do the mode switch through the BIOS (hook not yet present
|
|
* in Windows NT).
|
|
*/
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
ResetDevice_cx();
|
|
}
|
|
}
|
|
else{
|
|
ResetDevice_m();
|
|
}
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_SET_POWER_MANAGEMENT:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - SET_POWER_MANAGEMENT\n"));
|
|
|
|
/*
|
|
* If the VIDEO_POWER_MANAGEMENT structure is the wrong size
|
|
* (miniport and display driver using different versions),
|
|
* report the error.
|
|
*/
|
|
if (((PVIDEO_POWER_MANAGEMENT)(RequestPacket->InputBuffer))->Length
|
|
!= sizeof(struct _VIDEO_POWER_MANAGEMENT))
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
ulScratch = ((PVIDEO_POWER_MANAGEMENT)(RequestPacket->InputBuffer))->PowerState;
|
|
|
|
switch (ulScratch)
|
|
{
|
|
case VideoPowerOn:
|
|
VideoDebugPrint((DEBUG_DETAIL, "DPMS ON selected\n"));
|
|
break;
|
|
|
|
case VideoPowerStandBy:
|
|
VideoDebugPrint((DEBUG_DETAIL, "DPMS STAND-BY selected\n"));
|
|
break;
|
|
|
|
case VideoPowerSuspend:
|
|
VideoDebugPrint((DEBUG_DETAIL, "DPMS SUSPEND selected\n"));
|
|
break;
|
|
|
|
case VideoPowerOff:
|
|
VideoDebugPrint((DEBUG_DETAIL, "DPMS OFF selected\n"));
|
|
break;
|
|
|
|
default:
|
|
VideoDebugPrint((DEBUG_ERROR, "DPMS invalid state selected\n"));
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Different card families need different routines to set
|
|
* the power management state.
|
|
*/
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
status = SetPowerManagement_cx(ulScratch);
|
|
else
|
|
status = SetPowerManagement_m(QueryPtr, ulScratch);
|
|
break;
|
|
|
|
|
|
/*
|
|
* Packets used in DCI support. They were added some time after
|
|
* the initial release of Windows NT 3.5, so not all versions of
|
|
* the DDK will support them. Make the packet code conditional on
|
|
* our building a driver for NT version 3.51 or later in order to
|
|
* avoid the need for a SOURCES flag to identify DCI vs. non-DCI builds.
|
|
*/
|
|
#if (TARGET_BUILD >= 351)
|
|
case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - SHARE_VIDEO_MEMORY\n"));
|
|
|
|
if ((RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) ||
|
|
(RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)))
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "IOCTL_VIDEO_SHARE_VIDEO_MEMORY - ERROR_INSUFFICIENT_BUFFER\n"));
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Share the video memory in the manner appropriate to the
|
|
* card we are using. We can only share memory if the
|
|
* card supports an aperture - Mach 8 cards never support
|
|
* an aperture, so if we are working with one, we know
|
|
* that we can't share the memory. The card-specific
|
|
* routines will identify no-aperture and other cases
|
|
* where we can't share video memory on Mach 32 and
|
|
* Mach 64 cards.
|
|
*/
|
|
if ((phwDeviceExtension->ModelNumber == _8514_ULTRA) ||
|
|
(phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA))
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "IOCTL_VIDEO_SHARE_VIDEO_MEMORY - Mach 8 can't share memory\n"));
|
|
status = ERROR_INVALID_FUNCTION;
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
|
|
{
|
|
status = ShareVideoMemory_m(RequestPacket, QueryPtr);
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
status = ShareVideoMemory_cx(RequestPacket, QueryPtr);
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - UNSHARE_VIDEO_MEMORY\n"));
|
|
|
|
if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY))
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
status = VideoPortUnmapMemory(phwDeviceExtension,
|
|
((PVIDEO_SHARE_MEMORY)(RequestPacket->InputBuffer))->RequestedVirtualAddress,
|
|
((PVIDEO_SHARE_MEMORY)(RequestPacket->InputBuffer))->ProcessHandle);
|
|
|
|
break;
|
|
#endif /* TARGET_BUILD >= 350 */
|
|
|
|
|
|
// ------ * ATI-specific packets start here. -------------
|
|
/*
|
|
* Get the version number of the miniport, and the
|
|
* resolutions supported (including maximum colour
|
|
* depth).
|
|
*/
|
|
case IOCTL_VIDEO_ATI_GET_VERSION:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - ATIGetVersion\n"));
|
|
|
|
/*
|
|
* Two versions of this packet exist, depending on which display
|
|
* driver is used. Display drivers which use the old version do
|
|
* not send information to the miniport, so the input buffer is
|
|
* null. Drivers which use the new version pass a non-null input
|
|
* buffer.
|
|
*/
|
|
if (RequestPacket->InputBufferLength == 0)
|
|
{
|
|
/*
|
|
* Old packet.
|
|
*/
|
|
if (RequestPacket->OutputBufferLength < sizeof(VERSION_NT))
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
RequestPacket->StatusBlock->Information = sizeof(VERSION_NT);
|
|
|
|
FirstMode = (struct st_mode_table *)QueryPtr;
|
|
((struct query_structure *)FirstMode)++;
|
|
|
|
VersionInformation = RequestPacket->OutputBuffer;
|
|
VersionInformation->miniport =
|
|
(MINIPORT_BUILD << 16) | (MINIPORT_VERSION_MAJOR << 8) | MINIPORT_VERSION_MINOR;
|
|
|
|
/*
|
|
* Get the capabilities of the video card. The capcard field
|
|
* holds the following information:
|
|
*
|
|
* Bits 0-3 Bus type (defined values from AMACH.H)
|
|
* Bits 4-7 Product identifier (defined values from AMACH.H)
|
|
* Bit 8 No aperture is available
|
|
* Bit 9 64k VGA aperture is available
|
|
* Bit 10 Linear aperture is available
|
|
*
|
|
* NOTE: Bits 9 and 10 are NOT mutually exclusive.
|
|
*/
|
|
VersionInformation->capcard = QueryPtr->q_bus_type;
|
|
VersionInformation->capcard |= (phwDeviceExtension->ModelNumber) << 4;
|
|
|
|
if (QueryPtr->q_aperture_cfg)
|
|
VersionInformation->capcard |= ATIC_APERTURE_LFB;
|
|
|
|
/*
|
|
* 64k VGA aperture is available on the VGAWonder, and on
|
|
* accelerator cards with the VGA enabled and the VGA boundary
|
|
* set to shared memory.
|
|
*/
|
|
if ((phwDeviceExtension->ModelNumber == WONDER) ||
|
|
((QueryPtr->q_VGA_type) && !(QueryPtr->q_VGA_boundary)))
|
|
VersionInformation->capcard |= ATIC_APERTURE_VGA;
|
|
|
|
/*
|
|
* If neither aperture is available, set the "no aperture" bit.
|
|
*/
|
|
if (!(VersionInformation->capcard & ATIC_APERTURE_LFB) &&
|
|
!(VersionInformation->capcard & ATIC_APERTURE_VGA))
|
|
VersionInformation->capcard |= ATIC_APERTURE_NONE;
|
|
|
|
// Get the available resolutions and maximum colour depth for
|
|
// each. init to a value which does not correspond to any
|
|
// resolution.
|
|
CrtTable = FirstMode;
|
|
LastXRes = -1;
|
|
ResolutionsDone = -1;
|
|
for (ModesLookedAt = 0; ModesLookedAt < QueryPtr->q_number_modes; ModesLookedAt++)
|
|
{
|
|
// do we have a new resolution?
|
|
if (LastXRes != CrtTable->m_x_size)
|
|
{
|
|
ResolutionsDone++;
|
|
LastXRes = CrtTable->m_x_size;
|
|
VersionInformation->resolution[ResolutionsDone].color = 0;
|
|
}
|
|
|
|
/*
|
|
* Write the desired information from the current mode table
|
|
* in the query structure into the current mode table in
|
|
* the OUTPut buffer.
|
|
* Leave the OUTPut buffer with the highest colour depth in
|
|
* each supported resolution.
|
|
*/
|
|
if (CrtTable->m_pixel_depth > VersionInformation->resolution[ResolutionsDone].color)
|
|
{
|
|
VersionInformation->resolution[ResolutionsDone].xres = CrtTable->m_x_size;
|
|
VersionInformation->resolution[ResolutionsDone].yres = CrtTable->m_y_size;
|
|
VersionInformation->resolution[ResolutionsDone].color= CrtTable->m_pixel_depth;
|
|
}
|
|
|
|
CrtTable++; // Advance to the next mode table
|
|
}
|
|
status = NO_ERROR;
|
|
}
|
|
else if((RequestPacket->InputBuffer == RequestPacket->OutputBuffer) &&
|
|
(((PENH_VERSION_NT)(RequestPacket->InputBuffer))->StructureVersion == 0) &&
|
|
(((PENH_VERSION_NT)(RequestPacket->InputBuffer))->InterfaceVersion == 0))
|
|
{
|
|
/*
|
|
* Interim packet
|
|
*/
|
|
|
|
if (RequestPacket->OutputBufferLength < sizeof(ENH_VERSION_NT))
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
|
|
RequestPacket->StatusBlock->Information = sizeof(ENH_VERSION_NT);
|
|
|
|
EnhVersionInformation = RequestPacket->OutputBuffer;
|
|
|
|
/*
|
|
* Report the miniport version we are using.
|
|
*/
|
|
// EnhVersionInformation->InterfaceVersion = (MINIPORT_VERSION_MAJOR << 8) | MINIPORT_VERSION_MINOR;
|
|
EnhVersionInformation->InterfaceVersion = 0;
|
|
|
|
/*
|
|
* Remove the following line ONLY for official release versions
|
|
* of the miniport. This line indicates that this is an
|
|
* experimental (unsupported) version.
|
|
*/
|
|
EnhVersionInformation->InterfaceVersion |= BETA_MINIPORT;
|
|
|
|
/*
|
|
* Report the chip used as both a numeric value and a flag.
|
|
*/
|
|
EnhVersionInformation->ChipIndex = QueryPtr->q_asic_rev;
|
|
EnhVersionInformation->ChipFlag = 1 << (QueryPtr->q_asic_rev);
|
|
|
|
/*
|
|
* Report the best aperture configuration available.
|
|
*
|
|
* Linear Framebuffer is preferable to VGA aperture,
|
|
* which is preferable to engine-only.
|
|
*
|
|
* NOTE: VGA aperture will need to be split into
|
|
* 68800-style and 68800CX-style once we
|
|
* go from the emulator to silicon.
|
|
*/
|
|
if (QueryPtr->q_aperture_cfg != 0)
|
|
EnhVersionInformation->ApertureType = AP_LFB;
|
|
else if ((QueryPtr->q_asic_rev != CI_38800_1) && (QueryPtr->q_VGA_type == 1))
|
|
EnhVersionInformation->ApertureType = AP_68800_VGA;
|
|
else
|
|
EnhVersionInformation->ApertureType = ENGINE_ONLY;
|
|
EnhVersionInformation->ApertureFlag = 1 << (EnhVersionInformation->ApertureType);
|
|
|
|
/*
|
|
* Report the bus type being used.
|
|
*/
|
|
EnhVersionInformation->BusType = QueryPtr->q_bus_type;
|
|
EnhVersionInformation->BusFlag = 1 << (EnhVersionInformation->BusType);
|
|
|
|
/*
|
|
* For ASIC revisions that are capable of using memory mapped
|
|
* registers, check to see whether we are using them.
|
|
*/
|
|
if ((QueryPtr->q_asic_rev == CI_68800_6) || (QueryPtr->q_asic_rev == CI_68800_AX))
|
|
{
|
|
if (MemoryMappedEnabled_m())
|
|
EnhVersionInformation->BusFlag |= FL_MM_REGS;
|
|
}
|
|
|
|
/*
|
|
* Report the number of ATI graphics cards in the system,
|
|
* so the display driver will know how many auxillary
|
|
* cards to initialize.
|
|
*
|
|
* Since multiheaded support requires all the ATI cards
|
|
* present to be block I/O cards, the global variable
|
|
* NumBlockCardsFound will always be 2 or higher in
|
|
* multiheaded systems. If it is 0 (non-block card found,
|
|
* since we will never get to this point if there are
|
|
* no ATI cards) or 1 (single block I/O card), report
|
|
* that there is 1 ATI card present.
|
|
*/
|
|
if (NumBlockCardsFound >= 2)
|
|
EnhVersionInformation->NumCards = NumBlockCardsFound;
|
|
else
|
|
EnhVersionInformation->NumCards = 1;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Reporting %d cards\n", EnhVersionInformation->NumCards));
|
|
|
|
/*
|
|
* Fill in the list of features this card supports.
|
|
*
|
|
* We can disable the sync signals even on cards that
|
|
* don't have registers dedicated to DPMS support, so
|
|
* all our cards support DPMS.
|
|
*/
|
|
EnhVersionInformation->FeatureFlags = EVN_DPMS;
|
|
|
|
/*
|
|
* All platforms except the DEC Alpha are always
|
|
* capable of using dense space. On the Alpha,
|
|
* some machines with some of our cards are
|
|
* capable of using dense space, while others
|
|
* aren't.
|
|
*/
|
|
#if defined(_ALPHA_)
|
|
if (DenseOnAlpha(QueryPtr) == TRUE)
|
|
{
|
|
EnhVersionInformation->FeatureFlags |= EVN_DENSE_CAPABLE;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Reporting dense capable in FeatureFlags\n"));
|
|
}
|
|
#else
|
|
EnhVersionInformation->FeatureFlags |= EVN_DENSE_CAPABLE;
|
|
#endif
|
|
if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
|
|
{
|
|
if ((QueryPtr->q_asic_rev == CI_68800_6) && (QueryPtr->q_aperture_cfg == 0)
|
|
&& (QueryPtr->q_VGA_type == 1) && ((QueryPtr->q_memory_type == 5) ||
|
|
(QueryPtr->q_memory_type == 6)))
|
|
EnhVersionInformation->FeatureFlags |= EVN_SPLIT_TRANS;
|
|
if (IsMioBug_m(QueryPtr))
|
|
EnhVersionInformation->FeatureFlags |= EVN_MIO_BUG;
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
if (IsPackedIO_cx())
|
|
EnhVersionInformation->FeatureFlags |= EVN_PACKED_IO;
|
|
|
|
if ((QueryPtr->q_memory_type == VMEM_SDRAM) &&
|
|
(QueryPtr->q_memory_size == VRAM_1mb))
|
|
EnhVersionInformation->FeatureFlags |= EVN_SDRAM_1M;
|
|
|
|
if (QueryPtr->q_DAC_type == DAC_TVP3026)
|
|
{
|
|
EnhVersionInformation->FeatureFlags |= EVN_TVP_DAC_CUR;
|
|
}
|
|
else if (QueryPtr->q_DAC_type == DAC_IBM514)
|
|
{
|
|
EnhVersionInformation->FeatureFlags |= EVN_IBM514_DAC_CUR;
|
|
}
|
|
else if (QueryPtr->q_DAC_type == DAC_INTERNAL_CT)
|
|
{
|
|
EnhVersionInformation->FeatureFlags |= EVN_INT_DAC_CUR;
|
|
EnhVersionInformation->FeatureFlags |= EVN_CT_ASIC;
|
|
}
|
|
else if (QueryPtr->q_DAC_type == DAC_INTERNAL_VT)
|
|
{
|
|
EnhVersionInformation->FeatureFlags |= EVN_INT_DAC_CUR;
|
|
EnhVersionInformation->FeatureFlags |= EVN_VT_ASIC;
|
|
}
|
|
else if (QueryPtr->q_DAC_type == DAC_INTERNAL_GT)
|
|
{
|
|
EnhVersionInformation->FeatureFlags |= EVN_INT_DAC_CUR;
|
|
EnhVersionInformation->FeatureFlags |= EVN_GT_ASIC;
|
|
}
|
|
}
|
|
/*
|
|
* Currently there are no feature flags specific to the Mach 8.
|
|
*/
|
|
|
|
status = NO_ERROR;
|
|
}
|
|
else /* Final form of the packet is not yet defined */
|
|
{
|
|
status = ERROR_INVALID_FUNCTION;
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
* Packet to return information regarding the capabilities/bugs
|
|
* of the current mode.
|
|
*/
|
|
case IOCTL_VIDEO_ATI_GET_MODE_INFORMATION:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - ATIGetModeInformation\n"));
|
|
if (RequestPacket->OutputBufferLength <
|
|
(RequestPacket->StatusBlock->Information = sizeof(ENH_VERSION_NT)))
|
|
{
|
|
status = ERROR_INSUFFICIENT_BUFFER;
|
|
break;
|
|
}
|
|
ATIModeInformation = RequestPacket->OutputBuffer;
|
|
ATIModeInformation->ModeFlags = 0;
|
|
|
|
/*
|
|
* Information regarding the visible portion of the screen.
|
|
*/
|
|
ATIModeInformation->VisWidthPix = QueryPtr->q_desire_x;
|
|
ATIModeInformation->VisHeight = QueryPtr->q_desire_y;
|
|
ATIModeInformation->BitsPerPixel = QueryPtr->q_pix_depth;
|
|
|
|
/*
|
|
* We require the true pitch in 24bpp
|
|
*/
|
|
if (QueryPtr->q_pix_depth == 24)
|
|
{
|
|
ATIModeInformation->PitchPix = QueryPtr->q_screen_pitch * 3;
|
|
}
|
|
else
|
|
{
|
|
ATIModeInformation->PitchPix = QueryPtr->q_screen_pitch;
|
|
}
|
|
/*
|
|
* The FracBytesPerPixel field represents the first 3 places
|
|
* of decimal in the fractional part of bytes per pixel.
|
|
* No precision is lost, because the smallest granularity
|
|
* (one bit per pixel) is 0.125 bytes per pixel, and any
|
|
* multiple of this value does not extend beyond 3 places
|
|
* of decimal.
|
|
*
|
|
* Mach 8 1280x1024 4BPP is packed pixel, other 4BPP modes all
|
|
* ignore the upper 4 bits of each byte.
|
|
*/
|
|
if ((QueryPtr->q_pix_depth == 4) &&
|
|
!((QueryPtr->q_asic_rev == CI_38800_1) && (QueryPtr->q_desire_x == 1280)))
|
|
{
|
|
ATIModeInformation->IntBytesPerPixel = 1;
|
|
ATIModeInformation->FracBytesPerPixel = 0;
|
|
}
|
|
else{
|
|
ATIModeInformation->IntBytesPerPixel = QueryPtr->q_pix_depth / 8;
|
|
switch (QueryPtr->q_pix_depth % 8)
|
|
{
|
|
case 0:
|
|
ATIModeInformation->FracBytesPerPixel = 0;
|
|
break;
|
|
|
|
case 1:
|
|
ATIModeInformation->FracBytesPerPixel = 125;
|
|
break;
|
|
|
|
case 2:
|
|
ATIModeInformation->FracBytesPerPixel = 250;
|
|
break;
|
|
|
|
case 3:
|
|
ATIModeInformation->FracBytesPerPixel = 375;
|
|
break;
|
|
|
|
case 4:
|
|
ATIModeInformation->FracBytesPerPixel = 500;
|
|
break;
|
|
|
|
case 5:
|
|
ATIModeInformation->FracBytesPerPixel = 625;
|
|
break;
|
|
|
|
case 6:
|
|
ATIModeInformation->FracBytesPerPixel = 750;
|
|
break;
|
|
|
|
case 7:
|
|
ATIModeInformation->FracBytesPerPixel = 875;
|
|
break;
|
|
}
|
|
}
|
|
ATIModeInformation->PitchByte = (QueryPtr->q_screen_pitch *
|
|
((ATIModeInformation->IntBytesPerPixel * 1000) + ATIModeInformation->FracBytesPerPixel)) / 8000;
|
|
ATIModeInformation->VisWidthByte = (QueryPtr->q_desire_x *
|
|
((ATIModeInformation->IntBytesPerPixel * 1000) + ATIModeInformation->FracBytesPerPixel)) / 8000;
|
|
|
|
/*
|
|
* Information regarding the offscreen memory to the right
|
|
* of the visible screen.
|
|
*/
|
|
ATIModeInformation->RightWidthPix = ATIModeInformation->PitchPix - ATIModeInformation->VisWidthPix;
|
|
ATIModeInformation->RightWidthByte = ATIModeInformation->PitchByte - ATIModeInformation->VisWidthByte;
|
|
ATIModeInformation->RightStartOffPix = ATIModeInformation->VisWidthPix + 1;
|
|
ATIModeInformation->RightStartOffByte = ATIModeInformation->VisWidthByte + 1;
|
|
ATIModeInformation->RightEndOffPix = ATIModeInformation->PitchPix;
|
|
ATIModeInformation->RightEndOffByte = ATIModeInformation->PitchByte;
|
|
|
|
/*
|
|
* Information regarding the offscreen memory below the
|
|
* visible screen.
|
|
*/
|
|
ATIModeInformation->BottomWidthPix = ATIModeInformation->PitchPix;
|
|
ATIModeInformation->BottomWidthByte = ATIModeInformation->PitchByte;
|
|
ATIModeInformation->BottomStartOff = ATIModeInformation->VisHeight + 1;
|
|
/*
|
|
* "Hard" values are the maximum Y coordinate which is backed by
|
|
* video memory. "Soft" values are the maximum Y coordinate which
|
|
* may be accessed without resetting the graphic engine offset
|
|
* into video memory.
|
|
*
|
|
* In 4BPP modes, we always force the card to think it has
|
|
* only 1M of memory.
|
|
*/
|
|
if (QueryPtr->q_pix_depth == 4)
|
|
{
|
|
ATIModeInformation->BottomEndOffHard = ONE_MEG / ATIModeInformation->PitchByte;
|
|
}
|
|
else
|
|
{
|
|
ATIModeInformation->BottomEndOffHard = ((QueryPtr->q_memory_size - QueryPtr->q_VGA_boundary)
|
|
* QUARTER_MEG) / ATIModeInformation->PitchByte;
|
|
}
|
|
if ((QueryPtr->q_asic_rev == CI_88800_GX) && (ATIModeInformation->BottomEndOffHard > 16387))
|
|
ATIModeInformation->BottomEndOffSoft = 16387;
|
|
else if (ATIModeInformation->BottomEndOffHard > 1535)
|
|
ATIModeInformation->BottomEndOffSoft = 1535;
|
|
else
|
|
ATIModeInformation->BottomEndOffSoft = ATIModeInformation->BottomEndOffHard;
|
|
ATIModeInformation->BottomHeightHard = ATIModeInformation->BottomEndOffHard - ATIModeInformation->VisHeight;
|
|
ATIModeInformation->BottomHeightSoft = ATIModeInformation->BottomEndOffSoft - ATIModeInformation->VisHeight;
|
|
|
|
/*
|
|
* Fill in the list of "quirks" experienced by this particular mode.
|
|
*/
|
|
if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
|
|
{
|
|
if (((QueryPtr->q_desire_x == 1280) && (QueryPtr->q_desire_y == 1024)) ||
|
|
(((QueryPtr->q_DAC_type == DAC_STG1700) ||
|
|
(QueryPtr->q_DAC_type == DAC_STG1702) ||
|
|
(QueryPtr->q_DAC_type == DAC_STG1703)) && (QueryPtr->q_pix_depth >= 24)))
|
|
{
|
|
ATIModeInformation->ModeFlags |= AMI_ODD_EVEN;
|
|
}
|
|
|
|
/*
|
|
* The test for block write mode must be made after we
|
|
* switch into graphics mode, but it is not mode dependent.
|
|
*
|
|
* Because the test corrupts the screen, and is not
|
|
* mode dependent, only run it the first time this
|
|
* packet is called and save the result to report
|
|
* on subsequent calls.
|
|
*/
|
|
if (QueryPtr->q_BlockWrite == BLOCK_WRITE_UNKNOWN)
|
|
{
|
|
if (BlockWriteAvail_m(QueryPtr))
|
|
QueryPtr->q_BlockWrite = BLOCK_WRITE_YES;
|
|
else
|
|
QueryPtr->q_BlockWrite = BLOCK_WRITE_NO;
|
|
}
|
|
if (QueryPtr->q_BlockWrite == BLOCK_WRITE_YES)
|
|
ATIModeInformation->ModeFlags |= AMI_BLOCK_WRITE;
|
|
}
|
|
else if(phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
if (((QueryPtr->q_DAC_type == DAC_STG1700) ||
|
|
(QueryPtr->q_DAC_type == DAC_STG1702) ||
|
|
(QueryPtr->q_DAC_type == DAC_STG1703) ||
|
|
(QueryPtr->q_DAC_type == DAC_ATT408) ||
|
|
(QueryPtr->q_DAC_type == DAC_CH8398)) &&
|
|
(QueryPtr->q_pix_depth >= 24))
|
|
ATIModeInformation->ModeFlags |= AMI_ODD_EVEN;
|
|
if (((QueryPtr->q_pix_depth == 24) && (QueryPtr->q_desire_x == 1280)) ||
|
|
((QueryPtr->q_pix_depth == 24) && (QueryPtr->q_desire_x == 1152)) ||
|
|
((QueryPtr->q_pix_depth == 16) && (QueryPtr->q_desire_x == 1600)))
|
|
ATIModeInformation->ModeFlags |= AMI_2M_BNDRY;
|
|
|
|
if (TextBanding_cx(QueryPtr))
|
|
ATIModeInformation->ModeFlags |= AMI_TEXTBAND;
|
|
|
|
/*
|
|
* See Mach 32 section above for explanation.
|
|
*/
|
|
if (QueryPtr->q_BlockWrite == BLOCK_WRITE_UNKNOWN)
|
|
{
|
|
if (BlockWriteAvail_cx(QueryPtr))
|
|
QueryPtr->q_BlockWrite = BLOCK_WRITE_YES;
|
|
else
|
|
QueryPtr->q_BlockWrite = BLOCK_WRITE_NO;
|
|
}
|
|
if (QueryPtr->q_BlockWrite == BLOCK_WRITE_YES)
|
|
ATIModeInformation->ModeFlags |= AMI_BLOCK_WRITE;
|
|
}
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
|
|
/*
|
|
* Packet to force initialization of auxillary card in multiheaded
|
|
* setup. Currently (NT 3.51 retail), only the primrary card
|
|
* receives a call to ATIMPInitialize().
|
|
*
|
|
* This packet must be called for all auxillary cards before
|
|
* IOCTL_VIDEO_SET_CURRENT_MODE is called for any card, since
|
|
* ATIMPInitialize() uses resources that are only available
|
|
* when the primrary (VGA enabled) card is in a VGA mode.
|
|
*/
|
|
case IOCTL_VIDEO_ATI_INIT_AUX_CARD:
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO - ATIInitAuxCard\n"));
|
|
ATIMPInitialize(phwDeviceExtension);
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
VideoDebugPrint((DEBUG_ERROR, "Fell through ATIMP startIO routine - invalid command\n"));
|
|
status = ERROR_INVALID_FUNCTION;
|
|
break;
|
|
|
|
}
|
|
|
|
RequestPacket->StatusBlock->Status = status;
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATIMPStartIO: Returning with status=%d\n", status));
|
|
|
|
return TRUE;
|
|
|
|
} // end ATIMPStartIO()
|
|
|
|
/***************************************************************************
|
|
*
|
|
* BOOLEAN ATIMPResetHw(HwDeviceExtension, Columns, Rows);
|
|
*
|
|
* PVOID HwDeviceExtension; Pointer to the miniport's device extension.
|
|
* ULONG Columns; Number of character columns on text screen
|
|
* ULONG Rows; Number of character rows on text screen
|
|
*
|
|
* DESCRIPTION:
|
|
* Put the graphics card into either a text mode or a state where an
|
|
* INT 10 call will put it into a text mode.
|
|
*
|
|
* GLOBALS CHANGED:
|
|
* phwDeviceExtension This global variable is set in every entry point routine.
|
|
*
|
|
* CALLED BY:
|
|
* This is one of the entry point routines for Windows NT.
|
|
*
|
|
* AUTHOR:
|
|
* Robert Wolff
|
|
*
|
|
* CHANGE HISTORY:
|
|
*
|
|
* TEST HISTORY:
|
|
*
|
|
***************************************************************************/
|
|
|
|
BOOLEAN ATIMPResetHw(PVOID HwDeviceExtension, ULONG Columns, ULONG Rows)
|
|
{
|
|
phwDeviceExtension = HwDeviceExtension;
|
|
|
|
/*
|
|
* On the Mach 64, an INT 10 to VGA text mode will work even
|
|
* when in accelerator mode, so we don't need to explicitly
|
|
* switch out of accelerator mode. On the Mach 8 and Mach 32,
|
|
* we must switch out of accelerator mode, and on the Mach 32
|
|
* we must load the VGA text font.
|
|
*
|
|
* On the Mach 64, some non-x86 machines (first noticed on the
|
|
* DEC Alpha) don't do the warm boot BIOS re-initialization that
|
|
* is done on the x86. Part of this re-initialization sets the
|
|
* memory size register to the correct amount of memory, which
|
|
* must be done if we were in a 4BPP mode (in 4BPP, we must force
|
|
* the memory size to 1M). To avoid locking out modes requiring
|
|
* over 1M (at least until the next cold boot) on these machines,
|
|
* we must restore the memory size to the correct value. Since this
|
|
* has the side effect of generating black vertical bands as a
|
|
* transient (due to interleaving of memory banks on 2M and higher
|
|
* configurations), only do this on non-x86 machines, since the
|
|
* BIOS will take care of it (without the visible side effect)
|
|
* on x86 platforms.
|
|
*
|
|
* Since this routine, and all routines it calls, must be
|
|
* nonpageable (in case the reason it is called is because
|
|
* there is a fatal error in the paging mechanism), and
|
|
* VideoDebugPrint() is pageable, we must not call VideoDebugPrint()
|
|
* from this routine. Temporary additions for testing are OK,
|
|
* but the calls must be removed before the code is released
|
|
* for production.
|
|
*/
|
|
#if defined (i386) || defined (_i386_)
|
|
if (phwDeviceExtension->ModelNumber != MACH64_ULTRA)
|
|
SetTextMode_m();
|
|
#else
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
RestoreMemSize_cx();
|
|
else
|
|
SetTextMode_m();
|
|
#endif
|
|
|
|
return FALSE;
|
|
|
|
} /* end ATIMPResetHw() */
|
|
|
|
#if (TARGET_BUILD >= 500)
|
|
|
|
#define QUERY_MONITOR_ID 0x22446688
|
|
#define QUERY_NONDDC_MONITOR_ID 0x11223344
|
|
|
|
VP_STATUS
|
|
ATIMPSetPower50(
|
|
PHW_DEVICE_EXTENSION pHwDeviceExtension,
|
|
ULONG HwDeviceId,
|
|
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
|
|
)
|
|
//
|
|
// DESCRIPTION:
|
|
// Set the graphics card to the desired DPMS state.
|
|
//
|
|
// PARAMETERS:
|
|
// pHwDeviceExtension Points to per-adapter device extension.
|
|
// HwDeviceId id identifying the device.
|
|
// pVideoPowerMgmt Points to structure containing desired DPMS state.
|
|
//
|
|
// RETURN VALUE:
|
|
// Status code.
|
|
//
|
|
{
|
|
ULONG ulDesiredState;
|
|
|
|
ASSERT((pHwDeviceExtension != NULL) && (pVideoPowerMgmt != NULL));
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ati.sys ATIMPSetPower50: *** Entry point ***\n"));
|
|
|
|
ulDesiredState = pVideoPowerMgmt->PowerState;
|
|
|
|
//
|
|
// Check the ID passed down by the caller.
|
|
// We must handle setting the power for each of the devices specifically.
|
|
//
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys ATIMPSetPower50: Device Id = 0x%x\n", HwDeviceId));
|
|
|
|
if ((QUERY_MONITOR_ID == HwDeviceId) ||
|
|
(QUERY_NONDDC_MONITOR_ID == HwDeviceId))
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys ATIMPSetPower50: Device Id = Monitor\n"));
|
|
|
|
if (pVideoPowerMgmt->PowerState == VideoPowerHibernate) {
|
|
|
|
// We just leave the monitor powered on for Hibernate.
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// This is the monitor -- we will use the standard BIOS DPMS call.
|
|
//
|
|
return SetMonitorPowerState(pHwDeviceExtension, ulDesiredState);
|
|
}
|
|
else if (DISPLAY_ADAPTER_HW_ID == HwDeviceId)
|
|
{
|
|
VP_STATUS status;
|
|
struct query_structure *QueryPtr =
|
|
(struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys ATIMPSetPower50: Device Id = Graphics Adapter\n"));
|
|
|
|
switch (pVideoPowerMgmt->PowerState) {
|
|
|
|
case VideoPowerOn:
|
|
case VideoPowerHibernate:
|
|
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case VideoPowerStandBy:
|
|
case VideoPowerSuspend:
|
|
case VideoPowerOff:
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// We indicated in ATIGetPowerState that we couldn't
|
|
// do VideoPowerOff. So we should not get a call to
|
|
// do it here.
|
|
//
|
|
|
|
ASSERT(FALSE);
|
|
status = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "ati.sys ATIMPSetPower50: Unknown pHwDeviceId\n"));
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
} // ATIMPSetPower50()
|
|
|
|
VP_STATUS
|
|
ATIMPGetPower50(
|
|
PHW_DEVICE_EXTENSION pHwDeviceExtension,
|
|
ULONG HwDeviceId,
|
|
PVIDEO_POWER_MANAGEMENT pVideoPowerMgmt
|
|
)
|
|
//
|
|
// DESCRIPTION:
|
|
// Returns whether or not this particular DPMS state can be set on the
|
|
// graphics card or monitor
|
|
//
|
|
// PARAMETERS:
|
|
// pHwDeviceExtension Points to per-adapter device extension.
|
|
// HwDeviceId id identifying the device.
|
|
// pVideoPowerMgmt Points to DPMS state we wish to know is supported or not.
|
|
//
|
|
// RETURN VALUE:
|
|
// Status code.
|
|
//
|
|
{
|
|
ASSERT((pHwDeviceExtension != NULL) && (pVideoPowerMgmt != NULL));
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ati.sys ATIMPGetPower50: *** Entry point ***\n"));
|
|
|
|
//
|
|
// We currently only support settings the power on the monitor.
|
|
// Check that we get the private ID we passed back the system.
|
|
//
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys ATIMPGetPower50: Device Id = 0x%x\n", HwDeviceId));
|
|
|
|
if ((QUERY_MONITOR_ID == HwDeviceId) ||
|
|
(QUERY_NONDDC_MONITOR_ID == HwDeviceId))
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys ATIMPGetPower50: Device Id = Monitor, State = D%ld\n",
|
|
pVideoPowerMgmt->PowerState - 1));
|
|
|
|
switch (pVideoPowerMgmt->PowerState)
|
|
{
|
|
case VideoPowerOn:
|
|
case VideoPowerHibernate:
|
|
|
|
return NO_ERROR;
|
|
|
|
case VideoPowerStandBy:
|
|
case VideoPowerSuspend:
|
|
case VideoPowerOff:
|
|
|
|
return ERROR_INVALID_FUNCTION;
|
|
|
|
default:
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
}
|
|
else if (DISPLAY_ADAPTER_HW_ID == HwDeviceId)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys ATIMPGetPower50: Device Id = Graphics Adapter, State = D%ld\n",
|
|
pVideoPowerMgmt->PowerState - 1));
|
|
|
|
switch (pVideoPowerMgmt->PowerState) {
|
|
|
|
case VideoPowerOn:
|
|
case VideoPowerHibernate:
|
|
|
|
return NO_ERROR;
|
|
|
|
case VideoPowerStandBy:
|
|
case VideoPowerSuspend:
|
|
case VideoPowerOff:
|
|
|
|
//
|
|
// Indicate that we can't do VideoPowerOff, because
|
|
// we have no way of coming back when power is re-applied
|
|
// to the card.
|
|
//
|
|
|
|
return ERROR_INVALID_FUNCTION;
|
|
|
|
default:
|
|
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_FUNCTION;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "ati.sys ATIMPGetPower50: Unknown HwDeviceId\n"));
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
} // ATIMPGetPower50()
|
|
|
|
ULONG
|
|
ATIMPGetVideoChildDescriptor(
|
|
PVOID pHwDeviceExtension,
|
|
PVIDEO_CHILD_ENUM_INFO ChildEnumInfo,
|
|
PVIDEO_CHILD_TYPE pChildType,
|
|
PVOID pvChildDescriptor,
|
|
PULONG pHwId,
|
|
PULONG pUnused
|
|
)
|
|
//
|
|
// DESCRIPTION:
|
|
// Enumerate all devices controlled by the ATI graphics chip.
|
|
// This includes DDC monitors attached to the board, as well as other devices
|
|
// which may be connected to a proprietary bus.
|
|
//
|
|
// PARAMETERS:
|
|
// HwDeviceExtension Pointer to our hardware device extension structure.
|
|
// ChildEnumInfo Information about the device that should be enumerated.
|
|
// pvChildDescriptor Identification structure of the device (EDID, string).
|
|
// pHwId Private unique 32 bit ID to passed back to the miniport.
|
|
// pUnused Do not use.
|
|
//
|
|
// RETURN VALUE:
|
|
// ERROR_NO_MORE_DEVICES if no more child devices exist.
|
|
// ERROR_INVALID_NAME if the device could not be enumerated, but more devices
|
|
// exist.
|
|
// ERROR_MORE_DATA to be called again
|
|
//
|
|
// NOTE:
|
|
// In the event of a failure return, none of the fields are valid except for
|
|
// the return value and the pbMoreChildren field.
|
|
//
|
|
{
|
|
//
|
|
//
|
|
ULONG Status;
|
|
|
|
ASSERT(NULL != pHwDeviceExtension);
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI.SYS!AtiGetVideoChildDescriptor: *** Entry point ***\n"));
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI.SYS!AtiGetVideoChildDescriptor: pHwDeviceExtension = 0x%08X\n",
|
|
pHwDeviceExtension));
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI.SYS!AtiGetVideoChildDescriptor: ChildIndex = %ld\n", ChildEnumInfo->ChildIndex));
|
|
|
|
|
|
switch (ChildEnumInfo->ChildIndex) {
|
|
case 0:
|
|
|
|
//
|
|
// Case 0 is used to enumerate devices found by the ACPI firmware.
|
|
//
|
|
// Since we do not support ACPI devices yet, we must return failure.
|
|
//
|
|
|
|
Status = ERROR_NO_MORE_DEVICES;
|
|
break;
|
|
|
|
case 1:
|
|
|
|
//
|
|
// This is the last device we enumerate. Tell the system we don't
|
|
// have any more.
|
|
//
|
|
|
|
*pChildType = Monitor;
|
|
|
|
//
|
|
// Obtain the EDID structure via DDC.
|
|
//
|
|
|
|
if (DDC2Query50(pHwDeviceExtension,
|
|
pvChildDescriptor,
|
|
ChildEnumInfo->ChildDescriptorSize) == TRUE)
|
|
{
|
|
ASSERT(pChildType != NULL && pHwId != NULL);
|
|
|
|
*pHwId = QUERY_MONITOR_ID;
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ati.sys ATIMPGetVideoChildDescriptor: Successfully read EDID structure\n"));
|
|
|
|
} else {
|
|
|
|
//
|
|
// Alway return TRUE, since we always have a monitor output
|
|
// on the card and it just may not be a detectable device.
|
|
//
|
|
ASSERT(pChildType != NULL && pHwId != NULL);
|
|
|
|
*pHwId = QUERY_NONDDC_MONITOR_ID;
|
|
|
|
VideoDebugPrint((DEBUG_NORMAL, "ati.sys ATIMPGetVideoChildDescriptor: DDC not supported\n"));
|
|
|
|
}
|
|
|
|
Status = ERROR_MORE_DATA;
|
|
break;
|
|
|
|
case DISPLAY_ADAPTER_HW_ID:
|
|
{
|
|
|
|
PUSHORT pPnpDeviceDescription = NULL;
|
|
ULONG stringSize = sizeof(L"*PNPXXXX");
|
|
|
|
struct query_structure * QueryPtr =
|
|
(struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
|
|
//
|
|
// Special ID to handle return legacy PnP IDs for root enumerated
|
|
// devices.
|
|
//
|
|
|
|
*pChildType = VideoChip;
|
|
*pHwId = DISPLAY_ADAPTER_HW_ID;
|
|
|
|
|
|
//
|
|
// Figure out which card type and set pPnpDeviceDescription at
|
|
// associated string.
|
|
//
|
|
|
|
// "ATI Graphics Ultra Pro (mach32)"
|
|
pPnpDeviceDescription = L"*PNP090A";
|
|
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
// "ATI Graphics Pro Turbo (mach64)"
|
|
pPnpDeviceDescription = L"*PNP0916";
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == MACH32_ULTRA)
|
|
{
|
|
if (QueryPtr->q_system_bus_type == Eisa)
|
|
{
|
|
// "ATI Graphics Ultra Pro EISA (mach32)"
|
|
pPnpDeviceDescription = L"*ATI4402";
|
|
}
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == GRAPHICS_ULTRA)
|
|
{
|
|
// "ATI Graphics Ultra (mach8)"
|
|
pPnpDeviceDescription = L"*PNP090B";
|
|
|
|
}
|
|
else if (phwDeviceExtension->ModelNumber == WONDER)
|
|
{
|
|
// "ATI VGA Wonder"
|
|
pPnpDeviceDescription = L"*PNP090D";
|
|
}
|
|
|
|
//
|
|
// Now just copy the string into memory provided.
|
|
//
|
|
|
|
memcpy(pvChildDescriptor, pPnpDeviceDescription, stringSize);
|
|
|
|
Status = ERROR_MORE_DATA;
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
default:
|
|
|
|
Status = ERROR_NO_MORE_DEVICES;
|
|
break;
|
|
}
|
|
|
|
if (ERROR_MORE_DATA == Status)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI.SYS!AtiGetVideoChildDescriptor: ChildType = %ld\n", *pChildType));
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI.SYS!AtiGetVideoChildDescriptor: pvHdId = 0x%x\n", *pHwId));
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI.SYS!AtiGetVideoChildDescriptor: *** Exit TRUE ***\n"));
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "ATI.SYS!AtiGetVideoChildDescriptor: *** Exit FALSE ***\n"));
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // AtiGetVideoChildDescriptor()
|
|
|
|
#endif // TARGET_BUILD >= 500
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
/*
|
|
* VP_STATUS RegistryParameterCallback(phwDeviceExtension, Context, Name, Data, Length);
|
|
*
|
|
* PHW_DEVICE_EXTENSION phwDeviceExtension; Miniport device extension
|
|
* PVOID Context; Context parameter passed to the callback routine
|
|
* PWSTR Name; Pointer to the name of the requested field
|
|
* PVOID Data; Pointer to a buffer containing the information
|
|
* ULONG Length; Length of the data
|
|
*
|
|
* Routine to process the information coming back from the registry.
|
|
*
|
|
* Return value:
|
|
* NO_ERROR if successful
|
|
* ERROR_INSUFFICIENT_BUFFER if too much data to store
|
|
*/
|
|
VP_STATUS RegistryParameterCallback(PHW_DEVICE_EXTENSION phwDeviceExtension,
|
|
PVOID Context,
|
|
PWSTR Name,
|
|
PVOID Data,
|
|
ULONG Length)
|
|
{
|
|
if (Length > REGISTRY_BUFFER_SIZE)
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
/*
|
|
* Copy the data to our local buffer so other routines
|
|
* can use it.
|
|
*/
|
|
memcpy(RegistryBuffer, Data, Length);
|
|
RegistryBufferLength = Length;
|
|
return NO_ERROR;
|
|
|
|
} /* RegistryParameterCallback() */
|
|
|
|
BOOLEAN
|
|
SetDisplayPowerState(
|
|
PHW_DEVICE_EXTENSION phwDeviceExtension,
|
|
VIDEO_POWER_STATE VideoPowerState
|
|
)
|
|
//
|
|
// DESCRIPTION:
|
|
// Set the graphics card to the desired DPMS state under NT 3.51 and NT 4.0.
|
|
//
|
|
// PARAMETERS:
|
|
// phwDeviceExtension Pointer to our hardware device extension structure.
|
|
// VideoPowerState Desired DPMS state.
|
|
//
|
|
// RETURN VALUE:
|
|
// TRUE if successful.
|
|
// FALSE if unsuccessful.
|
|
//
|
|
{
|
|
ASSERT(phwDeviceExtension != NULL);
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys SetDisplayPowerState: Setting power state to %lu\n", VideoPowerState));
|
|
|
|
//
|
|
// Different card families need different routines to set the power management state.
|
|
//
|
|
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
{
|
|
VIDEO_X86_BIOS_ARGUMENTS Registers;
|
|
|
|
//
|
|
// Invoke the BIOS call to set the desired DPMS state. The BIOS call
|
|
// enumeration of DPMS states is in the same order as that in
|
|
// VIDEO_POWER_STATE, but it is zero-based instead of one-based.
|
|
//
|
|
VideoPortZeroMemory(&Registers, sizeof(VIDEO_X86_BIOS_ARGUMENTS));
|
|
Registers.Eax = BIOS_SET_DPMS;
|
|
Registers.Ecx = VideoPowerState - 1;
|
|
VideoPortInt10(phwDeviceExtension, &Registers);
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_ERROR, "ati.sys SetDisplayPowerState: Invalid adapter type\n"));
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
} // SetDisplayPowerState()
|
|
|
|
VIDEO_POWER_STATE
|
|
GetDisplayPowerState(
|
|
PHW_DEVICE_EXTENSION phwDeviceExtension
|
|
)
|
|
//
|
|
// DESCRIPTION:
|
|
// Retrieve the current DPMS state from the graphics card.
|
|
//
|
|
// PARAMETERS:
|
|
// phwDeviceExtension Pointer to our hardware device extension structure.
|
|
//
|
|
// RETURN VALUE:
|
|
// Current power management state.
|
|
//
|
|
// NOTE:
|
|
// The enumerations VIDEO_DEVICE_POWER_MANAGEMENT (used by GetDisplayPowerState()) and VIDEO_POWER_MANAGEMENT
|
|
// (used by this IOCTL) have opposite orderings (VIDEO_POWER_MANAGEMENT values increase as power consumption
|
|
// decreases, while VIDEO_DEVICE_POWER_MANAGEMENT values increase as power consumption increases, and has
|
|
// a reserved value for "state unknown"), so we can't simply add a constant to translate between them.
|
|
//
|
|
{
|
|
VIDEO_POWER_STATE CurrentState = VideoPowerUnspecified; // Current DPMS state
|
|
|
|
ASSERT(phwDeviceExtension != NULL);
|
|
|
|
//
|
|
// Different card families need different routines to retrieve the power management state.
|
|
//
|
|
if (phwDeviceExtension->ModelNumber == MACH64_ULTRA)
|
|
CurrentState = GetPowerManagement_cx(phwDeviceExtension);
|
|
|
|
//
|
|
// VIDEO_POWER_STATE has 5 possible states and a
|
|
// reserved value to report that we can't read the state.
|
|
// Our cards support 3 levels of monitor power-down in
|
|
// addition to normal operation. Since the number of
|
|
// values which can be reported exceeds the number
|
|
// of states our cards can be in, we will never report
|
|
// one of the possible states (VPPowerDeviceD3).
|
|
//
|
|
switch (CurrentState)
|
|
{
|
|
case VideoPowerUnspecified:
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys GetDisplayPowerState: unknown videocard\n"));
|
|
break;
|
|
|
|
case VideoPowerOn:
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys GetDisplayPowerState: Currently set to DPMS ON\n"));
|
|
break;
|
|
|
|
case VideoPowerStandBy:
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys GetDisplayPowerState: Currently set to DPMS STAND-BY\n"));
|
|
break;
|
|
|
|
case VideoPowerSuspend:
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys GetDisplayPowerState: Currently set to DPMS SUSPEND\n"));
|
|
break;
|
|
|
|
case VideoPowerOff:
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "ati.sys GetDisplayPowerState: Currently set to DPMS OFF\n"));
|
|
break;
|
|
|
|
default:
|
|
|
|
VideoDebugPrint((DEBUG_ERROR, "ati.sys GetDisplayPowerState: Currently set to invalid DPMS state\n"));
|
|
break;
|
|
}
|
|
|
|
return CurrentState;
|
|
} // GetDisplayPowerState()
|
|
|
|
|
|
|
|
// *********************** End of ATIMP.C ****************************
|