📄 atiprobe.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 voidATIScanPCIBases( 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 CARD8ATICheckSparseIOBases( 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 voidATIClaimSparseIOBases( 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 ATIPtrATIVGAProbe( 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 voidATIVGAWonderProbe( 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 ATIPtrATI8514Probe( 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -