2343 lines
75 KiB
C
2343 lines
75 KiB
C
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/atiprobe.c,v 1.62tsi Exp $ */
|
|
/*
|
|
* Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that copyright
|
|
* notice and this permission notice appear in supporting documentation, and
|
|
* that the name of Marc Aurele La France not be used in advertising or
|
|
* publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. Marc Aurele La France makes no representations
|
|
* about the suitability of this software for any purpose. It is provided
|
|
* "as-is" without express or implied warranty.
|
|
*
|
|
* MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
|
* EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "ati.h"
|
|
#include "atiadapter.h"
|
|
#include "atiadjust.h"
|
|
#include "atibus.h"
|
|
#include "atichip.h"
|
|
#include "aticonsole.h"
|
|
#include "atifillin.h"
|
|
#include "atiident.h"
|
|
#include "atimach64io.h"
|
|
#include "atimodule.h"
|
|
#include "atipreinit.h"
|
|
#include "atiprobe.h"
|
|
#include "atiscreen.h"
|
|
#include "ativalid.h"
|
|
#include "ativersion.h"
|
|
#include "atividmem.h"
|
|
#include "atiwonderio.h"
|
|
|
|
#include "radeon_probe.h"
|
|
#include "radeon_version.h"
|
|
#include "r128_probe.h"
|
|
#include "r128_version.h"
|
|
|
|
/*
|
|
* NOTES:
|
|
*
|
|
* - The driver private structures (ATIRec's) are allocated here, rather than
|
|
* in ATIPreInit(). This allows ATIProbe() to pass information to later
|
|
* stages.
|
|
* - A minor point, perhaps, is that XF86Config Chipset names denote functional
|
|
* levels, rather than specific graphics controller chips.
|
|
* - ATIProbe() does not call xf86MatchPciInstances(), because ATIProbe()
|
|
* should be able to match a mix of PCI and non-PCI devices to XF86Config
|
|
* Device sections. Also, PCI configuration space for Mach32's is to be
|
|
* largely ignored.
|
|
*/
|
|
|
|
/* Used as a temporary buffer */
|
|
#define Identifier ((char *)(pATI->MMIOCache))
|
|
|
|
/*
|
|
* An internal structure definition to facilitate the matching of detected
|
|
* adapters to XF86Config Device sections.
|
|
*/
|
|
typedef struct _ATIGDev
|
|
{
|
|
GDevPtr pGDev;
|
|
int iATIPtr;
|
|
CARD8 Chipset;
|
|
} ATIGDev, *ATIGDevPtr;
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
/*
|
|
* Definitions for I/O conflict avoidance.
|
|
*/
|
|
#define LongPort(_Port) GetBits(_Port, PCIGETIO(SPARSE_IO_BASE))
|
|
#define DetectedVGA (1 << 0)
|
|
#define Detected8514A (1 << 1)
|
|
#define DetectedMach64 (1 << 2)
|
|
#define Allowed (1 << 3)
|
|
#define DoProbe (1 << 4)
|
|
typedef struct
|
|
{
|
|
IOADDRESS Base;
|
|
CARD8 Size;
|
|
CARD8 Flag;
|
|
} PortRec, *PortPtr;
|
|
|
|
/*
|
|
* ATIScanPCIBases --
|
|
*
|
|
* This function loops though a device's PCI registered bases and accumulates
|
|
* a list of block I/O bases in use in the system.
|
|
*/
|
|
static void
|
|
ATIScanPCIBases
|
|
(
|
|
PortPtr *PCIPorts,
|
|
int *nPCIPort,
|
|
const CARD32 *pBase,
|
|
const int *pSize,
|
|
const CARD8 ProbeFlag
|
|
)
|
|
{
|
|
IOADDRESS Base;
|
|
int i, j;
|
|
|
|
for (i = 6; --i >= 0; pBase++, pSize++)
|
|
{
|
|
if (*pBase & PCI_MAP_IO)
|
|
{
|
|
Base = *pBase & ~IO_BYTE_SELECT;
|
|
for (j = 0; ; j++)
|
|
{
|
|
if (j >= *nPCIPort)
|
|
{
|
|
(*nPCIPort)++;
|
|
*PCIPorts = (PortPtr)xnfrealloc(*PCIPorts,
|
|
*nPCIPort * SizeOf(PortRec));
|
|
(*PCIPorts)[j].Base = Base;
|
|
(*PCIPorts)[j].Size = (CARD8)*pSize;
|
|
(*PCIPorts)[j].Flag = ProbeFlag;
|
|
break;
|
|
}
|
|
|
|
if (Base == (*PCIPorts)[j].Base)
|
|
break;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
/* Allow for 64-bit addresses */
|
|
if (!PCI_MAP_IS64BITMEM(*pBase))
|
|
continue;
|
|
|
|
i--;
|
|
pBase++;
|
|
pSize++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ATICheckSparseIOBases --
|
|
*
|
|
* This function checks whether a sparse I/O base can safely be probed.
|
|
*/
|
|
static CARD8
|
|
ATICheckSparseIOBases
|
|
(
|
|
pciVideoPtr pVideo,
|
|
CARD8 *ProbeFlags,
|
|
const IOADDRESS IOBase,
|
|
const int Count,
|
|
const Bool Override
|
|
)
|
|
{
|
|
CARD32 FirstPort, LastPort;
|
|
|
|
if (!pVideo || !xf86IsPrimaryPci(pVideo))
|
|
{
|
|
FirstPort = LongPort(IOBase);
|
|
LastPort = LongPort(IOBase + Count - 1);
|
|
|
|
for (; FirstPort <= LastPort; FirstPort++)
|
|
{
|
|
CARD8 ProbeFlag = ProbeFlags[FirstPort];
|
|
|
|
if (ProbeFlag & DoProbe)
|
|
continue;
|
|
|
|
if (!(ProbeFlag & Allowed))
|
|
return ProbeFlag;
|
|
|
|
if (Override)
|
|
continue;
|
|
|
|
/* User might wish to override this decision */
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": Sparse I/O base 0x%04lX not probed.\n", IOBase);
|
|
return Allowed;
|
|
}
|
|
}
|
|
|
|
return DoProbe;
|
|
}
|
|
|
|
#ifndef AVOID_NON_PCI
|
|
|
|
/*
|
|
* ATIClaimSparseIOBases --
|
|
*
|
|
* This function updates the sparse I/O base table with information from the
|
|
* hardware probes.
|
|
*/
|
|
static void
|
|
ATIClaimSparseIOBases
|
|
(
|
|
CARD8 *ProbeFlags,
|
|
const IOADDRESS IOBase,
|
|
const int Count,
|
|
const CARD8 ProbeFlag
|
|
)
|
|
{
|
|
CARD32 FirstPort = LongPort(IOBase),
|
|
LastPort = LongPort(IOBase + Count - 1);
|
|
|
|
for (; FirstPort <= LastPort; FirstPort++)
|
|
ProbeFlags[FirstPort] = ProbeFlag;
|
|
}
|
|
|
|
#endif /* AVOID_NON_PCI */
|
|
|
|
/*
|
|
* ATIVGAProbe --
|
|
*
|
|
* This function looks for an IBM standard VGA, or clone, and sets
|
|
* pATI->VGAAdapter if one is found.
|
|
*/
|
|
static ATIPtr
|
|
ATIVGAProbe
|
|
(
|
|
ATIPtr pVGA
|
|
)
|
|
{
|
|
CARD8 IOValue1, IOValue2, IOValue3;
|
|
|
|
if (!pVGA)
|
|
pVGA = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
|
|
|
|
/*
|
|
* VGA has one more attribute register than EGA. See if it can be read and
|
|
* written. Note that the CRTC registers are not used here, so there's no
|
|
* need to unlock them.
|
|
*/
|
|
ATISetVGAIOBase(pVGA, inb(R_GENMO));
|
|
(void)inb(GENS1(pVGA->CPIO_VGABase));
|
|
IOValue1 = inb(ATTRX);
|
|
(void)inb(GENS1(pVGA->CPIO_VGABase));
|
|
IOValue2 = GetReg(ATTRX, 0x14U | 0x20U);
|
|
outb(ATTRX, IOValue2 ^ 0x0FU);
|
|
IOValue3 = GetReg(ATTRX, 0x14U | 0x20U);
|
|
outb(ATTRX, IOValue2);
|
|
outb(ATTRX, IOValue1);
|
|
(void)inb(GENS1(pVGA->CPIO_VGABase));
|
|
if (IOValue3 == (IOValue2 ^ 0x0FU))
|
|
{
|
|
/* VGA device detected */
|
|
if (pVGA->Chip == ATI_CHIP_NONE)
|
|
pVGA->Chip = ATI_CHIP_VGA;
|
|
if (pVGA->VGAAdapter == ATI_ADAPTER_NONE)
|
|
pVGA->VGAAdapter = ATI_ADAPTER_VGA;
|
|
if (pVGA->Adapter == ATI_ADAPTER_NONE)
|
|
pVGA->Adapter = ATI_ADAPTER_VGA;
|
|
}
|
|
else
|
|
{
|
|
pVGA->VGAAdapter = ATI_ADAPTER_NONE;
|
|
}
|
|
|
|
return pVGA;
|
|
}
|
|
|
|
/*
|
|
* ATIVGAWonderProbe --
|
|
*
|
|
* This function determines if ATI extended VGA registers can be accessed
|
|
* through the I/O port specified by pATI->CPIO_VGAWonder. If not, the
|
|
* function resets pATI->CPIO_VGAWonder to zero.
|
|
*/
|
|
static void
|
|
ATIVGAWonderProbe
|
|
(
|
|
pciVideoPtr pVideo,
|
|
ATIPtr pATI,
|
|
ATIPtr p8514,
|
|
CARD8 *ProbeFlags
|
|
)
|
|
{
|
|
CARD8 IOValue1, IOValue2, IOValue3, IOValue4, IOValue5, IOValue6;
|
|
|
|
switch (ATICheckSparseIOBases(pVideo, ProbeFlags,
|
|
pATI->CPIO_VGAWonder, 2, TRUE))
|
|
{
|
|
case 0:
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": Expected VGA Wonder capability could not be"
|
|
" detected at I/O port 0x%04lX because it would conflict with"
|
|
" a non-video PCI/AGP device.\n", pATI->CPIO_VGAWonder);
|
|
pATI->CPIO_VGAWonder = 0;
|
|
break;
|
|
|
|
case Detected8514A:
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": Expected VGA Wonder capability could not be"
|
|
" detected at I/O port 0x%04lX because it would conflict with"
|
|
" a %s %s.\n", pATI->CPIO_VGAWonder,
|
|
ATIBusNames[p8514->BusType], ATIAdapterNames[p8514->Adapter]);
|
|
pATI->CPIO_VGAWonder = 0;
|
|
break;
|
|
|
|
case DetectedMach64:
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": Expected VGA Wonder capability could not be"
|
|
" detected at I/O port 0x%04lX because it would conflict with"
|
|
" a Mach64.\n", pATI->CPIO_VGAWonder);
|
|
pATI->CPIO_VGAWonder = 0;
|
|
break;
|
|
|
|
case DetectedVGA:
|
|
default: /* Must be DoProbe */
|
|
if (pVideo && !xf86IsPrimaryPci(pVideo) &&
|
|
(pATI->Chip <= ATI_CHIP_88800GXD))
|
|
{
|
|
/* Set up extended VGA register addressing */
|
|
PutReg(GRAX, 0x50U, GetByte(pATI->CPIO_VGAWonder, 0));
|
|
PutReg(GRAX, 0x51U,
|
|
GetByte(pATI->CPIO_VGAWonder, 1) | pATI->VGAOffset);
|
|
}
|
|
/*
|
|
* Register 0xBB is used by the BIOS to keep track of various
|
|
* things (monitor type, etc.). Except for 18800-x's, register
|
|
* 0xBC must be zero and causes the adapter to enter a test mode
|
|
* when written to with a non-zero value.
|
|
*/
|
|
IOValue1 = inb(pATI->CPIO_VGAWonder);
|
|
IOValue2 = ATIGetExtReg(IOValue1);
|
|
IOValue3 = ATIGetExtReg(0xBBU);
|
|
ATIPutExtReg(0xBBU, IOValue3 ^ 0xAAU);
|
|
IOValue4 = ATIGetExtReg(0xBBU);
|
|
ATIPutExtReg(0xBBU, IOValue3 ^ 0x55U);
|
|
IOValue5 = ATIGetExtReg(0xBBU);
|
|
ATIPutExtReg(0xBBU, IOValue3);
|
|
if (pATI->Chip <= ATI_CHIP_18800_1)
|
|
IOValue6 = 0;
|
|
else
|
|
IOValue6 = ATIGetExtReg(0xBCU);
|
|
ATIPutExtReg(IOValue1, IOValue2);
|
|
|
|
if ((IOValue4 == (IOValue3 ^ 0xAAU)) &&
|
|
(IOValue5 == (IOValue3 ^ 0x55U)) &&
|
|
(IOValue6 == 0))
|
|
{
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": VGA Wonder at I/O port 0x%04lX detected.\n",
|
|
pATI->CPIO_VGAWonder);
|
|
}
|
|
else
|
|
{
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": Expected VGA Wonder capability at I/O port"
|
|
" 0x%04lX was not detected.\n", pATI->CPIO_VGAWonder);
|
|
pATI->CPIO_VGAWonder = 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ATI8514Probe --
|
|
*
|
|
* This function looks for an 8514/A compatible and returns an ATIRec if one is
|
|
* found. The function also determines whether or not the detected 8514/A
|
|
* compatible device is actually a Mach8 or Mach32, and sets pATI->Adapter
|
|
* accordingly.
|
|
*/
|
|
static ATIPtr
|
|
ATI8514Probe
|
|
(
|
|
pciVideoPtr pVideo
|
|
)
|
|
{
|
|
ATIPtr pATI = NULL;
|
|
CARD16 IOValue1, IOValue2;
|
|
|
|
/*
|
|
* Save register value to be modified, just in case there is no 8514/A
|
|
* compatible accelerator. Note that, in more ways than one,
|
|
* SUBSYS_STAT == SUBSYS_CNTL.
|
|
*/
|
|
IOValue1 = inw(SUBSYS_STAT);
|
|
IOValue2 = IOValue1 & _8PLANE;
|
|
|
|
/* Reset any 8514/A compatible adapter that might be present */
|
|
outw(SUBSYS_CNTL, IOValue2 | (GPCTRL_RESET | CHPTEST_NORMAL));
|
|
outw(SUBSYS_CNTL, IOValue2 | (GPCTRL_ENAB | CHPTEST_NORMAL |
|
|
RVBLNKFLG | RPICKFLAG | RINVALIDIO | RGPIDLE));
|
|
|
|
/* Probe for an 8514/A compatible */
|
|
IOValue2 = inw(ERR_TERM);
|
|
outw(ERR_TERM, 0x5A5AU);
|
|
ProbeWaitIdleEmpty();
|
|
if (inw(ERR_TERM) == 0x5A5AU)
|
|
{
|
|
outw(ERR_TERM, 0x2525U);
|
|
if (inw(ERR_TERM) == 0x2525U)
|
|
{
|
|
pATI = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
|
|
pATI->Adapter = ATI_ADAPTER_8514A;
|
|
pATI->ChipHasSUBSYS_CNTL = TRUE;
|
|
pATI->PCIInfo = pVideo;
|
|
}
|
|
}
|
|
outw(ERR_TERM, IOValue2);
|
|
|
|
/* Restore register value clobbered by 8514/A reset attempt */
|
|
if (!pATI)
|
|
{
|
|
outw(SUBSYS_CNTL, IOValue1);
|
|
return NULL;
|
|
}
|
|
|
|
/* Ensure any Mach8 or Mach32 is not in 8514/A emulation mode */
|
|
IOValue1 = inw(CLOCK_SEL);
|
|
outw(CLOCK_SEL, IOValue1);
|
|
ProbeWaitIdleEmpty();
|
|
|
|
IOValue1 = IOValue2 = inw(ROM_ADDR_1);
|
|
outw(ROM_ADDR_1, 0x5555U);
|
|
ProbeWaitIdleEmpty();
|
|
if (inw(ROM_ADDR_1) == 0x5555U)
|
|
{
|
|
outw(ROM_ADDR_1, 0x2A2AU);
|
|
ProbeWaitIdleEmpty();
|
|
if (inw(ROM_ADDR_1) == 0x2A2AU)
|
|
pATI->Adapter = ATI_ADAPTER_MACH8;
|
|
}
|
|
outw(ROM_ADDR_1, IOValue1);
|
|
|
|
if (pATI->Adapter == ATI_ADAPTER_MACH8)
|
|
{
|
|
/* A Mach8 or Mach32 has been detected */
|
|
IOValue1 = inw(READ_SRC_X);
|
|
outw(DESTX_DIASTP, 0xAAAAU);
|
|
ProbeWaitIdleEmpty();
|
|
if (inw(READ_SRC_X) == 0x02AAU)
|
|
pATI->Adapter = ATI_ADAPTER_MACH32;
|
|
|
|
outw(DESTX_DIASTP, 0x5555U);
|
|
ProbeWaitIdleEmpty();
|
|
if (inw(READ_SRC_X) == 0x0555U)
|
|
{
|
|
if (pATI->Adapter != ATI_ADAPTER_MACH32)
|
|
pATI->Adapter = ATI_ADAPTER_8514A;
|
|
}
|
|
else
|
|
{
|
|
if (pATI->Adapter != ATI_ADAPTER_MACH8)
|
|
pATI->Adapter = ATI_ADAPTER_8514A;
|
|
}
|
|
outw(DESTX_DIASTP, IOValue1);
|
|
}
|
|
|
|
switch (pATI->Adapter)
|
|
{
|
|
case ATI_ADAPTER_8514A:
|
|
pATI->Coprocessor = ATI_CHIP_8514A;
|
|
IOValue1 = inb(EXT_CONFIG_3);
|
|
outb(EXT_CONFIG_3, IOValue1 & 0x0FU);
|
|
if (!(inb(EXT_CONFIG_3) & 0xF0U))
|
|
{
|
|
outb(EXT_CONFIG_3, IOValue1 | 0xF0U);
|
|
if ((inb(EXT_CONFIG_3) & 0xF0U) == 0xF0U)
|
|
pATI->Coprocessor = ATI_CHIP_CT480;
|
|
}
|
|
outb(EXT_CONFIG_3, IOValue1);
|
|
break;
|
|
|
|
case ATI_ADAPTER_MACH8:
|
|
pATI->Coprocessor = ATI_CHIP_38800_1;
|
|
if (inw(CONFIG_STATUS_1) & MC_BUS)
|
|
pATI->BusType = ATI_BUS_MCA16;
|
|
break;
|
|
|
|
case ATI_ADAPTER_MACH32:
|
|
IOValue1 = inw(CONFIG_STATUS_1);
|
|
pATI->BusType = GetBits(IOValue1, BUS_TYPE);
|
|
pATI->BIOSBase = 0x000C0000U +
|
|
(GetBits(IOValue2, BIOS_BASE_SEGMENT) << 11);
|
|
if (!(IOValue1 & (_8514_ONLY | CHIP_DIS)))
|
|
{
|
|
pATI->VGAAdapter = ATI_ADAPTER_MACH32;
|
|
if ((xf86ReadBIOS(pATI->BIOSBase, 0x10U,
|
|
(pointer)(&pATI->CPIO_VGAWonder),
|
|
SizeOf(pATI->CPIO_VGAWonder)) <
|
|
SizeOf(pATI->CPIO_VGAWonder)) ||
|
|
!(pATI->CPIO_VGAWonder &= SPARSE_IO_PORT))
|
|
pATI->CPIO_VGAWonder = 0x01CEU;
|
|
pATI->VGAOffset = 0x80U;
|
|
}
|
|
|
|
ATIMach32ChipID(pATI);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return pATI;
|
|
}
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
/*
|
|
* ATIMach64Detect --
|
|
*
|
|
* This function determines if a Mach64 is detectable at a particular base
|
|
* address.
|
|
*/
|
|
static Bool
|
|
ATIMach64Detect
|
|
(
|
|
ATIPtr pATI,
|
|
const CARD16 ChipType,
|
|
const ATIChipType Chip
|
|
)
|
|
{
|
|
CARD32 IOValue, bus_cntl, gen_test_cntl;
|
|
|
|
(void)ATIMapApertures(-1, pATI); /* Ignore errors */
|
|
|
|
#ifdef AVOID_CPIO
|
|
|
|
if (!pATI->pBlock[0])
|
|
{
|
|
ATIUnmapApertures(-1, pATI);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
/* Make sure any Mach64 is not in some weird state */
|
|
bus_cntl = inr(BUS_CNTL);
|
|
if (Chip < ATI_CHIP_264VTB)
|
|
outr(BUS_CNTL,
|
|
(bus_cntl & ~(BUS_HOST_ERR_INT_EN | BUS_FIFO_ERR_INT_EN)) |
|
|
(BUS_HOST_ERR_INT | BUS_FIFO_ERR_INT));
|
|
else if (Chip < ATI_CHIP_264VT4)
|
|
outr(BUS_CNTL, (bus_cntl & ~BUS_HOST_ERR_INT_EN) | BUS_HOST_ERR_INT);
|
|
|
|
gen_test_cntl = inr(GEN_TEST_CNTL);
|
|
IOValue = gen_test_cntl &
|
|
(GEN_OVR_OUTPUT_EN | GEN_OVR_POLARITY | GEN_CUR_EN | GEN_BLOCK_WR_EN);
|
|
outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN);
|
|
outr(GEN_TEST_CNTL, IOValue);
|
|
outr(GEN_TEST_CNTL, IOValue | GEN_GUI_EN);
|
|
|
|
/* See if a Mach64 answers */
|
|
IOValue = inr(SCRATCH_REG0);
|
|
|
|
/* Test odd bits */
|
|
outr(SCRATCH_REG0, 0x55555555U);
|
|
if (inr(SCRATCH_REG0) == 0x55555555U)
|
|
{
|
|
/* Test even bits */
|
|
outr(SCRATCH_REG0, 0xAAAAAAAAU);
|
|
if (inr(SCRATCH_REG0) == 0xAAAAAAAAU)
|
|
{
|
|
/*
|
|
* *Something* has a R/W 32-bit register at this address. Try to
|
|
* make sure it's a Mach64. The following assumes that ATI will
|
|
* not be producing any more adapters that do not register
|
|
* themselves in PCI configuration space.
|
|
*/
|
|
ATIMach64ChipID(pATI, ChipType);
|
|
if ((pATI->Chip != ATI_CHIP_Mach64) ||
|
|
(pATI->CPIODecoding == BLOCK_IO))
|
|
pATI->Adapter = ATI_ADAPTER_MACH64;
|
|
}
|
|
}
|
|
|
|
/* Restore clobbered register value */
|
|
outr(SCRATCH_REG0, IOValue);
|
|
|
|
/* If no Mach64 was detected, return now */
|
|
if (pATI->Adapter != ATI_ADAPTER_MACH64)
|
|
{
|
|
outr(GEN_TEST_CNTL, gen_test_cntl);
|
|
outr(BUS_CNTL, bus_cntl);
|
|
ATIUnmapApertures(-1, pATI);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Determine legacy BIOS address */
|
|
pATI->BIOSBase = 0x000C0000U +
|
|
(GetBits(inr(SCRATCH_REG1), BIOS_BASE_SEGMENT) << 11);
|
|
|
|
ATIUnmapApertures(-1, pATI);
|
|
pATI->PCIInfo = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
#ifdef AVOID_CPIO
|
|
|
|
/*
|
|
* ATIMach64Probe --
|
|
*
|
|
* This function looks for a Mach64 at a particular MMIO address and returns an
|
|
* ATIRec if one is found.
|
|
*/
|
|
static ATIPtr
|
|
ATIMach64Probe
|
|
(
|
|
pciVideoPtr pVideo,
|
|
const IOADDRESS IOBase,
|
|
const CARD8 IODecoding,
|
|
const ATIChipType Chip
|
|
)
|
|
{
|
|
ATIPtr pATI = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
|
|
CARD16 ChipType = 0;
|
|
|
|
pATI->CPIOBase = IOBase;
|
|
pATI->CPIODecoding = IODecoding;
|
|
|
|
if (pVideo)
|
|
{
|
|
pATI->PCIInfo = pVideo;
|
|
ChipType = pVideo->chipType;
|
|
|
|
/*
|
|
* Probe through auxiliary MMIO aperture if one exists. Because such
|
|
* apertures can be enabled/disabled only through PCI, this probes no
|
|
* further.
|
|
*/
|
|
if ((pVideo->size[2] >= 12) &&
|
|
(pATI->Block0Base = pVideo->memBase[2]) &&
|
|
(pATI->Block0Base < (CARD32)(-1 << pVideo->size[2])))
|
|
{
|
|
pATI->Block0Base += 0x00000400U;
|
|
goto LastProbe;
|
|
}
|
|
|
|
/*
|
|
* Probe through the primary MMIO aperture that exists at the tail end
|
|
* of the linear aperture. Test for both 8MB and 4MB linear apertures.
|
|
*/
|
|
if ((pVideo->size[0] >= 22) && (pATI->Block0Base = pVideo->memBase[0]))
|
|
{
|
|
pATI->Block0Base += 0x007FFC00U;
|
|
if ((pVideo->size[0] >= 23) &&
|
|
ATIMach64Detect(pATI, ChipType, Chip))
|
|
return pATI;
|
|
|
|
pATI->Block0Base -= 0x00400000U;
|
|
if (ATIMach64Detect(pATI, ChipType, Chip))
|
|
return pATI;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* A last, perhaps desparate, probe attempt. Note that if this succeeds,
|
|
* there's a VGA in the system and it's likely the PIO version of the
|
|
* driver should be used instead (barring OS issues).
|
|
*/
|
|
pATI->Block0Base = 0x000BFC00U;
|
|
|
|
LastProbe:
|
|
if (ATIMach64Detect(pATI, ChipType, Chip))
|
|
return pATI;
|
|
|
|
xfree(pATI);
|
|
return NULL;
|
|
}
|
|
|
|
#else /* AVOID_CPIO */
|
|
|
|
/*
|
|
* ATIMach64Probe --
|
|
*
|
|
* This function looks for a Mach64 at a particular PIO address and returns an
|
|
* ATIRec if one is found.
|
|
*/
|
|
static ATIPtr
|
|
ATIMach64Probe
|
|
(
|
|
pciVideoPtr pVideo,
|
|
const IOADDRESS IOBase,
|
|
const CARD8 IODecoding,
|
|
const ATIChipType Chip
|
|
)
|
|
{
|
|
ATIPtr pATI;
|
|
CARD32 IOValue;
|
|
CARD16 ChipType = 0;
|
|
|
|
if (!IOBase)
|
|
return NULL;
|
|
|
|
if (pVideo)
|
|
{
|
|
if ((IODecoding == BLOCK_IO) &&
|
|
((pVideo->size[1] < 8) ||
|
|
(IOBase >= (CARD32)(-1 << pVideo->size[1]))))
|
|
return NULL;
|
|
|
|
ChipType = pVideo->chipType;
|
|
}
|
|
|
|
pATI = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
|
|
pATI->CPIOBase = IOBase;
|
|
pATI->CPIODecoding = IODecoding;
|
|
pATI->PCIInfo = pVideo;
|
|
|
|
if (!ATIMach64Detect(pATI, ChipType, Chip))
|
|
{
|
|
xfree(pATI);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Determine VGA capability. VGA can always be enabled on integrated
|
|
* controllers. For the GX/CX, it's a board strap.
|
|
*/
|
|
if (pATI->Chip >= ATI_CHIP_264CT)
|
|
{
|
|
pATI->VGAAdapter = ATI_ADAPTER_MACH64;
|
|
}
|
|
else
|
|
{
|
|
IOValue = inr(CONFIG_STATUS64_0);
|
|
pATI->BusType = GetBits(IOValue, CFG_BUS_TYPE);
|
|
IOValue &= (CFG_VGA_EN | CFG_CHIP_EN);
|
|
if (pATI->Chip == ATI_CHIP_88800CX)
|
|
IOValue |= CFG_VGA_EN;
|
|
if (IOValue == (CFG_VGA_EN | CFG_CHIP_EN))
|
|
{
|
|
pATI->VGAAdapter = ATI_ADAPTER_MACH64;
|
|
pATI->CPIO_VGAWonder = 0x01CEU;
|
|
pATI->VGAOffset = 0x80U;
|
|
}
|
|
}
|
|
|
|
return pATI;
|
|
}
|
|
|
|
/*
|
|
* ATIAssignVGA --
|
|
*
|
|
* This function is called to associate a VGA interface with an accelerator.
|
|
* This is done by temporarily configuring the accelerator to route VGA RAMDAC
|
|
* I/O through the accelerator's RAMDAC. A value is then written through the
|
|
* VGA DAC ports and a check is made to see if the same value shows up on the
|
|
* accelerator side.
|
|
*/
|
|
static void
|
|
ATIAssignVGA
|
|
(
|
|
pciVideoPtr pVideo,
|
|
ATIPtr *ppVGA,
|
|
ATIPtr pATI,
|
|
ATIPtr p8514,
|
|
CARD8 *ProbeFlags
|
|
)
|
|
{
|
|
ATIPtr pVGA = *ppVGA;
|
|
CARD8 OldDACMask;
|
|
|
|
/* Assume unassignable VGA */
|
|
pATI->VGAAdapter = ATI_ADAPTER_NONE;
|
|
|
|
/* If no assignable VGA, return now */
|
|
if ((pATI != pVGA) && (!pVGA || (pVGA->Adapter > ATI_ADAPTER_VGA)))
|
|
return;
|
|
|
|
switch (pATI->Adapter)
|
|
{
|
|
case ATI_ADAPTER_8514A:
|
|
{
|
|
/*
|
|
* Assumption: Bit DISABPASSTHRU in ADVFUNC_CNTL is already
|
|
* off.
|
|
*/
|
|
OldDACMask = inb(VGA_DAC_MASK);
|
|
|
|
if (inb(IBM_DAC_MASK) == OldDACMask)
|
|
{
|
|
outb(VGA_DAC_MASK, 0xA5U);
|
|
if (inb(IBM_DAC_MASK) == 0xA5U)
|
|
pATI->VGAAdapter = ATI_ADAPTER_VGA;
|
|
outb(VGA_DAC_MASK, OldDACMask);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ATI_ADAPTER_MACH8:
|
|
{
|
|
CARD16 ClockSel = inw(CLOCK_SEL);
|
|
|
|
if (ClockSel & DISABPASSTHRU)
|
|
outw(CLOCK_SEL, ClockSel & ~DISABPASSTHRU);
|
|
|
|
ProbeWaitIdleEmpty();
|
|
|
|
OldDACMask = inb(VGA_DAC_MASK);
|
|
|
|
if (inb(IBM_DAC_MASK) == OldDACMask)
|
|
{
|
|
outb(VGA_DAC_MASK, 0xA5U);
|
|
if (inb(IBM_DAC_MASK) == 0xA5U)
|
|
pATI->VGAAdapter = ATI_ADAPTER_VGA;
|
|
outb(VGA_DAC_MASK, OldDACMask);
|
|
}
|
|
|
|
if (ClockSel & DISABPASSTHRU)
|
|
outw(CLOCK_SEL, ClockSel);
|
|
}
|
|
break;
|
|
|
|
case ATI_ADAPTER_MACH32:
|
|
{
|
|
CARD16 ClockSel = inw(CLOCK_SEL),
|
|
MiscOptions = inw(MISC_OPTIONS);
|
|
|
|
if (ClockSel & DISABPASSTHRU)
|
|
outw(CLOCK_SEL, ClockSel & ~DISABPASSTHRU);
|
|
if (MiscOptions & (DISABLE_VGA | DISABLE_DAC))
|
|
outw(MISC_OPTIONS,
|
|
MiscOptions & ~(DISABLE_VGA | DISABLE_DAC));
|
|
|
|
ProbeWaitIdleEmpty();
|
|
|
|
OldDACMask = inb(VGA_DAC_MASK);
|
|
|
|
if (inb(IBM_DAC_MASK) == OldDACMask)
|
|
{
|
|
outb(VGA_DAC_MASK, 0xA5U);
|
|
if (inb(IBM_DAC_MASK) == 0xA5U)
|
|
pATI->VGAAdapter = ATI_ADAPTER_MACH32;
|
|
outb(VGA_DAC_MASK, OldDACMask);
|
|
}
|
|
|
|
if (ClockSel & DISABPASSTHRU)
|
|
outw(CLOCK_SEL, ClockSel);
|
|
if (MiscOptions & (DISABLE_VGA | DISABLE_DAC))
|
|
outw(MISC_OPTIONS, MiscOptions);
|
|
}
|
|
break;
|
|
|
|
case ATI_ADAPTER_MACH64:
|
|
{
|
|
CARD32 DACCntl = inr(DAC_CNTL);
|
|
|
|
if (!(DACCntl & DAC_VGA_ADR_EN))
|
|
outr(DAC_CNTL, DACCntl | DAC_VGA_ADR_EN);
|
|
|
|
OldDACMask = inb(VGA_DAC_MASK);
|
|
|
|
if (in8(M64_DAC_MASK) == OldDACMask)
|
|
{
|
|
outb(VGA_DAC_MASK, 0xA5U);
|
|
if (in8(M64_DAC_MASK) == 0xA5U)
|
|
pATI->VGAAdapter = ATI_ADAPTER_MACH64;
|
|
outb(VGA_DAC_MASK, OldDACMask);
|
|
}
|
|
|
|
if (!(DACCntl & DAC_VGA_ADR_EN))
|
|
outr(DAC_CNTL, DACCntl);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
|
|
{
|
|
pATI->CPIO_VGAWonder = 0;
|
|
return;
|
|
}
|
|
|
|
if (pATI->CPIO_VGAWonder)
|
|
{
|
|
ATIVGAWonderProbe(pVideo, pATI, p8514, ProbeFlags);
|
|
if (!pATI->CPIO_VGAWonder)
|
|
{
|
|
/*
|
|
* Some adapters are reputed to append ATI extended VGA registers
|
|
* to the VGA Graphics controller registers. In particular, 0x01CE
|
|
* cannot, in general, be used in a PCI environment due to routing
|
|
* of I/O through the bus tree.
|
|
*/
|
|
pATI->CPIO_VGAWonder = GRAX;
|
|
ATIVGAWonderProbe(pVideo, pATI, p8514, ProbeFlags);
|
|
}
|
|
}
|
|
|
|
if (pATI == pVGA)
|
|
{
|
|
pATI->SharedVGA = TRUE;
|
|
return;
|
|
}
|
|
|
|
/* Assign the VGA to this adapter */
|
|
xfree(pVGA);
|
|
*ppVGA = pATI;
|
|
|
|
xf86MsgVerb(X_INFO, 3, ATI_NAME ": VGA assigned to this adapter.\n");
|
|
}
|
|
|
|
#ifndef AVOID_NON_PCI
|
|
|
|
/*
|
|
* ATIClaimVGA --
|
|
*
|
|
* Attempt to assign a non-shareable VGA to an accelerator. If successful,
|
|
* update ProbeFlags array.
|
|
*/
|
|
static void
|
|
ATIClaimVGA
|
|
(
|
|
pciVideoPtr pVideo,
|
|
ATIPtr *ppVGA,
|
|
ATIPtr pATI,
|
|
ATIPtr p8514,
|
|
CARD8 *ProbeFlags,
|
|
int Detected
|
|
)
|
|
{
|
|
ATIAssignVGA(pVideo, ppVGA, pATI, p8514, ProbeFlags);
|
|
if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
|
|
return;
|
|
|
|
ATIClaimSparseIOBases(ProbeFlags, MonochromeIOBase, 48, Detected);
|
|
if (!pATI->CPIO_VGAWonder)
|
|
return;
|
|
|
|
ATIClaimSparseIOBases(ProbeFlags, pATI->CPIO_VGAWonder, 2, Detected);
|
|
}
|
|
|
|
#endif /* AVOID_NON_PCI */
|
|
|
|
/*
|
|
* ATIFindVGA --
|
|
*
|
|
* This function determines if a VGA associated with an ATI PCI adapter is
|
|
* shareable.
|
|
*/
|
|
static void
|
|
ATIFindVGA
|
|
(
|
|
pciVideoPtr pVideo,
|
|
ATIPtr *ppVGA,
|
|
ATIPtr *ppATI,
|
|
ATIPtr p8514,
|
|
CARD8 *ProbeFlags
|
|
)
|
|
{
|
|
ATIPtr pATI = *ppATI;
|
|
|
|
if (!*ppVGA)
|
|
{
|
|
/*
|
|
* An ATI PCI adapter has been detected at this point, and its VGA, if
|
|
* any, is shareable. Ensure the VGA isn't in sleep mode.
|
|
*/
|
|
outb(GENENA, 0x16U);
|
|
outb(GENVS, 0x01U);
|
|
outb(GENENA, 0x0EU);
|
|
|
|
pATI = ATIVGAProbe(pATI);
|
|
if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
|
|
return;
|
|
|
|
ppVGA = ppATI;
|
|
}
|
|
|
|
ATIAssignVGA(pVideo, ppVGA, pATI, p8514, ProbeFlags);
|
|
}
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
/*
|
|
* ATIProbe --
|
|
*
|
|
* This function is called once, at the start of the first server generation to
|
|
* do a minimal probe for supported hardware.
|
|
*/
|
|
Bool
|
|
ATIProbe
|
|
(
|
|
DriverPtr pDriver,
|
|
int flags
|
|
)
|
|
{
|
|
ATIPtr pATI, *ATIPtrs = NULL;
|
|
GDevPtr *GDevs, pGDev;
|
|
pciVideoPtr pVideo, *xf86PciVideoInfo = xf86GetPciVideoInfo();
|
|
ATIGDev *ATIGDevs = NULL, *pATIGDev;
|
|
ScrnInfoPtr pScreenInfo;
|
|
Bool ProbeSuccess = FALSE;
|
|
Bool DoRage128 = FALSE, DoRadeon = FALSE;
|
|
int i, j, k;
|
|
int nGDev, nATIGDev = -1, nATIPtr = 0;
|
|
int Chipset;
|
|
ATIChipType Chip;
|
|
|
|
#if !defined(AVOID_NON_PCI) || !defined(AVOID_CPIO)
|
|
pciConfigPtr pPCI;
|
|
CARD32 PciReg;
|
|
#endif /* AVOID_NON_PCI || AVOID_CPIO */
|
|
|
|
#ifndef AVOID_NON_PCI
|
|
ATIPtr pMach64[3] = {NULL, NULL, NULL};
|
|
#endif
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
ATIPtr pVGA = NULL, p8514 = NULL;
|
|
pciConfigPtr *xf86PciInfo = xf86GetPciConfigInfo();
|
|
PortPtr PCIPorts = NULL;
|
|
int nPCIPort = 0;
|
|
CARD8 fChipsets[ATI_CHIPSET_MAX];
|
|
static const IOADDRESS Mach64SparseIOBases[] = {0x02ECU, 0x01CCU, 0x01C8U};
|
|
CARD8 ProbeFlags[LongPort(SPARSE_IO_BASE) + 1];
|
|
|
|
unsigned long BIOSBase;
|
|
static const CARD8 ATISignature[] = " 761295520";
|
|
# define SignatureSize 10
|
|
# define PrefixSize 0x50U
|
|
# define BIOSSignature 0x30U
|
|
CARD8 BIOS[PrefixSize];
|
|
# define BIOSWord(_n) (BIOS[_n] | (BIOS[(_n) + 1] << 8))
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
# define AddAdapter(_p) \
|
|
do \
|
|
{ \
|
|
nATIPtr++; \
|
|
ATIPtrs = (ATIPtr *)xnfrealloc(ATIPtrs, SizeOf(ATIPtr) * nATIPtr); \
|
|
ATIPtrs[nATIPtr - 1] = (_p); \
|
|
(_p)->iEntity = -2; \
|
|
} while (0)
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
(void)memset(fChipsets, FALSE, SizeOf(fChipsets));
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
if (!(flags & PROBE_DETECT))
|
|
{
|
|
/*
|
|
* Get a list of XF86Config device sections whose "Driver" is either
|
|
* not specified, or specified as this driver. From this list,
|
|
* eliminate those device sections that specify a "Chipset" or a
|
|
* "ChipID" not recognised by the driver. Those device sections that
|
|
* specify a "ChipRev" without a "ChipID" are also weeded out.
|
|
*/
|
|
nATIGDev = 0;
|
|
if ((nGDev = xf86MatchDevice(ATI_NAME, &GDevs)) > 0)
|
|
{
|
|
ATIGDevs = (ATIGDevPtr)xnfcalloc(nGDev, SizeOf(ATIGDev));
|
|
|
|
for (i = 0, pATIGDev = ATIGDevs; i < nGDev; i++)
|
|
{
|
|
pGDev = GDevs[i];
|
|
Chipset = ATIIdentProbe(pGDev->chipset);
|
|
if (Chipset == -1)
|
|
continue;
|
|
|
|
if ((pGDev->chipID > (int)((CARD16)(-1))) ||
|
|
(pGDev->chipRev > (int)((CARD8)(-1))))
|
|
continue;
|
|
|
|
if (pGDev->chipID >= 0)
|
|
{
|
|
if (ATIChipID(pGDev->chipID, 0) == ATI_CHIP_Mach64)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (pGDev->chipRev >= 0)
|
|
continue;
|
|
}
|
|
|
|
pATIGDev->pGDev = pGDev;
|
|
pATIGDev->Chipset = Chipset;
|
|
nATIGDev++;
|
|
pATIGDev++;
|
|
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": Candidate \"Device\" section \"%s\".\n",
|
|
pGDev->identifier);
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
fChipsets[Chipset] = TRUE;
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
}
|
|
|
|
xfree(GDevs);
|
|
|
|
if (!nATIGDev)
|
|
{
|
|
xfree(ATIGDevs);
|
|
ATIGDevs = NULL;
|
|
}
|
|
}
|
|
|
|
if (xf86MatchDevice(R128_NAME, NULL) > 0)
|
|
DoRage128 = TRUE;
|
|
if (xf86MatchDevice(RADEON_NAME, NULL) > 0)
|
|
DoRadeon = TRUE;
|
|
}
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
/*
|
|
* Collect hardware information. This must be done with care to avoid
|
|
* lockups due to overlapping I/O port assignments.
|
|
*
|
|
* First, scan PCI configuration space for registered I/O ports (which will
|
|
* be block I/O bases). Each such port is used to generate a list of
|
|
* sparse I/O bases it precludes. This list is then used to decide whether
|
|
* or not certain sparse I/O probes are done. Unfortunately, this assumes
|
|
* that any registered I/O base actually reserves upto the full 256 ports
|
|
* allowed by the PCI specification. This assumption holds true for PCI
|
|
* Mach64, but probably doesn't for other device types. For some things,
|
|
* such as video devices, the number of ports a base represents is
|
|
* determined by the server's PCI probe, but, for other devices, this
|
|
* cannot be done by a user-level process without jeopardizing system
|
|
* integrity. This information should ideally be retrieved from the OS's
|
|
* own PCI probe (if any), but there's currently no portable way of doing
|
|
* so. The following allows sparse I/O probes to be forced in certain
|
|
* circumstances when an appropriate chipset specification is used in any
|
|
* XF86Config Device section.
|
|
*
|
|
* Note that this is not bullet-proof. Lockups can still occur, but they
|
|
* will usually be due to devices that are misconfigured to respond to the
|
|
* same I/O ports as 8514/A's or ATI sparse I/O devices without registering
|
|
* them in PCI configuration space.
|
|
*/
|
|
if (nATIGDev)
|
|
{
|
|
if (xf86PciVideoInfo)
|
|
{
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor == PCI_VENDOR_ATI) ||
|
|
!(pPCI = pVideo->thisCard))
|
|
continue;
|
|
|
|
ATIScanPCIBases(&PCIPorts, &nPCIPort,
|
|
&pPCI->pci_base0, pVideo->size,
|
|
(pciReadLong(pPCI->tag, PCI_CMD_STAT_REG) &
|
|
PCI_CMD_IO_ENABLE) ? 0 : Allowed);
|
|
}
|
|
}
|
|
|
|
/* Check non-video PCI devices for I/O bases */
|
|
if (xf86PciInfo)
|
|
{
|
|
for (i = 0; (pPCI = xf86PciInfo[i++]); )
|
|
{
|
|
if ((pPCI->pci_vendor == PCI_VENDOR_ATI) ||
|
|
(pPCI->pci_base_class == PCI_CLASS_BRIDGE) ||
|
|
(pPCI->pci_header_type &
|
|
~GetByte(PCI_HEADER_MULTIFUNCTION, 2)))
|
|
continue;
|
|
|
|
ATIScanPCIBases(&PCIPorts, &nPCIPort,
|
|
&pPCI->pci_base0, pPCI->basesize,
|
|
(pciReadLong(pPCI->tag, PCI_CMD_STAT_REG) &
|
|
PCI_CMD_IO_ENABLE) ? 0 : Allowed);
|
|
}
|
|
}
|
|
|
|
/* Generate ProbeFlags array from list of registered PCI I/O bases */
|
|
(void)memset(ProbeFlags, Allowed | DoProbe, SizeOf(ProbeFlags));
|
|
for (i = 0; i < nPCIPort; i++)
|
|
{
|
|
CARD32 Base = PCIPorts[i].Base;
|
|
CARD16 Count = (1 << PCIPorts[i].Size) - 1;
|
|
CARD8 ProbeFlag = PCIPorts[i].Flag;
|
|
|
|
/*
|
|
* The following reduction of Count is based on the assumption that
|
|
* PCI-registered I/O port ranges do not overlap.
|
|
*/
|
|
for (j = 0; j < nPCIPort; j++)
|
|
{
|
|
CARD32 Base2 = PCIPorts[j].Base;
|
|
|
|
if (Base < Base2)
|
|
while ((Base + Count) >= Base2)
|
|
Count >>= 1;
|
|
}
|
|
|
|
Base = LongPort(Base);
|
|
Count = LongPort((Count | IO_BYTE_SELECT) + 1);
|
|
while (Count--)
|
|
ProbeFlags[Base++] &= ProbeFlag;
|
|
}
|
|
|
|
xfree(PCIPorts);
|
|
|
|
#ifndef AVOID_NON_PCI
|
|
|
|
/*
|
|
* A note on probe strategy. I/O and memory response by certain PCI
|
|
* devices has been disabled by the common layer at this point,
|
|
* including any devices this driver might be interested in. The
|
|
* following does sparse I/O probes, followed by block I/O probes.
|
|
* Block I/O probes are dictated by what is found to be of interest in
|
|
* PCI configuration space. All this will detect ATI adapters that do
|
|
* not implement this disablement, pre-PCI or not.
|
|
*
|
|
* PCI configuration space is then scanned again for ATI devices that
|
|
* failed to be detected the first time around. Each such device is
|
|
* probed for again, this time with I/O temporarily enabled through
|
|
* PCI.
|
|
*/
|
|
if (ATICheckSparseIOBases(NULL, ProbeFlags, ATTRX, 16, TRUE) ==
|
|
DoProbe)
|
|
{
|
|
pATI = ATIVGAProbe(NULL);
|
|
if (pATI->Adapter == ATI_ADAPTER_NONE)
|
|
{
|
|
xfree(pATI);
|
|
|
|
xf86MsgVerb(X_INFO, 4,
|
|
ATI_NAME ": Unshared VGA not detected.\n");
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Claim all MDA/HGA/CGA/EGA/VGA I/O ports. This might need to
|
|
* be more selective.
|
|
*/
|
|
ATIClaimSparseIOBases(ProbeFlags, MonochromeIOBase, 48,
|
|
DetectedVGA);
|
|
|
|
pVGA = pATI;
|
|
strcpy(Identifier, "Unshared VGA");
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s detected.\n", Identifier);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xf86MsgVerb(X_INFO, 2, ATI_NAME ": Unshared VGA not probed.\n");
|
|
}
|
|
|
|
/*
|
|
* Mach8/32 probing doesn't work well on some legacy free ia64
|
|
* However if we use AVOID_CPIO we don't get here at all.
|
|
*/
|
|
if (ATICheckSparseIOBases(NULL, ProbeFlags, 0x02E8U, 8,
|
|
fChipsets[ATI_CHIPSET_IBM8514] ||
|
|
fChipsets[ATI_CHIPSET_MACH8] ||
|
|
fChipsets[ATI_CHIPSET_MACH32]) == DoProbe)
|
|
{
|
|
if ((pATI = ATI8514Probe(NULL)))
|
|
{
|
|
strcpy(Identifier, "Unshared 8514/A");
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s detected.\n", Identifier);
|
|
|
|
AddAdapter(p8514 = pATI);
|
|
|
|
if ((pATI->VGAAdapter != ATI_ADAPTER_NONE) ||
|
|
(pATI->Coprocessor != ATI_CHIP_NONE))
|
|
ATIClaimVGA(NULL, &pVGA, pATI, p8514, ProbeFlags,
|
|
Detected8514A);
|
|
|
|
ATIClaimSparseIOBases(ProbeFlags, 0x02E8U, 8, Detected8514A);
|
|
}
|
|
else
|
|
{
|
|
xf86MsgVerb(X_INFO, 4,
|
|
ATI_NAME ": Unshared 8514/A not detected.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
xf86MsgVerb(X_INFO, 2,
|
|
ATI_NAME ": Unshared 8514/A not probed.\n");
|
|
}
|
|
|
|
/*
|
|
* Also NONPCI Mach64 probing is evil on legacy free platforms.
|
|
* However if we use AVOID_CPIO we don't get here at all.
|
|
*/
|
|
for (i = 0; i < NumberOf(Mach64SparseIOBases); i++)
|
|
{
|
|
if (ATICheckSparseIOBases(NULL, ProbeFlags, Mach64SparseIOBases[i],
|
|
4, fChipsets[ATI_CHIPSET_MACH64]) != DoProbe)
|
|
{
|
|
xf86MsgVerb(X_INFO, 2,
|
|
ATI_NAME ": Unshared Mach64 at PIO base 0x%04lX not"
|
|
" probed.\n",
|
|
Mach64SparseIOBases[i]);
|
|
continue;
|
|
}
|
|
|
|
pATI = ATIMach64Probe(NULL, Mach64SparseIOBases[i], SPARSE_IO, 0);
|
|
if (!pATI)
|
|
{
|
|
xf86MsgVerb(X_INFO, 4,
|
|
ATI_NAME ": Unshared Mach64 at PIO base 0x%04lX not"
|
|
" detected.\n", Mach64SparseIOBases[i]);
|
|
continue;
|
|
}
|
|
|
|
sprintf(Identifier, "Unshared Mach64 at sparse PIO base 0x%04lX",
|
|
Mach64SparseIOBases[i]);
|
|
xf86MsgVerb(X_INFO, 3, ATI_NAME ": %s detected.\n", Identifier);
|
|
|
|
AddAdapter(pMach64[i] = pATI);
|
|
|
|
if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
|
|
ATIClaimVGA(NULL, &pVGA, pATI, p8514, ProbeFlags,
|
|
DetectedMach64);
|
|
|
|
ATIClaimSparseIOBases(ProbeFlags, Mach64SparseIOBases[i], 4,
|
|
DetectedMach64);
|
|
}
|
|
#endif /* AVOID_NON_PCI */
|
|
|
|
}
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
if (xf86PciVideoInfo)
|
|
{
|
|
if (nATIGDev)
|
|
{
|
|
|
|
#ifndef AVOID_NON_PCI
|
|
|
|
#ifdef AVOID_CPIO
|
|
|
|
/* PCI sparse I/O adapters can still be used through MMIO */
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
|
|
(pVideo->chipType == PCI_CHIP_MACH32) ||
|
|
pVideo->size[1] ||
|
|
!(pPCI = pVideo->thisCard))
|
|
continue;
|
|
|
|
PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG);
|
|
|
|
/* Possibly fix block I/O indicator */
|
|
if (PciReg & 0x00000004U)
|
|
pciWriteLong(pPCI->tag, PCI_REG_USERCONFIG,
|
|
PciReg & ~0x00000004U);
|
|
|
|
Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
|
|
|
|
/*
|
|
* The CPIO base used by the adapter is of little concern here.
|
|
*/
|
|
pATI = ATIMach64Probe(pVideo, 0, SPARSE_IO, Chip);
|
|
if (!pATI)
|
|
continue;
|
|
|
|
sprintf(Identifier,
|
|
"Unshared PCI sparse I/O Mach64 in slot %d:%d:%d",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s detected through Block 0 at 0x%08lX.\n",
|
|
Identifier, pATI->Block0Base);
|
|
AddAdapter(pATI);
|
|
pATI->PCIInfo = pVideo;
|
|
}
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
|
|
(pVideo->chipType == PCI_CHIP_MACH32) ||
|
|
!pVideo->size[1])
|
|
continue;
|
|
|
|
/* For now, ignore Rage128's and Radeon's */
|
|
Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
|
|
if ((Chip > ATI_CHIP_Mach64) ||
|
|
!(pPCI = pVideo->thisCard))
|
|
continue;
|
|
|
|
/*
|
|
* Possibly fix block I/O indicator in PCI configuration space.
|
|
*/
|
|
PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG);
|
|
if (!(PciReg & 0x00000004U))
|
|
pciWriteLong(pPCI->tag, PCI_REG_USERCONFIG,
|
|
PciReg | 0x00000004U);
|
|
|
|
pATI =
|
|
ATIMach64Probe(pVideo, pVideo->ioBase[1], BLOCK_IO, Chip);
|
|
if (!pATI)
|
|
continue;
|
|
|
|
sprintf(Identifier, "Unshared PCI/AGP Mach64 in slot %d:%d:%d",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s detected.\n", Identifier);
|
|
AddAdapter(pATI);
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
/* This is probably not necessary */
|
|
if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
|
|
ATIClaimVGA(pVideo, &pVGA, pATI, p8514,
|
|
ProbeFlags, DetectedMach64);
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
}
|
|
|
|
#endif /* AVOID_NON_PCI */
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
/*
|
|
* This is the second pass through PCI configuration space. Much
|
|
* of this is verbiage to deal with potential situations that are
|
|
* very unlikely to occur in practice.
|
|
*
|
|
* First, look for non-ATI shareable VGA's. For now, these must
|
|
* the primary device.
|
|
*/
|
|
if (ATICheckSparseIOBases(NULL, ProbeFlags, ATTRX, 16, TRUE) ==
|
|
DoProbe)
|
|
{
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor == PCI_VENDOR_ATI) ||
|
|
!xf86IsPrimaryPci(pVideo))
|
|
continue;
|
|
|
|
if (!xf86CheckPciSlot(pVideo->bus,
|
|
pVideo->device,
|
|
pVideo->func))
|
|
continue;
|
|
|
|
xf86SetPciVideo(pVideo, MEM_IO);
|
|
|
|
pATI = ATIVGAProbe(NULL);
|
|
if (pATI->Adapter == ATI_ADAPTER_NONE)
|
|
{
|
|
xfree(pATI);
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI/AGP VGA compatible in slot"
|
|
" %d:%d:%d could not be detected!\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
}
|
|
else
|
|
{
|
|
sprintf(Identifier,
|
|
"Shared non-ATI VGA in PCI/AGP slot %d:%d:%d",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
xf86MsgVerb(X_INFO, 3, ATI_NAME ": %s detected.\n",
|
|
Identifier);
|
|
AddAdapter(pATI);
|
|
pATI->SharedVGA = TRUE;
|
|
pATI->BusType = ATI_BUS_PCI;
|
|
pATI->PCIInfo = pVideo;
|
|
}
|
|
|
|
xf86SetPciVideo(NULL, NONE);
|
|
}
|
|
}
|
|
|
|
/* Next, look for PCI Mach32's */
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
|
|
(pVideo->chipType != PCI_CHIP_MACH32))
|
|
continue;
|
|
|
|
switch (ATICheckSparseIOBases(pVideo, ProbeFlags,
|
|
0x02E8U, 8, TRUE))
|
|
{
|
|
case 0:
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach32 in slot %d:%d:%d will not"
|
|
" be enabled\n because it conflicts with a"
|
|
" non-video PCI/AGP device.\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
break;
|
|
|
|
#ifndef AVOID_NON_PCI
|
|
|
|
case Detected8514A:
|
|
if ((p8514->BusType >= ATI_BUS_PCI) && !p8514->PCIInfo)
|
|
p8514->PCIInfo = pVideo;
|
|
else
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach32 in slot %d:%d:%d will"
|
|
" not be enabled\n because it conflicts with"
|
|
" another %s %s.\n",
|
|
pVideo->bus, pVideo->device, pVideo->func,
|
|
ATIBusNames[p8514->BusType],
|
|
ATIAdapterNames[p8514->Adapter]);
|
|
break;
|
|
|
|
case DetectedMach64:
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach32 in slot %d:%d:%d will not"
|
|
" be enabled\n because it conflicts with a Mach64"
|
|
" at I/O base 0x02EC.\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
break;
|
|
|
|
#endif /* AVOID_NON_PCI */
|
|
|
|
default: /* Must be DoProbe */
|
|
if (!xf86CheckPciSlot(pVideo->bus,
|
|
pVideo->device,
|
|
pVideo->func))
|
|
continue;
|
|
|
|
xf86SetPciVideo(pVideo, MEM_IO);
|
|
|
|
if (!(pATI = ATI8514Probe(pVideo)))
|
|
{
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach32 in slot %d:%d:%d could"
|
|
" not be detected!\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
}
|
|
else
|
|
{
|
|
sprintf(Identifier,
|
|
"Shared 8514/A in PCI slot %d:%d:%d",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s detected.\n", Identifier);
|
|
if (pATI->Adapter != ATI_ADAPTER_MACH32)
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach32 in slot %d:%d:%d"
|
|
" could only be detected as an %s!\n",
|
|
pVideo->bus, pVideo->device, pVideo->func,
|
|
ATIAdapterNames[pATI->Adapter]);
|
|
|
|
AddAdapter(pATI);
|
|
pATI->SharedAccelerator = TRUE;
|
|
|
|
if ((pATI->VGAAdapter != ATI_ADAPTER_NONE) ||
|
|
(pATI->Coprocessor != ATI_CHIP_NONE))
|
|
ATIFindVGA(pVideo, &pVGA, &pATI, p8514,
|
|
ProbeFlags);
|
|
}
|
|
xf86SetPciVideo(NULL, NONE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Next, look for sparse I/O Mach64's */
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
|
|
(pVideo->chipType == PCI_CHIP_MACH32) ||
|
|
pVideo->size[1])
|
|
continue;
|
|
|
|
pPCI = pVideo->thisCard;
|
|
if (pPCI == NULL)
|
|
continue;
|
|
|
|
PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG);
|
|
j = PciReg & 0x03U;
|
|
if (j == 0x03U)
|
|
{
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach64 in slot %d:%d:%d cannot be"
|
|
" enabled\n because it has neither a block, nor a"
|
|
" sparse, I/O base.\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
}
|
|
else switch(ATICheckSparseIOBases(pVideo, ProbeFlags,
|
|
Mach64SparseIOBases[j], 4, TRUE))
|
|
{
|
|
case 0:
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach64 in slot %d:%d:%d will not"
|
|
" be enabled\n because it conflicts with another"
|
|
" non-video PCI device.\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
break;
|
|
|
|
#ifndef AVOID_NON_PCI
|
|
|
|
case Detected8514A:
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach64 in slot %d:%d:%d will not"
|
|
" be enabled\n because it conflicts with an %s.\n",
|
|
pVideo->bus, pVideo->device, pVideo->func,
|
|
ATIAdapterNames[p8514->Adapter]);
|
|
break;
|
|
|
|
case DetectedMach64:
|
|
pATI = pMach64[j];
|
|
if ((pATI->BusType >= ATI_BUS_PCI) && !pATI->PCIInfo)
|
|
pATI->PCIInfo = pVideo;
|
|
else
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach64 in slot %d:%d:%d will"
|
|
" not be enabled\n because it conflicts with"
|
|
" another %s Mach64 at sparse I/O base"
|
|
" 0x%04lX.\n",
|
|
pVideo->bus, pVideo->device, pVideo->func,
|
|
ATIBusNames[pATI->BusType],
|
|
Mach64SparseIOBases[j]);
|
|
break;
|
|
|
|
#endif /* AVOID_NON_PCI */
|
|
|
|
default: /* Must be DoProbe */
|
|
if (!xf86CheckPciSlot(pVideo->bus,
|
|
pVideo->device,
|
|
pVideo->func))
|
|
continue;
|
|
|
|
/* Possibly fix block I/O indicator */
|
|
if (PciReg & 0x00000004U)
|
|
pciWriteLong(pPCI->tag, PCI_REG_USERCONFIG,
|
|
PciReg & ~0x00000004U);
|
|
|
|
xf86SetPciVideo(pVideo, MEM_IO);
|
|
|
|
Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
|
|
pATI = ATIMach64Probe(pVideo, Mach64SparseIOBases[j],
|
|
SPARSE_IO, Chip);
|
|
if (!pATI)
|
|
{
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach64 in slot %d:%d:%d could"
|
|
" not be detected!\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
}
|
|
else
|
|
{
|
|
sprintf(Identifier,
|
|
"Shared PCI Mach64 in slot %d:%d:%d",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s with sparse PIO base 0x%04lX"
|
|
" detected.\n", Identifier,
|
|
Mach64SparseIOBases[j]);
|
|
AddAdapter(pATI);
|
|
pATI->SharedAccelerator = TRUE;
|
|
pATI->PCIInfo = pVideo;
|
|
|
|
if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
|
|
ATIFindVGA(pVideo, &pVGA, &pATI, p8514,
|
|
ProbeFlags);
|
|
}
|
|
|
|
xf86SetPciVideo(NULL, NONE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#else /* AVOID_CPIO */
|
|
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
|
|
(pVideo->chipType == PCI_CHIP_MACH32) ||
|
|
pVideo->size[1])
|
|
continue;
|
|
|
|
/* Check if this one has already been detected */
|
|
for (j = 0; j < nATIPtr; j++)
|
|
{
|
|
pATI = ATIPtrs[j];
|
|
if (pATI->PCIInfo == pVideo)
|
|
goto SkipThisSlot;
|
|
}
|
|
|
|
if (!xf86CheckPciSlot(pVideo->bus,
|
|
pVideo->device,
|
|
pVideo->func))
|
|
continue;
|
|
|
|
xf86SetPciVideo(pVideo, MEM_IO);
|
|
|
|
Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
|
|
|
|
/* The adapter's CPIO base is of little concern here */
|
|
pATI = ATIMach64Probe(pVideo, 0, SPARSE_IO, Chip);
|
|
if (pATI)
|
|
{
|
|
sprintf(Identifier, "Shared PCI Mach64 in slot %d:%d:%d",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s with Block 0 base 0x%08lX detected.\n",
|
|
Identifier, pATI->Block0Base);
|
|
AddAdapter(pATI);
|
|
pATI->SharedAccelerator = TRUE;
|
|
pATI->PCIInfo = pVideo;
|
|
}
|
|
else
|
|
{
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI Mach64 in slot %d:%d:%d could not be"
|
|
" detected!\n",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
}
|
|
|
|
xf86SetPciVideo(NULL, NONE);
|
|
|
|
SkipThisSlot:;
|
|
}
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
}
|
|
|
|
/* Lastly, look for block I/O devices */
|
|
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
|
|
{
|
|
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
|
|
(pVideo->chipType == PCI_CHIP_MACH32) ||
|
|
!pVideo->size[1])
|
|
continue;
|
|
|
|
/* Check for Rage128's, Radeon's and later adapters */
|
|
Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
|
|
if (Chip > ATI_CHIP_Mach64)
|
|
{
|
|
if (Chip <= ATI_CHIP_Rage128)
|
|
DoRage128 = TRUE;
|
|
else if (Chip <= ATI_CHIP_Radeon)
|
|
DoRadeon = TRUE;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (!nATIGDev)
|
|
continue;
|
|
|
|
/* Check if this one has already been detected */
|
|
for (j = 0; j < nATIPtr; j++)
|
|
{
|
|
pATI = ATIPtrs[j];
|
|
if (pATI->CPIOBase == pVideo->ioBase[1])
|
|
goto SetPCIInfo;
|
|
}
|
|
|
|
if (!xf86CheckPciSlot(pVideo->bus, pVideo->device, pVideo->func))
|
|
continue;
|
|
|
|
/* Probe for it */
|
|
xf86SetPciVideo(pVideo, MEM_IO);
|
|
|
|
pATI = ATIMach64Probe(pVideo, pVideo->ioBase[1], BLOCK_IO, Chip);
|
|
if (pATI)
|
|
{
|
|
sprintf(Identifier, "Shared PCI/AGP Mach64 in slot %d:%d:%d",
|
|
pVideo->bus, pVideo->device, pVideo->func);
|
|
xf86MsgVerb(X_INFO, 3, ATI_NAME ": %s detected.\n",
|
|
Identifier);
|
|
AddAdapter(pATI);
|
|
pATI->SharedAccelerator = TRUE;
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
|
|
ATIFindVGA(pVideo, &pVGA, &pATI, p8514, ProbeFlags);
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
}
|
|
|
|
xf86SetPciVideo(NULL, NONE);
|
|
|
|
if (!pATI)
|
|
{
|
|
xf86Msg(X_WARNING,
|
|
ATI_NAME ": PCI/AGP Mach64 in slot %d:%d:%d could not be"
|
|
" detected!\n", pVideo->bus, pVideo->device, pVideo->func);
|
|
continue;
|
|
}
|
|
|
|
SetPCIInfo:
|
|
pATI->PCIInfo = pVideo;
|
|
}
|
|
}
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
/*
|
|
* At this point, if there's a non-shareable VGA with its own framebuffer,
|
|
* find out if it's an ATI VGA Wonder.
|
|
*/
|
|
do
|
|
{
|
|
if (!nATIGDev || !pVGA || (pVGA->VGAAdapter > ATI_ADAPTER_VGA))
|
|
break;
|
|
|
|
/* If it has not been assigned to a coprocessor, keep track of it */
|
|
if (pVGA->Coprocessor == ATI_CHIP_NONE)
|
|
AddAdapter(pVGA);
|
|
|
|
/*
|
|
* A VGA should have installed its int 10 vector. Use that to find the
|
|
* VGA BIOS. If this fails, scan all legacy BIOS segments, in 512-byte
|
|
* increments.
|
|
*/
|
|
if (xf86ReadBIOS(0U, 0x42U, BIOS, 2) != 2)
|
|
goto NoVGAWonder;
|
|
|
|
pATI = NULL;
|
|
BIOSBase = 0;
|
|
if (!(BIOS[0] & 0x1FU)) /* Otherwise there's no 512-byte alignment */
|
|
BIOSBase = ((BIOS[1] << 8) | BIOS[0]) << 4;
|
|
|
|
/* Look for its BIOS */
|
|
for(; ; BIOSBase += 0x00000200U)
|
|
{
|
|
if (!BIOSBase)
|
|
goto SkipBiosSegment;
|
|
|
|
if (BIOSBase >= 0x000F8000U)
|
|
goto NoVGAWonder;
|
|
|
|
/* Skip over those that are already known */
|
|
for (i = 0; i < nATIPtr; i++)
|
|
if (ATIPtrs[i]->BIOSBase == BIOSBase)
|
|
goto SkipBiosSegment;
|
|
|
|
/* Get first 80 bytes of video BIOS */
|
|
if (xf86ReadBIOS(BIOSBase, 0, BIOS, SizeOf(BIOS)) !=
|
|
SizeOf(BIOS))
|
|
goto NoVGAWonder;
|
|
|
|
if ((BIOS[0x00U] != 0x55U) || (BIOS[0x01U] != 0xAAU))
|
|
goto SkipBiosSegment;
|
|
|
|
if ((BIOS[0x1EU] == 'I') &&
|
|
(BIOS[0x1FU] == 'B') &&
|
|
(BIOS[0x20U] == 'M'))
|
|
break;
|
|
|
|
/* XXX Should PCI BIOS signature be checked for here ? */
|
|
if ((BIOS[0x20U] == 'P') &&
|
|
(BIOS[0x21U] == 'C') &&
|
|
(BIOS[0x22U] == 'I'))
|
|
break;
|
|
|
|
SkipBiosSegment:
|
|
if (pATI)
|
|
continue;
|
|
|
|
pATI = pVGA;
|
|
BIOSBase = 0x000C0000U - 0x00000200U;
|
|
}
|
|
|
|
pVGA->BIOSBase = BIOSBase;
|
|
|
|
/* Look for the ATI signature string */
|
|
if (memcmp(BIOS + BIOSSignature, ATISignature, SignatureSize))
|
|
break;
|
|
|
|
if (BIOS[0x40U] != '3')
|
|
break;
|
|
|
|
switch (BIOS[0x41U])
|
|
{
|
|
case '1':
|
|
/* This is a Mach8 or VGA Wonder adapter of some kind */
|
|
if ((BIOS[0x43U] >= '1') && (BIOS[0x43U] <= '6'))
|
|
pVGA->Chip = BIOS[0x43U] - ('1' - ATI_CHIP_18800);
|
|
|
|
switch (BIOS[0x43U])
|
|
{
|
|
case '1': /* ATI_CHIP_18800 */
|
|
pVGA->VGAOffset = 0xB0U;
|
|
pVGA->VGAAdapter = ATI_ADAPTER_V3;
|
|
break;
|
|
|
|
case '2': /* ATI_CHIP_18800_1 */
|
|
pVGA->VGAOffset = 0xB0U;
|
|
if (BIOS[0x42U] & 0x10U)
|
|
pVGA->VGAAdapter = ATI_ADAPTER_V5;
|
|
else
|
|
pVGA->VGAAdapter = ATI_ADAPTER_V4;
|
|
break;
|
|
|
|
case '3': /* ATI_CHIP_28800_2 */
|
|
case '4': /* ATI_CHIP_28800_4 */
|
|
case '5': /* ATI_CHIP_28800_5 */
|
|
case '6': /* ATI_CHIP_28800_6 */
|
|
pVGA->VGAOffset = 0xA0U;
|
|
if (BIOS[0x44U] & 0x80U)
|
|
pVGA->VGAAdapter = ATI_ADAPTER_XL;
|
|
else
|
|
pVGA->VGAAdapter = ATI_ADAPTER_PLUS;
|
|
break;
|
|
|
|
case 'a': /* A crippled Mach32 */
|
|
case 'b':
|
|
case 'c':
|
|
pVGA->VGAOffset = 0x80U;
|
|
pVGA->VGAAdapter = ATI_ADAPTER_NONISA;
|
|
ATIMach32ChipID(pVGA);
|
|
ProbeWaitIdleEmpty();
|
|
if (inw(SUBSYS_STAT) != (CARD16)(-1))
|
|
pVGA->ChipHasSUBSYS_CNTL = TRUE;
|
|
break;
|
|
#if 0
|
|
case ' ': /* A crippled Mach64 */
|
|
pVGA->VGAOffset = 0x80U;
|
|
pVGA->VGAAdapter = ATI_ADAPTER_NONISA;
|
|
ATIMach64ChipID(pVGA, 0);
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (pVGA->VGAAdapter == ATI_ADAPTER_NONE)
|
|
break;
|
|
|
|
/* Set VGA Wonder I/O port */
|
|
pVGA->CPIO_VGAWonder = BIOSWord(0x10U) & SPARSE_IO_PORT;
|
|
if (!pVGA->CPIO_VGAWonder)
|
|
pVGA->CPIO_VGAWonder = 0x01CEU;
|
|
|
|
ATIVGAWonderProbe(NULL, pVGA, p8514, ProbeFlags);
|
|
break;
|
|
#if 0
|
|
case '2':
|
|
pVGA->VGAOffset = 0xB0U; /* Presumably */
|
|
pVGA->VGAAdapter = ATI_ADAPTER_EGA_PLUS;
|
|
break;
|
|
|
|
case '3':
|
|
pVGA->VGAOffset = 0xB0U; /* Presumably */
|
|
pVGA->VGAAdapter = ATI_ADAPTER_BASIC;
|
|
break;
|
|
|
|
case '?': /* A crippled Mach64 */
|
|
pVGA->VGAAdapter = ATI_ADAPTER_NONISA;
|
|
ATIMach64ChipID(pVGA, 0);
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (pVGA->Adapter <= ATI_ADAPTER_VGA)
|
|
pVGA->Adapter = pVGA->VGAAdapter;
|
|
|
|
NoVGAWonder:;
|
|
} while (0);
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
/*
|
|
* Re-order list of detected devices so that the primary device is before
|
|
* any other PCI device.
|
|
*/
|
|
for (i = 0; i < nATIPtr; i++)
|
|
{
|
|
if (!ATIPtrs[i]->PCIInfo)
|
|
continue;
|
|
|
|
for (j = i; j < nATIPtr; j++)
|
|
{
|
|
pATI = ATIPtrs[j];
|
|
if (!xf86IsPrimaryPci(pATI->PCIInfo))
|
|
continue;
|
|
|
|
for (; j > i; j--)
|
|
ATIPtrs[j] = ATIPtrs[j - 1];
|
|
ATIPtrs[j] = pATI;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (flags & PROBE_DETECT)
|
|
{
|
|
/*
|
|
* No XF86Config information available, so use the default Chipset of
|
|
* "ati", and as many device sections as there are adapters.
|
|
*/
|
|
for (i = 0; i < nATIPtr; i++)
|
|
{
|
|
pATI = ATIPtrs[i];
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
if ((pATI->Adapter != ATI_ADAPTER_VGA) &&
|
|
((pATI->Adapter != ATI_ADAPTER_8514A) ||
|
|
((pATI->VGAAdapter != ATI_ADAPTER_VGA) &&
|
|
(pATI->VGAAdapter != ATI_ADAPTER_NONE))))
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
{
|
|
ProbeSuccess = TRUE;
|
|
pGDev = xf86AddDeviceToConfigure(ATI_DRIVER_NAME,
|
|
pATI->PCIInfo, ATI_CHIPSET_ATI);
|
|
if (pGDev)
|
|
{
|
|
/* Fill in additional information */
|
|
pGDev->vendor = ATI_NAME;
|
|
pGDev->chipset = (char *)ATIChipsetNames[ATI_CHIPSET_ATI];
|
|
if (!pATI->PCIInfo)
|
|
pGDev->busID = NULL;
|
|
}
|
|
}
|
|
|
|
xfree(pATI);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Assign detected devices to XF86Config Device sections. This is done
|
|
* by comparing certain Device section specifications against the
|
|
* corresponding adapter information. Begin with those specifications
|
|
* that are independent of the adapter's bus location.
|
|
*/
|
|
for (i = 0, pATIGDev = ATIGDevs; i < nATIGDev; i++, pATIGDev++)
|
|
{
|
|
pGDev = pATIGDev->pGDev;
|
|
|
|
for (j = 0; j < nATIPtr; j++)
|
|
{
|
|
pATI = ATIPtrs[j];
|
|
|
|
/*
|
|
* First check the Chipset specification. The placement of
|
|
* "break" and "continue" statements here is carefully chosen
|
|
* to produce the intended behaviour for each Chipset value.
|
|
*/
|
|
switch (pATIGDev->Chipset)
|
|
{
|
|
case ATI_CHIPSET_ATI:
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
if (pATI->Adapter == ATI_ADAPTER_VGA)
|
|
continue;
|
|
if (pATI->Adapter != ATI_ADAPTER_8514A)
|
|
break;
|
|
/* Fall through */
|
|
|
|
case ATI_CHIPSET_ATIVGA:
|
|
if (pATI->VGAAdapter == ATI_ADAPTER_VGA)
|
|
continue;
|
|
/* Fall through */
|
|
|
|
case ATI_CHIPSET_IBMVGA:
|
|
if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
|
|
continue;
|
|
break;
|
|
|
|
case ATI_CHIPSET_VGAWONDER:
|
|
if (!pATI->CPIO_VGAWonder)
|
|
continue;
|
|
break;
|
|
|
|
case ATI_CHIPSET_IBM8514:
|
|
if (pATI->Adapter == ATI_ADAPTER_8514A)
|
|
break;
|
|
/* Fall through */
|
|
|
|
case ATI_CHIPSET_MACH8:
|
|
if (pATI->Adapter == ATI_ADAPTER_MACH8)
|
|
break;
|
|
/* Fall through */
|
|
|
|
case ATI_CHIPSET_MACH32:
|
|
if (pATI->Adapter == ATI_ADAPTER_MACH32)
|
|
break;
|
|
continue;
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
case ATI_CHIPSET_MACH64:
|
|
if (pATI->Adapter == ATI_ADAPTER_MACH64)
|
|
break;
|
|
continue;
|
|
|
|
default:
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* The ChipID and ChipRev specifications are compared next.
|
|
* First, require these to be unspecified for anything other
|
|
* than Mach32 or Mach64 adapters. ChipRev is also required to
|
|
* be unspecified for Mach32's. ChipID is optional for
|
|
* Mach32's, and both specifications are optional for Mach64's.
|
|
* Lastly, allow both specifications to override their detected
|
|
* value in the case of Mach64 adapters whose ChipID is
|
|
* unrecognised.
|
|
*/
|
|
pVideo = pATI->PCIInfo;
|
|
if (pGDev->chipID >= 0)
|
|
{
|
|
if ((pATI->ChipType != pGDev->chipID) &&
|
|
(!pVideo || (pGDev->chipID != pVideo->chipType)))
|
|
{
|
|
if ((pATI->Adapter != ATI_ADAPTER_MACH64) ||
|
|
(pATI->Chip != ATI_CHIP_Mach64))
|
|
continue;
|
|
|
|
Chip = ATIChipID(pGDev->chipID, 0);
|
|
if ((Chip <= ATI_CHIP_264GTB) ||
|
|
(Chip == ATI_CHIP_Mach64))
|
|
continue;
|
|
}
|
|
if ((pGDev->chipRev >= 0) &&
|
|
(pATI->ChipRev != pGDev->chipRev) &&
|
|
(!pVideo || (pGDev->chipRev != pVideo->chipRev) ||
|
|
(pGDev->chipID != pVideo->chipType)))
|
|
{
|
|
if (pATI->Chip < ATI_CHIP_264CT)
|
|
continue;
|
|
|
|
if (pATI->Chip != ATI_CHIP_Mach64)
|
|
{
|
|
/*
|
|
* There are two foundry codes for UMC. Some
|
|
* adapters will advertise one in CONFIG_CHIP_ID
|
|
* and the other in PCI configuration space. For
|
|
* matching purposes, make both codes compare
|
|
* equal.
|
|
*/
|
|
# define UMC_IGNORE \
|
|
(ATI_FOUNDRY_UMC ^ ATI_FOUNDRY_UMCA)
|
|
# define UMC_NOCARE \
|
|
GetBits(SetBits(UMC_IGNORE, CFG_CHIP_FOUNDRY), \
|
|
CFG_CHIP_REV)
|
|
|
|
if ((pATI->ChipRev ^ pGDev->chipRev) & ~UMC_NOCARE)
|
|
continue;
|
|
|
|
if ((pATI->ChipFoundry != ATI_FOUNDRY_UMC) &&
|
|
(pATI->ChipFoundry != ATI_FOUNDRY_UMCA))
|
|
continue;
|
|
|
|
k = GetBits(pGDev->chipRev,
|
|
GetBits(CFG_CHIP_FOUNDRY, CFG_CHIP_REV));
|
|
if ((k != ATI_FOUNDRY_UMC) &&
|
|
(k != ATI_FOUNDRY_UMCA))
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* IOBase is next. This is the first specification that is
|
|
* potentially dependent on bus location. It is only allowed
|
|
* for Mach64 adapters, and is optional.
|
|
*/
|
|
if (pGDev->IOBase && (pATI->CPIOBase != pGDev->IOBase))
|
|
continue;
|
|
|
|
/*
|
|
* Compare BusID's. This specification is only allowed for PCI
|
|
* Mach32's or Mach64's and is optional.
|
|
*/
|
|
if (pGDev->busID && pGDev->busID[0])
|
|
{
|
|
pVideo = pATI->PCIInfo;
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
if (!pVideo)
|
|
continue;
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
if (!xf86ComparePciBusString(pGDev->busID,
|
|
pVideo->bus, pVideo->device, pVideo->func))
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* Ensure no two adapters are assigned to the same XF86Config
|
|
* Device section.
|
|
*/
|
|
if (pATIGDev->iATIPtr)
|
|
{
|
|
if (pATIGDev->iATIPtr < 0)
|
|
break;
|
|
|
|
xf86Msg(X_ERROR,
|
|
ATI_NAME ": XF86Config Device section \"%s\" may not"
|
|
" be assigned to more than one adapter.\n",
|
|
pGDev->identifier);
|
|
pATIGDev->iATIPtr = -1;
|
|
break;
|
|
}
|
|
|
|
/* Assign adapter */
|
|
pATIGDev->iATIPtr = j + 1;
|
|
|
|
/*
|
|
* For compatibility with previous releases, assign the first
|
|
* applicable adapter if there is only one Device section.
|
|
*/
|
|
if (nATIGDev == 1)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Ensure no two XF86Config Device sections are assigned to the same
|
|
* adapter. Then, generate screens for any that are left.
|
|
*/
|
|
for (i = 0, pATIGDev = ATIGDevs; i < nATIGDev; i++, pATIGDev++)
|
|
{
|
|
pGDev = pATIGDev->pGDev;
|
|
|
|
j = pATIGDev->iATIPtr;
|
|
if (j <= 0)
|
|
continue;
|
|
|
|
for (k = i; ++k < nATIGDev; )
|
|
{
|
|
if (j == ATIGDevs[k].iATIPtr)
|
|
{
|
|
xf86Msg(X_ERROR,
|
|
ATI_NAME ": XF86Config Device sections \"%s\" and"
|
|
" \"%s\" may not be assigned to the same adapter.\n",
|
|
pGDev->identifier, ATIGDevs[k].pGDev->identifier);
|
|
pATIGDev->iATIPtr = ATIGDevs[k].iATIPtr = -1;
|
|
}
|
|
}
|
|
|
|
j = ATIGDevs[i].iATIPtr;
|
|
if (j <= 0)
|
|
continue;
|
|
|
|
pATI = ATIPtrs[j - 1];
|
|
|
|
xf86MsgVerb(X_INFO, 3,
|
|
ATI_NAME ": %s assigned to %sactive \"Device\" section"
|
|
" \"%s\".\n",
|
|
Identifier, pGDev->active ? "" : "in", pGDev->identifier);
|
|
|
|
/*
|
|
* Attach adapter to XF86Config Device section and register its
|
|
* resources.
|
|
*/
|
|
if (ATIClaimBusSlot(pDriver, pATIGDev->Chipset,
|
|
pGDev, pGDev->active, pATI) < 0)
|
|
{
|
|
xf86Msg(X_ERROR,
|
|
ATI_NAME ": Could not claim bus slot for %s.\n",
|
|
Identifier);
|
|
continue;
|
|
}
|
|
|
|
if (!pGDev->active)
|
|
continue;
|
|
|
|
/* Allocate screen */
|
|
pScreenInfo = xf86AllocateScreen(pDriver, 0);
|
|
|
|
#ifdef XFree86LOADER
|
|
|
|
if (!xf86LoadSubModule(pScreenInfo, "atimisc"))
|
|
{
|
|
xf86Msg(X_ERROR,
|
|
ATI_NAME ": Failed to load \"atimisc\" module.\n");
|
|
xf86DeleteScreen(pScreenInfo->scrnIndex, 0);
|
|
continue;
|
|
}
|
|
|
|
xf86LoaderReqSymLists(ATISymbols, NULL);
|
|
|
|
#endif
|
|
|
|
/* Attach device to screen */
|
|
xf86AddEntityToScreen(pScreenInfo, pATI->iEntity);
|
|
|
|
ATIPtrs[j - 1] = NULL;
|
|
|
|
/* Fill in probe data */
|
|
ATIFillInScreenInfo(pScreenInfo);
|
|
|
|
pScreenInfo->driverPrivate = pATI;
|
|
|
|
pATI->Chipset = pATIGDev->Chipset;
|
|
|
|
ProbeSuccess = TRUE;
|
|
}
|
|
|
|
/* Deal with unassigned adapters */
|
|
for (i = 0; i < nATIPtr; i++)
|
|
{
|
|
if (!(pATI = ATIPtrs[i]))
|
|
continue;
|
|
|
|
#ifndef AVOID_CPIO
|
|
|
|
if (pATI->Adapter > ATI_ADAPTER_VGA)
|
|
|
|
#endif /* AVOID_CPIO */
|
|
|
|
{
|
|
if (pATI->iEntity < 0)
|
|
(void)ATIClaimBusSlot(pDriver, 0, NULL, FALSE, pATI);
|
|
}
|
|
|
|
xfree(pATI);
|
|
}
|
|
|
|
xfree(ATIGDevs);
|
|
}
|
|
|
|
xfree(ATIPtrs);
|
|
|
|
/* Call Rage 128 driver probe */
|
|
if (DoRage128 && R128Probe(pDriver, flags))
|
|
ProbeSuccess = TRUE;
|
|
|
|
/* Call Radeon driver probe */
|
|
if (DoRadeon && RADEONProbe(pDriver, flags))
|
|
ProbeSuccess = TRUE;
|
|
|
|
return ProbeSuccess;
|
|
}
|