#include "ati.h"
#include "atiadapter.h"
#include "atiadjust.h"
#include "atibus.h"
#include "atichip.h"
#include "aticonsole.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"
#ifdef XFree86LOADER
static xf86PreInitProc * const volatile PreInitProc = ATIPreInit;
static xf86ScreenInitProc * const volatile ScreenInitProc = ATIScreenInit;
static xf86SwitchModeProc * const volatile SwitchModeProc = ATISwitchMode;
static xf86AdjustFrameProc * const volatile AdjustFrameProc = ATIAdjustFrame;
static xf86EnterVTProc * const volatile EnterVTProc = ATIEnterVT;
static xf86LeaveVTProc * const volatile LeaveVTProc = ATILeaveVT;
static xf86FreeScreenProc * const volatile FreeScreenProc = ATIFreeScreen;
static xf86ValidModeProc * const volatile ValidModeProc = ATIValidMode;
#define ATIPreInit PreInitProc
#define ATIScreenInit ScreenInitProc
#define ATISwitchMode SwitchModeProc
#define ATIAdjustFrame AdjustFrameProc
#define ATIEnterVT EnterVTProc
#define ATILeaveVT LeaveVTProc
#define ATIFreeScreen FreeScreenProc
#define ATIValidMode ValidModeProc
#endif
#define Identifier ((char *)(pATI->MMIOCache))
typedef struct _ATIGDev
{
GDevPtr pGDev;
int iATIPtr;
CARD8 Chipset;
} ATIGDev, *ATIGDevPtr;
#ifndef AVOID_CPIO
#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;
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;
}
if (!PCI_MAP_IS64BITMEM(*pBase))
continue;
i--;
pBase++;
pSize++;
}
}
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;
xf86Msg(X_WARNING,
ATI_NAME ": Sparse I/O base 0x%04lX not probed.\n", IOBase);
return Allowed;
}
}
return DoProbe;
}
#ifndef AVOID_NON_PCI
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
static ATIPtr
ATIVGAProbe
(
ATIPtr pVGA
)
{
CARD8 IOValue1, IOValue2, IOValue3;
if (!pVGA)
pVGA = (ATIPtr)xnfcalloc(1, SizeOf(ATIRec));
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))
{
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;
}
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:
if (pVideo && !xf86IsPrimaryPci(pVideo) &&
(pATI->Chip <= ATI_CHIP_88800GXD))
{
PutReg(GRAX, 0x50U, GetByte(pATI->CPIO_VGAWonder, 0));
PutReg(GRAX, 0x51U,
GetByte(pATI->CPIO_VGAWonder, 1) | pATI->VGAOffset);
}
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;
}
}
static ATIPtr
ATI8514Probe
(
pciVideoPtr pVideo
)
{
ATIPtr pATI = NULL;
CARD16 IOValue1, IOValue2;
IOValue1 = inw(SUBSYS_STAT);
IOValue2 = IOValue1 & _8PLANE;
outw(SUBSYS_CNTL, IOValue2 | (GPCTRL_RESET | CHPTEST_NORMAL));
outw(SUBSYS_CNTL, IOValue2 | (GPCTRL_ENAB | CHPTEST_NORMAL |
RVBLNKFLG | RPICKFLAG | RINVALIDIO | RGPIDLE));
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);
if (!pATI)
{
outw(SUBSYS_CNTL, IOValue1);
return NULL;
}
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)
{
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
static Bool
ATIMach64Detect
(
ATIPtr pATI,
const CARD16 ChipType,
const ATIChipType Chip
)
{
CARD32 IOValue, bus_cntl, gen_test_cntl;
(void)ATIMapApertures(-1, pATI);
#ifdef AVOID_CPIO
if (!pATI->pBlock[0])
{
ATIUnmapApertures(-1, pATI);
return FALSE;
}
#endif
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);
IOValue = inr(SCRATCH_REG0);
outr(SCRATCH_REG0, 0x55555555U);
if (inr(SCRATCH_REG0) == 0x55555555U)
{
outr(SCRATCH_REG0, 0xAAAAAAAAU);
if (inr(SCRATCH_REG0) == 0xAAAAAAAAU)
{
ATIMach64ChipID(pATI, ChipType);
if ((pATI->Chip != ATI_CHIP_Mach64) ||
(pATI->CPIODecoding == BLOCK_IO))
pATI->Adapter = ATI_ADAPTER_MACH64;
}
}
outr(SCRATCH_REG0, IOValue);
if (pATI->Adapter != ATI_ADAPTER_MACH64)
{
outr(GEN_TEST_CNTL, gen_test_cntl);
outr(BUS_CNTL, bus_cntl);
ATIUnmapApertures(-1, pATI);
return FALSE;
}
pATI->BIOSBase = 0x000C0000U +
(GetBits(inr(SCRATCH_REG1), BIOS_BASE_SEGMENT) << 11);
ATIUnmapApertures(-1, pATI);
pATI->PCIInfo = NULL;
return TRUE;
}
#ifdef AVOID_CPIO
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;
if ((pVideo->size[2] >= 12) &&
(pATI->Block0Base = pVideo->memBase[2]) &&
(pATI->Block0Base < (CARD32)(-1 << pVideo->size[2])))
{
pATI->Block0Base += 0x00000400U;
goto LastProbe;
}
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;
}
}
pATI->Block0Base = 0x000BFC00U;
LastProbe:
if (ATIMach64Detect(pATI, ChipType, Chip))
return pATI;
xfree(pATI);
return NULL;
}
#else
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;
}
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;
}
static void
ATIAssignVGA
(
pciVideoPtr pVideo,
ATIPtr *ppVGA,
ATIPtr pATI,
ATIPtr p8514,
CARD8 *ProbeFlags
)
{
ATIPtr pVGA = *ppVGA;
CARD8 OldDACMask;
pATI->VGAAdapter = ATI_ADAPTER_NONE;
if ((pATI != pVGA) && (!pVGA || (pVGA->Adapter > ATI_ADAPTER_VGA)))
return;
switch (pATI->Adapter)
{
case ATI_ADAPTER_8514A:
{
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)
{
pATI->CPIO_VGAWonder = GRAX;
ATIVGAWonderProbe(pVideo, pATI, p8514, ProbeFlags);
}
}
if (pATI == pVGA)
{
pATI->SharedVGA = TRUE;
return;
}
xfree(pVGA);
*ppVGA = pATI;
xf86MsgVerb(X_INFO, 3, ATI_NAME ": VGA assigned to this adapter.\n");
}
#ifndef AVOID_NON_PCI
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
static void
ATIFindVGA
(
pciVideoPtr pVideo,
ATIPtr *ppVGA,
ATIPtr *ppATI,
ATIPtr p8514,
CARD8 *ProbeFlags
)
{
ATIPtr pATI = *ppATI;
if (!*ppVGA)
{
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
Bool
ATIProbe
(
DriverPtr pDriver,
int flags
)
{
ATIPtr pATI, *ATIPtrs = NULL;
GDevPtr *GDevs, pGDev;
pciVideoPtr pVideo, *xf86PciVideoInfo = xf86GetPciVideoInfo();
pciConfigPtr pPCI;
ATIGDev *ATIGDevs = NULL, *pATIGDev;
ScrnInfoPtr pScreenInfo;
CARD32 PciReg;
Bool ProbeSuccess = FALSE;
Bool DoRage128 = FALSE, DoRadeon = FALSE;
int i, j, k;
int nGDev, nATIGDev = -1, nATIPtr = 0;
int Chipset;
ATIChipType Chip;
#ifndef AVOID_CPIO
ATIPtr pVGA = NULL, p8514 = NULL;
ATIPtr pMach64[3] = {NULL, NULL, 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
# 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
if (!(flags & PROBE_DETECT))
{
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
}
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
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);
}
}
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);
}
}
(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;
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
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
{
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");
}
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");
}
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
}
#endif
if (xf86PciVideoInfo)
{
if (nATIGDev)
{
#ifndef AVOID_NON_PCI
#ifdef AVOID_CPIO
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);
if (PciReg & 0x00000004U)
pciWriteLong(pPCI->tag, PCI_REG_USERCONFIG,
PciReg & ~0x00000004U);
Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
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
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
{
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
(pVideo->chipType == PCI_CHIP_MACH32) ||
!pVideo->size[1])
continue;
Chip = ATIChipID(pVideo->chipType, pVideo->chipRev);
if ((Chip > ATI_CHIP_Mach64) ||
!(pPCI = pVideo->thisCard))
continue;
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
if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
ATIClaimVGA(pVideo, &pVGA, pATI, p8514,
ProbeFlags, DetectedMach64);
#endif
}
#endif
#ifndef AVOID_CPIO
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);
}
}
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
default:
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;
}
}
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
{
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
(pVideo->chipType == PCI_CHIP_MACH32) ||
pVideo->size[1])
continue;
pPCI = pVideo->thisCard;
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
default:
if (!xf86CheckPciSlot(pVideo->bus,
pVideo->device,
pVideo->func))
continue;
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
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
{
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
(pVideo->chipType == PCI_CHIP_MACH32) ||
pVideo->size[1])
continue;
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);
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
}
for (i = 0; (pVideo = xf86PciVideoInfo[i++]); )
{
if ((pVideo->vendor != PCI_VENDOR_ATI) ||
(pVideo->chipType == PCI_CHIP_MACH32) ||
!pVideo->size[1])
continue;
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;
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;
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
}
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
do
{
if (!nATIGDev || !pVGA || (pVGA->VGAAdapter > ATI_ADAPTER_VGA))
break;
if (pVGA->Coprocessor == ATI_CHIP_NONE)
AddAdapter(pVGA);
if (xf86ReadBIOS(0U, 0x42U, BIOS, 2) != 2)
goto NoVGAWonder;
pATI = NULL;
BIOSBase = 0;
if (!(BIOS[0] & 0x1FU))
BIOSBase = ((BIOS[1] << 8) | BIOS[0]) << 4;
for(; ; BIOSBase += 0x00000200U)
{
if (!BIOSBase)
goto SkipBiosSegment;
if (BIOSBase >= 0x000F8000U)
goto NoVGAWonder;
for (i = 0; i < nATIPtr; i++)
if (ATIPtrs[i]->BIOSBase == BIOSBase)
goto SkipBiosSegment;
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;
if ((BIOS[0x20U] == 'P') &&
(BIOS[0x21U] == 'C') &&
(BIOS[0x22U] == 'I'))
break;
SkipBiosSegment:
if (pATI)
continue;
pATI = pVGA;
BIOSBase = 0x000C0000U - 0x00000200U;
}
pVGA->BIOSBase = BIOSBase;
if (memcmp(BIOS + BIOSSignature, ATISignature, SignatureSize))
break;
if (BIOS[0x40U] != '3')
break;
switch (BIOS[0x41U])
{
case '1':
if ((BIOS[0x43U] >= '1') && (BIOS[0x43U] <= '6'))
pVGA->Chip = BIOS[0x43U] - ('1' - ATI_CHIP_18800);
switch (BIOS[0x43U])
{
case '1':
pVGA->VGAOffset = 0xB0U;
pVGA->VGAAdapter = ATI_ADAPTER_V3;
break;
case '2':
pVGA->VGAOffset = 0xB0U;
if (BIOS[0x42U] & 0x10U)
pVGA->VGAAdapter = ATI_ADAPTER_V5;
else
pVGA->VGAAdapter = ATI_ADAPTER_V4;
break;
case '3':
case '4':
case '5':
case '6':
pVGA->VGAOffset = 0xA0U;
if (BIOS[0x44U] & 0x80U)
pVGA->VGAAdapter = ATI_ADAPTER_XL;
else
pVGA->VGAAdapter = ATI_ADAPTER_PLUS;
break;
case 'a':
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 ' ':
pVGA->VGAOffset = 0x80U;
pVGA->VGAAdapter = ATI_ADAPTER_NONISA;
ATIMach64ChipID(pVGA, 0);
break;
#endif
default:
break;
}
if (pVGA->VGAAdapter == ATI_ADAPTER_NONE)
break;
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;
pVGA->VGAAdapter = ATI_ADAPTER_EGA_PLUS;
break;
case '3':
pVGA->VGAOffset = 0xB0U;
pVGA->VGAAdapter = ATI_ADAPTER_BASIC;
break;
case '?':
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
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)
{
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
{
ProbeSuccess = TRUE;
pGDev = xf86AddDeviceToConfigure(ATI_DRIVER_NAME,
pATI->PCIInfo, ATI_CHIPSET_ATI);
if (pGDev)
{
pGDev->vendor = ATI_NAME;
pGDev->chipset = (char *)ATIChipsetNames[ATI_CHIPSET_ATI];
if (!pATI->PCIInfo)
pGDev->busID = NULL;
}
}
xfree(pATI);
}
}
else
{
for (i = 0, pATIGDev = ATIGDevs; i < nATIGDev; i++, pATIGDev++)
{
pGDev = pATIGDev->pGDev;
for (j = 0; j < nATIPtr; j++)
{
pATI = ATIPtrs[j];
switch (pATIGDev->Chipset)
{
case ATI_CHIPSET_ATI:
#ifndef AVOID_CPIO
if (pATI->Adapter == ATI_ADAPTER_VGA)
continue;
if (pATI->Adapter != ATI_ADAPTER_8514A)
break;
case ATI_CHIPSET_ATIVGA:
if (pATI->VGAAdapter == ATI_ADAPTER_VGA)
continue;
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;
case ATI_CHIPSET_MACH8:
if (pATI->Adapter == ATI_ADAPTER_MACH8)
break;
case ATI_CHIPSET_MACH32:
if (pATI->Adapter == ATI_ADAPTER_MACH32)
break;
continue;
#endif
case ATI_CHIPSET_MACH64:
if (pATI->Adapter == ATI_ADAPTER_MACH64)
break;
continue;
default:
continue;
}
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)
{
# 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;
}
}
}
if (pGDev->IOBase && (pATI->CPIOBase != pGDev->IOBase))
continue;
if (pGDev->busID && pGDev->busID[0])
{
pVideo = pATI->PCIInfo;
#ifndef AVOID_CPIO
if (!pVideo)
continue;
#endif
if (!xf86ComparePciBusString(pGDev->busID,
pVideo->bus, pVideo->device, pVideo->func))
continue;
}
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;
}
pATIGDev->iATIPtr = j + 1;
if (nATIGDev == 1)
break;
}
}
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);
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;
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
xf86AddEntityToScreen(pScreenInfo, pATI->iEntity);
ATIPtrs[j - 1] = NULL;
pScreenInfo->driverVersion = ATI_VERSION_CURRENT;
pScreenInfo->driverName = ATI_DRIVER_NAME;
pScreenInfo->name = ATI_NAME;
pScreenInfo->Probe = ATIProbe;
pScreenInfo->PreInit = ATIPreInit;
pScreenInfo->ScreenInit = ATIScreenInit;
pScreenInfo->SwitchMode = ATISwitchMode;
pScreenInfo->AdjustFrame = ATIAdjustFrame;
pScreenInfo->EnterVT = ATIEnterVT;
pScreenInfo->LeaveVT = ATILeaveVT;
pScreenInfo->FreeScreen = ATIFreeScreen;
pScreenInfo->ValidMode = ATIValidMode;
pScreenInfo->driverPrivate = pATI;
pATI->Chipset = pATIGDev->Chipset;
ProbeSuccess = TRUE;
}
for (i = 0; i < nATIPtr; i++)
{
if (!(pATI = ATIPtrs[i]))
continue;
#ifndef AVOID_CPIO
if (pATI->Adapter > ATI_ADAPTER_VGA)
#endif
{
if (pATI->iEntity < 0)
(void)ATIClaimBusSlot(pDriver, 0, NULL, FALSE, pATI);
}
xfree(pATI);
}
xfree(ATIGDevs);
}
xfree(ATIPtrs);
if (DoRage128 && R128Probe(pDriver, flags))
ProbeSuccess = TRUE;
if (DoRadeon && RADEONProbe(pDriver, flags))
ProbeSuccess = TRUE;
return ProbeSuccess;
}