541 lines
18 KiB
C
541 lines
18 KiB
C
/************************************************************************/
|
|
/* */
|
|
/* DETECT_M.C */
|
|
/* */
|
|
/* Aug 25 1993 (c) 1993, ATI Technologies Incorporated. */
|
|
/************************************************************************/
|
|
|
|
/********************** PolyTron RCS Utilities
|
|
|
|
$Revision: 1.9 $
|
|
$Date: 31 Mar 1995 11:55:44 $
|
|
$Author: RWOLFF $
|
|
$Log: S:/source/wnt/ms11/miniport/vcs/detect_m.c $
|
|
*
|
|
* Rev 1.9 31 Mar 1995 11:55:44 RWOLFF
|
|
* Changed from all-or-nothing debug print statements to thresholds
|
|
* depending on importance of the message.
|
|
*
|
|
* Rev 1.8 11 Jan 1995 13:58:46 RWOLFF
|
|
* Fixed bug introduced in rev. 1.4 - COM4: was detected as being a Mach8
|
|
* or Mach32 card, which would leave the triple-boot with no valid video
|
|
* driver.
|
|
*
|
|
* Rev 1.7 04 Jan 1995 12:02:06 RWOLFF
|
|
* Get_BIOS_Seg() moved to SERVICES.C as part of fix for non-ATI cards
|
|
* being detected as Mach64.
|
|
*
|
|
* Rev 1.6 23 Dec 1994 10:48:10 ASHANMUG
|
|
* ALPHA/Chrontel-DAC
|
|
*
|
|
* Rev 1.5 19 Aug 1994 17:10:56 RWOLFF
|
|
* Added support for Graphics Wonder, fixed search for BIOS signature,
|
|
* removed dead code.
|
|
*
|
|
* Rev 1.4 22 Jul 1994 17:46:56 RWOLFF
|
|
* Merged with Richard's non-x86 code stream.
|
|
*
|
|
* Rev 1.3 20 Jul 1994 13:03:44 RWOLFF
|
|
* Fixed debug print statment.
|
|
*
|
|
* Rev 1.2 31 Mar 1994 15:06:42 RWOLFF
|
|
* Added debugging code.
|
|
*
|
|
* Rev 1.1 07 Feb 1994 14:06:42 RWOLFF
|
|
* Added alloc_text() pragmas to allow miniport to be swapped out when
|
|
* not needed.
|
|
*
|
|
* Rev 1.0 31 Jan 1994 11:05:48 RWOLFF
|
|
* Initial revision.
|
|
*
|
|
* Rev 1.3 05 Nov 1993 13:23:36 RWOLFF
|
|
* Fixed BIOS segment detection (used to always get C000).
|
|
*
|
|
* Rev 1.2 08 Oct 1993 11:09:26 RWOLFF
|
|
* Added "_m" to function names to identify them as being specific to the
|
|
* 8514/A-compatible family of ATI accelerators.
|
|
*
|
|
* Rev 1.1 24 Sep 1993 11:41:58 RWOLFF
|
|
* Removed mapping of identification-only registers for all card families,
|
|
* added additional 8514/A-compatible information gathering formerly done
|
|
* in ATIMP.C.
|
|
*
|
|
* Rev 1.0 03 Sep 1993 14:22:48 RWOLFF
|
|
* Initial revision.
|
|
|
|
End of PolyTron RCS section *****************/
|
|
|
|
#ifdef DOC
|
|
DETECT_M.C - Identify which (if any) ATI card is present in the system.
|
|
|
|
DESCRIPTION
|
|
This file contains routines which check for the presence of various
|
|
ATI graphics accelerators.
|
|
|
|
NOTE: This module only has access to those I/O registers needed
|
|
to uniquely identify which ATI card is present.
|
|
|
|
OTHER FILES
|
|
|
|
#endif
|
|
|
|
#include "dderror.h"
|
|
|
|
#include "miniport.h"
|
|
#include "video.h"
|
|
#include "ntddvdeo.h"
|
|
|
|
#include "stdtyp.h"
|
|
#include "amach.h"
|
|
#include "amach1.h"
|
|
#include "atimp.h"
|
|
|
|
#define INCLUDE_DETECT_M
|
|
#include "detect_m.h"
|
|
#include "eeprom.h"
|
|
#include "modes_m.h"
|
|
#include "services.h"
|
|
#include "setup_m.h"
|
|
|
|
|
|
/*
|
|
* Allow miniport to be swapped out when not needed.
|
|
*/
|
|
#if defined (ALLOC_PRAGMA)
|
|
#pragma alloc_text(PAGE_M, WhichATIAccelerator_m)
|
|
#pragma alloc_text(PAGE_M, GetExtraData_m)
|
|
#pragma alloc_text(PAGE_M, ATIFindExtFcn_m)
|
|
#pragma alloc_text(PAGE_M, ATIFindEEPROM_m)
|
|
#pragma alloc_text(PAGE_M, ATIGetSpecialHandling_m)
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Static variables used by this module.
|
|
*/
|
|
static BYTE far *p; // Used to address ROM directly
|
|
static BYTE GraphicsWonderSignature[] = "GRAPHICS WONDER";
|
|
|
|
|
|
/*
|
|
* int WhichATIAccelerator_m(void);
|
|
*
|
|
* Determine which (if any) ATI 8514/A-compatible
|
|
* accelerator is present.
|
|
*
|
|
* Returns: Accelerator type
|
|
* _8514_ULTRA - 8514/Ultra
|
|
* GRAPHICS_ULTRA - Graphics ULTRA/Graphics VANTAGE
|
|
* MACH32_ULTRA - 68800 detected
|
|
* NO_ATI_ACCEL - no ATI 8514/A-compatible accelerator
|
|
*/
|
|
int WhichATIAccelerator_m(void)
|
|
{
|
|
int status;
|
|
WORD Scratch; /* Temporary variable */
|
|
|
|
/*
|
|
* All current ATI accelerators are 8514/A compatible. Check
|
|
* for 8514/A, and if not present assume that no ATI accelerator
|
|
* is present.
|
|
*/
|
|
|
|
/*
|
|
* Ensure that the DAC gets clocks (not guaranteed in ISA machines
|
|
* in VGA passthrough mode because the cable might not be connected).
|
|
*/
|
|
Passth8514_m(SHOW_ACCEL);
|
|
|
|
/*
|
|
* Cut the pixel clock down to low speed. The value given will yield
|
|
* 25 MHz on most of the clock chips we are dealing with.
|
|
*/
|
|
Scratch=(INPW(CLOCK_SEL) & 0xff00) | 0x51;
|
|
OUTPW(CLOCK_SEL,Scratch);
|
|
|
|
/************************************************************************
|
|
* DAC index read/write test
|
|
* This test writes to the read index and reads it back
|
|
* (it should be incremented by one). This tests for the
|
|
* presence of a standard DAC in an 8514/A adapter. This
|
|
* test is sufficient to ensure the presence of an 8514/A
|
|
* type adapter.
|
|
************************************************************************/
|
|
|
|
OUTP(DAC_R_INDEX,0xa4);
|
|
short_delay(); /* This delay must be greater than */
|
|
/* than the minimum delay required */
|
|
/* by the DAC (see the DAC spec) */
|
|
if (INP(DAC_W_INDEX) == 0xa5)
|
|
{
|
|
/*
|
|
* Reading back A5 from DAC_W_INDEX always means an 8514-compatible
|
|
* card is present, but not all 8514-compatible cards will
|
|
* produce this value.
|
|
*/
|
|
status=TRUE;
|
|
VideoDebugPrint((DEBUG_DETAIL, "First test - this is an 8514/A\n"));
|
|
}
|
|
else{
|
|
/*
|
|
* Secondary test for 8514/compatible card. Reset the draw engine,
|
|
* then write an alternating bit pattern to the ERR_TERM register.
|
|
*/
|
|
OUTPW(SUBSYS_CNTL, 0x900F);
|
|
OUTPW(SUBSYS_CNTL, 0x400F);
|
|
OUTPW(ERR_TERM, 0x5555);
|
|
WaitForIdle_m();
|
|
/*
|
|
* If we don't read back the value we wrote, then there is
|
|
* no 8514-compatible card in the system. If we do read back
|
|
* what we wrote, we must repeat the test with the opposite
|
|
* bit pattern.
|
|
*/
|
|
if (INPW(ERR_TERM) != 0x5555)
|
|
{
|
|
status=FALSE;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Second test - 0x5555 not found, no 8514/A\n"));
|
|
}
|
|
else{
|
|
OUTPW(ERR_TERM, 0x0AAAA);
|
|
WaitForIdle_m();
|
|
if (INPW(ERR_TERM) != 0x0AAAA)
|
|
{
|
|
status=FALSE;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Second test - 0xAAAA not found, no 8514/A\n"));
|
|
}
|
|
else
|
|
{
|
|
status=TRUE;
|
|
VideoDebugPrint((DEBUG_DETAIL, "Second test - this is an 8514/A\n"));
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Turn on passthrough so display is driven by VGA.
|
|
*/
|
|
Passth8514_m(SHOW_VGA);
|
|
|
|
if (status == FALSE)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "No 8514/A-compatible card found\n"));
|
|
return NO_ATI_ACCEL;
|
|
}
|
|
|
|
|
|
/*
|
|
* We now know that the video card is 8514/A compatible. Now check
|
|
* to see if it has the ATI extensions.
|
|
*/
|
|
Scratch = INPW (ROM_ADDR_1); // save original value
|
|
OUTPW (ROM_ADDR_1,0x5555); // bits 7 and 15 must be zero
|
|
|
|
WaitForIdle_m();
|
|
|
|
status = INPW(ROM_ADDR_1) == 0x5555 ? TRUE : FALSE;
|
|
|
|
OUTPW (ROM_ADDR_1, Scratch);
|
|
if (status == FALSE)
|
|
{
|
|
VideoDebugPrint((DEBUG_DETAIL, "8514/A-compatible card found, but it doesn't have ATI extensions\n"));
|
|
return NO_ATI_ACCEL;
|
|
}
|
|
|
|
|
|
/*
|
|
* We know that an ATI accelerator is present. Determine which one.
|
|
*/
|
|
|
|
VideoDebugPrint((DEBUG_DETAIL, "8514/A-compatible card found with ATI extensions\n"));
|
|
#if !defined (i386) && !defined (_i386_)
|
|
/*
|
|
* Alpha Jensen under test falsely reports Mach 32 as Mach 8
|
|
*/
|
|
Scratch = 0x02aa;
|
|
#else
|
|
// This is not a R/W register in the Mach 8 but it is in the Mach 32
|
|
OUTPW (SRC_X,0xaaaa); // fill with a dummy value
|
|
WaitForIdle_m();
|
|
Scratch = INPW(R_SRC_X);
|
|
#endif
|
|
if (Scratch == 0x02aa)
|
|
{
|
|
status = MACH32_ULTRA;
|
|
if (INPW(CONFIG_STATUS_1) & 1) //is 8514 or VGA enabled decides eeprom
|
|
{
|
|
Mach32DescribeEEPROM(STYLE_8514);
|
|
}
|
|
else
|
|
{
|
|
Mach32DescribeEEPROM(STYLE_VGA);
|
|
}
|
|
}
|
|
|
|
else{
|
|
/*
|
|
* Mach 8 card found, determine which one.
|
|
*
|
|
* Only the 8514/ULTRA shares its clock with the VGA.
|
|
* We can't check for the IBM 8514 ROM pages to be
|
|
* enabled, because if we did an 8514/ULTRA with the
|
|
* jumper set to disable the EEPROM would be falsely
|
|
* recognized as a Graphics ULTRA.
|
|
*
|
|
* Even if this jumper is set to "disabled", we can
|
|
* still read from the EEPROM.
|
|
*/
|
|
if (INPW(CONFIG_STATUS_2) & SHARE_CLOCK)
|
|
{
|
|
status = _8514_ULTRA;
|
|
/*
|
|
* Only the 8514/Ultra has a hardware bug that prevents it
|
|
* from writing to the EEPROM when it is in an 8 bit ISA bus.
|
|
*/
|
|
if ( ((INPW(CONFIG_STATUS_1) & MC_BUS) == 0) // ISA bus only
|
|
&& ((INPW(CONFIG_STATUS_1) & BUS_16) == 0)) // 8 bit BUS
|
|
{
|
|
Mach8UltraDescribeEEPROM(BUS_8BIT);
|
|
}
|
|
else
|
|
{
|
|
Mach8UltraDescribeEEPROM(BUS_16BIT);
|
|
}
|
|
}
|
|
else{
|
|
/*
|
|
* Graphics ULTRA or Graphics VANTAGE found. For our purposes,
|
|
* they are identical.
|
|
*/
|
|
status = GRAPHICS_ULTRA;
|
|
Mach8ComboDescribeEEPROM();
|
|
}
|
|
}
|
|
|
|
phwDeviceExtension->ee = ⅇ
|
|
|
|
return (status);
|
|
|
|
} /* WhichATIAccelerator_m() */
|
|
|
|
|
|
|
|
/*
|
|
* void GetExtraData_m(void);
|
|
*
|
|
* Collect additional data (register locations and revision-specific
|
|
* card capabilities) for the 8514/A-compatible family of ATI accelerators.
|
|
*/
|
|
void GetExtraData_m(void)
|
|
{
|
|
struct query_structure *QueryPtr; /* Query information for the card */
|
|
|
|
|
|
QueryPtr = (struct query_structure *) (phwDeviceExtension->CardInfo);
|
|
ati_reg = reg1CE; // ATI VGA extended register
|
|
vga_chip = VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[VGA_CHIP_OFFSET])); /* VGA chip revision as ASCII */
|
|
|
|
// Find out whether extended BIOS functions and the EEPROM are available.
|
|
QueryPtr->q_ext_bios_fcn = ATIFindExtFcn_m(QueryPtr);
|
|
QueryPtr->q_eeprom = ATIFindEEPROM_m(QueryPtr);
|
|
|
|
ATIGetSpecialHandling_m(QueryPtr); // special card distinctions
|
|
return;
|
|
} /* GetExtraData_m() */
|
|
|
|
|
|
|
|
/*
|
|
* BOOL ATIFindExtFcn_m(QueryPtr)
|
|
*
|
|
* struct query_structure *QueryPtr; Pointer to query structure
|
|
*
|
|
* Routine to see if extended BIOS functions for setting the accelerator
|
|
* mode are present in the BIOS of an ATI accelerator card. Assumes that
|
|
* an ATI accleratore with a ROM BIOS is present, results are undefined
|
|
* if this assumption is invalid.
|
|
*/
|
|
BOOL ATIFindExtFcn_m(struct query_structure *QueryPtr)
|
|
{
|
|
|
|
/*
|
|
* TEMPORARY WORKAROUND: Windows NT does not yet provide a hook
|
|
* to make an absolute far call to real mode code. To avoid
|
|
* branching into code which depends on this service being available,
|
|
* report that no extended BIOS functions are available.
|
|
*
|
|
* Once this hook becomes available so that we can use
|
|
* extended BIOS functions, we can check the BIOS to see
|
|
* if it contains entry points. On Mach 8 and Mach 32
|
|
* accelerators with extended BIOS functions, there will
|
|
* be an unconditional jump located at the entry point
|
|
* for each extended function.
|
|
*/
|
|
return FALSE;
|
|
|
|
} /* ATIFindExtFcn_m() */
|
|
|
|
|
|
|
|
/*
|
|
* BOOL ATIFindEEPROM_m(QueryPtr);
|
|
*
|
|
* struct query_structure *QueryPtr; Pointer to query structure
|
|
*
|
|
* Routine to see if an EEPROM is present on an ATI accelerator card.
|
|
* Assumes that an ATI accelerator is present and the model is known,
|
|
* results are undefined if this assumption is invalid.
|
|
*
|
|
* Returns:
|
|
* TRUE if an EEPROM is present on the card
|
|
* FALSE if no EEPROM is present
|
|
*/
|
|
BOOL ATIFindEEPROM_m(struct query_structure *QueryPtr)
|
|
{
|
|
WORD ValueRead; /* Value read from the EEPROM */
|
|
|
|
|
|
/*
|
|
* The EEPROM read will return all bits the same if no EEPROM
|
|
* is present. If an EEPROM is present, word 2 will have at least
|
|
* one bit set and at least one bit cleared regardless of
|
|
* accelerator type (8514/ULTRA, Graphics Ultra, or Mach 32).
|
|
*/
|
|
ValueRead = (ee.EEread) (2);
|
|
VideoDebugPrint((DEBUG_NORMAL, "Value read from second EEPROM word is 0x%X\n", ValueRead));
|
|
if ((ValueRead == 0x0FFFF) || !ValueRead)
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "Will check for OEM accelerator\n"));
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
VideoDebugPrint((DEBUG_NORMAL, "Won't check for OEM accelerator\n"));
|
|
return TRUE;
|
|
}
|
|
|
|
} /* ATIFindEEPROM_m() */
|
|
|
|
|
|
/*
|
|
* void ATIGetSpecialHandling_m(QueryPtr);
|
|
*
|
|
* struct query_structure *QueryPtr; Pointer to query structure
|
|
*
|
|
* Finds out from ROM BIOS whether or not 1280x1024 is available on
|
|
* a Mach 8 card, and whether or not all bits of memory aperture
|
|
* location are found in MEM_CFG register on a Mach 32. Assumes
|
|
* that an ATI accelerator with a ROM BIOS is present, results
|
|
* are undefined if this assumption is invalid.
|
|
*/
|
|
void ATIGetSpecialHandling_m(struct query_structure *QueryPtr)
|
|
{
|
|
USHORT SearchLoop; /* Used in finding beginning of Graphics Wonder ID string */
|
|
USHORT ScanLoop; /* Used in stepping through Graphics Wonder ID string */
|
|
|
|
|
|
/*
|
|
* Check the BIOS revision number. Mach 8 cards with a BIOS
|
|
* revision prior to 1.4 can't do 1280x1024, but use the same
|
|
* mode table for 132 column text mode.
|
|
*
|
|
* Some BIOS revisions (including 1.40 on a Graphics Ultra)
|
|
* only contain the first digit of the minor revision in the
|
|
* BIOS, while others (including 1.35 on an 8514/ULTRA) contain
|
|
* the entire minor revision.
|
|
*
|
|
* The q_ignore1280 field is ignored for Mach 32 cards.
|
|
*/
|
|
if((VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET])) < 1) || // Major revision
|
|
(VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET+1])) < 4) || // Single-digit minor revision
|
|
((VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET+1])) >= 10) && // 2-digit minor revision
|
|
(VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH8_REV_OFFSET+1])) < 40)))
|
|
QueryPtr->q_ignore1280 = TRUE;
|
|
else
|
|
QueryPtr->q_ignore1280 = FALSE;
|
|
|
|
|
|
|
|
/*
|
|
* On the Mach 32, bit 0 of BIOS byte MACH32_EXTRA_OFFSET will
|
|
* be set if bits 7 through 11 of the aperture address are to
|
|
* located in SCRATCH_PAD_0 and clear if all the bits are in
|
|
* MEM_CFG.
|
|
*
|
|
* The q_m32_aper_calc field is ignored for Mach 8 cards.
|
|
*/
|
|
if (VideoPortReadRegisterUchar (&((QueryPtr->q_bios)[MACH32_EXTRA_OFFSET])) & 0x0001)
|
|
QueryPtr->q_m32_aper_calc = TRUE;
|
|
else
|
|
QueryPtr->q_m32_aper_calc = FALSE;
|
|
|
|
/*
|
|
* The Graphics Wonder (low-cost version of the Mach 32) is
|
|
* available with either the BT48x or the TI34075 DAC.
|
|
*
|
|
* These cards may be built with ASICs which passed tests on
|
|
* modes supported by the BT48x DAC but failed tests on modes
|
|
* only supported by the TI34075. Such a card may appear to work
|
|
* in TI-only modes, but experience problems (not necessarily
|
|
* reproducable on other Graphics Wonder cards, even from the
|
|
* same production run) ranging from drawing bugs to hardware
|
|
* damage. For this reason, Graphics Wonder cards MUST NOT be
|
|
* run in modes not supported by the BT48x DAC.
|
|
*
|
|
* Initially assume that we do not have a Graphics Wonder. If
|
|
* we find the beginning of the ID string, we can change our
|
|
* assumption.
|
|
*/
|
|
QueryPtr->q_GraphicsWonder = FALSE;
|
|
for (SearchLoop = GW_AREA_START; SearchLoop < GW_AREA_END; SearchLoop++)
|
|
{
|
|
/*
|
|
* Loop until we have found what might be the Graphics Wonder
|
|
* identification string, but might also be a byte which
|
|
* happens to match the first character in the string.
|
|
* If we find a match, initially assume that we have
|
|
* found the start of the string.
|
|
*/
|
|
if (VideoPortReadRegisterUchar(&((QueryPtr->q_bios)[SearchLoop])) != GraphicsWonderSignature[0])
|
|
continue;
|
|
|
|
QueryPtr->q_GraphicsWonder = TRUE;
|
|
/*
|
|
* Check to see whether this is actually the start of the
|
|
* Graphics Wonder identification string. If it isn't,
|
|
* keep looking.
|
|
*/
|
|
for (ScanLoop = 0; GraphicsWonderSignature[ScanLoop] != 0; ScanLoop++)
|
|
{
|
|
if (VideoPortReadRegisterUchar(&((QueryPtr->q_bios)[SearchLoop + ScanLoop]))
|
|
!= GraphicsWonderSignature[ScanLoop])
|
|
{
|
|
QueryPtr->q_GraphicsWonder = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If this is a Graphics Wonder, restrict the maximum pixel
|
|
* depth of the TI34075 DAC to that supported by the BT48x.
|
|
*
|
|
* Once we have found the Graphics Wonder ID string, we don't
|
|
* need to keep looking for it.
|
|
*/
|
|
if (QueryPtr->q_GraphicsWonder == TRUE)
|
|
{
|
|
for (ScanLoop = RES_640; ScanLoop <= RES_1280; ScanLoop++)
|
|
{
|
|
MaxDepth[DAC_TI34075][ScanLoop] = MaxDepth[DAC_BT48x][ScanLoop];
|
|
}
|
|
QueryPtr->q_GraphicsWonder = TRUE;
|
|
break;
|
|
}
|
|
|
|
} /* end search for Graphics Wonder */
|
|
|
|
return;
|
|
|
|
} /* ATIGetSpecialHandling_m() */
|
|
|