/* $XFree86: xc/programs/Xserver/hw/xfree86/SuperProbe/ATIMach.c,v 3.9.2.2 1997/05/22 14:00:33 dawes Exp $ */ /* * (c) Copyright 1993,1994 by David Wexelblat * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * DAVID WEXELBLAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of David Wexelblat shall not be * used in advertising or otherwise to promote the sale, use or other dealings * in this Software without prior written authorization from David Wexelblat. * */ /* $XConsortium: ATIMach.c /main/10 1996/10/25 07:00:15 kaleb $ */ #include "Probe.h" static Word Ports[] = {ROM_ADDR_1, DESTX_DIASTP, READ_SRC_X, CONFIG_STATUS_1, MISC_OPTIONS, GP_STAT}; #define NUMPORTS (sizeof(Ports)/sizeof(Word)) static int MemProbe_ATIMach __STDCARGS((int)); extern void Probe_ATI_ChipID __STDCARGS((int, int *)); Chip_Descriptor ATIMach_Descriptor = { "ATI_Mach", Probe_ATIMach, Ports, NUMPORTS, TRUE, FALSE, FALSE, MemProbe_ATIMach, }; #define WaitIdleEmpty() { int i; \ for (i=0; i < 100000; i++) \ if (!(inpw(GP_STAT) & (GPBUSY | 1))) \ break; \ } /* ATI Mach64 I/O port addresses */ Word ATIMach64MEM_INFO, ATIMach64SCRATCH_REG1, ATIMach64DAC_CNTL, ATIMach64CONFIG_CHIP_ID; #ifdef __STDC__ static void Probe_ATIMach64(int *Chipset, unsigned short int IOBase, Bool SparseIO) #else static void Probe_ATIMach64(Chipset, IOBase, SparseIO) int *Chipset; unsigned short int IOBase; Bool SparseIO; #endif { Long tmp; Word IOPort; int chip; if ((*Chipset != -1) || (IOBase == 0)) return; /* Determine if a Mach64 answers the call */ IOPort = (SparseIO ? 0x4000 : 0x0080) + IOBase; EnableIOPorts(1, &IOPort); tmp = inpl(IOPort); outpl(IOPort, 0x55555555); /* Test odd bits */ if (inpl(IOPort) == 0x55555555) { outpl(IOPort, 0xAAAAAAAA); /* Test even bits */ if (inpl(IOPort) == 0xAAAAAAAA) { /* * Fix I/O ports. I know, I know: hard-wired * constants are *EVIL*, but this'll do for now. */ if (SparseIO) { ATIMach64SCRATCH_REG1 = 0x4400; ATIMach64MEM_INFO = 0x5000; ATIMach64DAC_CNTL = 0x6000; ATIMach64CONFIG_CHIP_ID = 0x6C00; } else { ATIMach64SCRATCH_REG1 = 0x0084; ATIMach64MEM_INFO = 0x00B0; ATIMach64DAC_CNTL = 0x00C4; ATIMach64CONFIG_CHIP_ID = 0x00E0; } ATIMach64SCRATCH_REG1 += IOBase; ATIMach64MEM_INFO += IOBase; ATIMach64DAC_CNTL += IOBase; ATIMach64CONFIG_CHIP_ID += IOBase; /* * Something's responding to our hail. Make sure it's * a Mach64. This assumes ATI won't be producing any * more adapters that don't register themselves in PCI * configuration space. */ Probe_ATI_ChipID(CHIP_MACH64, &chip); if ((chip == CHIP_ATI_UNK) && SparseIO) Chip_data = (Long)~0; else *Chipset = CHIP_MACH64; } } outpl(IOPort, tmp); DisableIOPorts(1, &IOPort); } #ifdef __STDC__ Bool Probe_ATIMach(int *Chipset) #else Bool Probe_ATIMach(Chipset) int *Chipset; #endif { Long tmp; static int chip = -1; static Bool Already_Called = FALSE; struct pci_config_reg *PCIDevice; int Index; if (Already_Called) { if (chip != -1) *Chipset = chip; return (chip != -1); } Already_Called = TRUE; EnableIOPorts(NUMPORTS, Ports); /* * Check for 8514/A registers. Don't read BIOS, or an attached 8514 * Ultra won't be detected (the slave SVGA's BIOS is in the normal SVGA * place). */ tmp = inpw(ROM_ADDR_1); outpw(ROM_ADDR_1, 0x5555); WaitIdleEmpty(); if (inpw(ROM_ADDR_1) == 0x5555) { outpw(ROM_ADDR_1, 0x2A2A); WaitIdleEmpty(); if (inpw(ROM_ADDR_1) == 0x2A2A) chip = CHIP_8514; } outpw(ROM_ADDR_1, tmp); if (chip != -1) { /* * An 8514 accelerator is really present; now figure * out which one. */ outpw(DESTX_DIASTP, 0xAAAA); WaitIdleEmpty(); if (inpw(READ_SRC_X) != 0x02AA) chip = CHIP_MACH8; else chip = CHIP_MACH32; outpw(DESTX_DIASTP, 0x5555); WaitIdleEmpty(); if (inpw(READ_SRC_X) != 0x0555) { if (chip != CHIP_MACH8) /* * Something bizarre is happening. */ chip = -1; } else { if (chip != CHIP_MACH32) /* * Something bizarre is happening. */ chip = -1; } } DisableIOPorts(NUMPORTS, Ports); if (chip == -1) { /* * Check for a Mach64. Start with sparse I/O base addresses, * then move on to PCI information. */ Probe_ATIMach64(&chip, 0x02EC, TRUE); Probe_ATIMach64(&chip, 0x01CC, TRUE); Probe_ATIMach64(&chip, 0x01C8, TRUE); Index = 0; while ((chip == -1) && (PCIDevice = pci_devp[Index++])) { if (PCIDevice->_vendor != PCI_VENDOR_ATI) continue; if (PCIDevice->_device == PCI_CHIP_MACH32) continue; Probe_ATIMach64(&chip, PCIDevice->_base1 & 0xFF00, FALSE); } } if (chip != -1) { *Chipset = chip; } return(chip != -1); } #ifdef __STDC__ static int MemProbe_ATIMach(int Chipset) #else static int MemProbe_ATIMach(Chipset) int Chipset; #endif { static int Mem = 0; static Bool Already_Called = FALSE; if (Already_Called) return (Mem); Already_Called = TRUE; EnableIOPorts(NUMPORTS, Ports); if (Chipset == CHIP_MACH8) { if (inpw(CONFIG_STATUS_1) & 0x0020) { Mem = 1024; } else { Mem = 512; } } else if (Chipset == CHIP_MACH32) { switch ((inpw(MISC_OPTIONS) & 0x000C) >> 2) { case 0x00: Mem = 512; break; case 0x01: Mem = 1024; break; case 0x02: Mem = 2048; break; case 0x03: Mem = 4096; break; } } else if (Chipset == CHIP_MACH64) { extern Bool Mach64xTB; int tmp; EnableIOPorts(1, &ATIMach64MEM_INFO); tmp = inpl(ATIMach64MEM_INFO); if (!Mach64xTB) { switch (tmp & 0x00000007) { case 0x00: Mem = 512; break; case 0x01: Mem = 1024; break; case 0x02: Mem = 2048; break; case 0x03: Mem = 4096; break; case 0x04: Mem = 6144; break; case 0x05: Mem = 8192; break; case 0x06: Mem = 12288; break; case 0x07: Mem = 16384; break; } } else { if ((tmp &= 0x0000000F) < 8) Mem = (tmp + 1) * 512; else if (tmp < 12) Mem = (tmp - 3) * 1024; else Mem = (tmp - 7) * 2048; } DisableIOPorts(1, &ATIMach64MEM_INFO); } DisableIOPorts(NUMPORTS, Ports); return(Mem); }