/* $XFree86: xc/programs/Xserver/hw/xfree86/SuperProbe/ATI.c,v 3.18 1999/06/06 08:48:42 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: ATI.c /main/10 1996/10/25 07:00:11 kaleb $ */ #include "Probe.h" static Word Ports[] = {0x01CE, 0x01CF}; #define NUMPORTS (sizeof(Ports)/sizeof(Word)) static int MemProbe_ATI __STDCARGS((int)); Chip_Descriptor ATI_Descriptor = { "ATI", Probe_ATI, Ports, NUMPORTS, TRUE, TRUE, TRUE, MemProbe_ATI, }; Bool Crippled_Mach32 = FALSE, Crippled_Mach64 = FALSE, Mach64xTB = FALSE; extern Chip_Descriptor ATIMach_Descriptor; #ifdef __STDC__ void Probe_ATI_ChipID(int chip, int *Chipset) #else void Probe_ATI_ChipID(chip, Chipset) int chip, *Chipset; #endif { if (chip == CHIP_MACH64) { extern Word ATIMach64CONFIG_CHIP_ID; EnableIOPorts(1, &ATIMach64CONFIG_CHIP_ID); chip = inpl(ATIMach64CONFIG_CHIP_ID); switch (chip & 0xFFFF) { case 0x00D7: case 0x4758: switch ((chip & 0xFF000000) >> 24) { case 0x00: *Chipset = CHIP_ATI88800GXC; break; case 0x01: *Chipset = CHIP_ATI88800GXD; break; case 0x02: *Chipset = CHIP_ATI88800GXE; break; case 0x03: *Chipset = CHIP_ATI88800GXF; break; default: Chip_data = chip; *Chipset = CHIP_ATI_UNK; break; } break; case 0x0057: case 0x4358: *Chipset = CHIP_ATI88800CX; break; case 0x0053: case 0x4354: *Chipset = CHIP_ATI264CT; break; case 0x0093: case 0x4554: *Chipset = CHIP_ATI264ET; break; case 0x02B3: case 0x5654: if (chip & 0x07000000) { Mach64xTB = TRUE; *Chipset = CHIP_ATI264VTB; } else *Chipset = CHIP_ATI264VT; break; case 0x02B4: case 0x5655: Mach64xTB = TRUE; *Chipset = CHIP_ATI264VT3; break; case 0x02B5: case 0x5656: Mach64xTB = TRUE; *Chipset = CHIP_ATI264VT4; break; case 0x00D3: case 0x4754: if (chip & 0x07000000) { Mach64xTB = TRUE; *Chipset = CHIP_ATI264GTB; } else *Chipset = CHIP_ATI264GT; break; case 0x00D4: case 0x4755: Mach64xTB = TRUE; *Chipset = CHIP_ATI264GTDVD; break; case 0x00D5: case 0x00D6: case 0x00D9: case 0x4756: case 0x4757: case 0x475A: Mach64xTB = TRUE; *Chipset = CHIP_ATI264GTIIc; break; case 0x00C1: case 0x00C3: case 0x00C8: case 0x00CF: case 0x00D0: case 0x4742: case 0x4744: case 0x4749: case 0x4750: case 0x4751: Mach64xTB = TRUE; *Chipset = CHIP_ATI264GT3; break; case 0x0166: case 0x4C47: Mach64xTB = TRUE; *Chipset = CHIP_ATI264LT; break; case 0x0161: case 0x0163: case 0x0168: case 0x016F: case 0x4C42: case 0x4C44: case 0x4C49: case 0x4C50: Mach64xTB = TRUE; *Chipset = CHIP_ATI264LTPRO; break; case 0x00CC: case 0x00CD: case 0x00CE: case 0x00D1: case 0x00D2: case 0x474D: case 0x474E: case 0x474F: case 0x4752: case 0x4753: Mach64xTB = TRUE; *Chipset = CHIP_ATI264XL; break; default: Chip_data = chip; Mach64xTB = TRUE; /* Most likely */ *Chipset = CHIP_ATI_UNK; break; } DisableIOPorts(1, &ATIMach64CONFIG_CHIP_ID); } else /* if (chip == CHIP_MACH32) */ { Word IOPort = CHIP_ID; EnableIOPorts(1, &IOPort); chip = inpw(CHIP_ID); if (chip == 0xFFFF) chip = 0; switch (chip & 0x03FF) { case 0x0000: *Chipset = CHIP_ATI68800_3; break; case 0x02F7: *Chipset = CHIP_ATI68800_6; break; case 0x0177: *Chipset = CHIP_ATI68800LX; break; case 0x0017: *Chipset = CHIP_ATI68800AX; break; default: Chip_data = chip; *Chipset = CHIP_ATI_UNK; break; } DisableIOPorts(1, &IOPort); } } #ifdef __STDC__ Bool Probe_ATI(int *Chipset) #else Bool Probe_ATI(Chipset) int *Chipset; #endif { Bool result = FALSE; Byte bios[10]; Byte *signature = (Byte *)"761295520"; int chip; /* * First, look for a Mach32 or a Mach64. */ if (ATIMach_Descriptor.f(&chip) && ((chip == CHIP_MACH32) || (chip == CHIP_MACH64))) { Probe_ATI_ChipID(chip, Chipset); return (TRUE); } if (ReadBIOS(0x31, bios, 9) != 9) { fprintf(stderr, "%s: Failed to read ATI signature\n", MyName); return(FALSE); } if (memcmp(bios, signature, 9) == 0) { if (ReadBIOS(0x40, bios, 4) != 4) { fprintf(stderr, "%s: Failed to read ATI BIOS data\n", MyName); return(FALSE); } result = TRUE; if ((bios[0] == '3') && (bios[1] == '1')) { /* Set up Ports array */ if (ReadBIOS(0x10, bios, sizeof(Word)) != sizeof(Word)) { fprintf(stderr, "%s: Failed to read ATI BIOS data\n", MyName); return (FALSE); } switch (bios[3]) { case '1': *Chipset = CHIP_ATI18800; break; case '2': *Chipset = CHIP_ATI18800_1; break; case '3': *Chipset = CHIP_ATI28800_2; break; case '4': *Chipset = CHIP_ATI28800_4; break; case '5': *Chipset = CHIP_ATI28800_5; break; case '6': *Chipset = CHIP_ATI28800_6; break; case 'a': case 'b': case 'c': Crippled_Mach32 = TRUE; Probe_ATI_ChipID(CHIP_MACH32, Chipset); break; case ' ': Crippled_Mach64 = TRUE; Probe_ATI_ChipID(CHIP_MACH64, Chipset); break; default: Chip_data = (((((bios[0] << 8) | bios[1]) << 8) | bios[2]) << 8) | bios[3]; *Chipset = CHIP_ATI_UNK; break; } if (!Crippled_Mach64) { Ports[0] = *((Word *)bios); Ports[1] = Ports[0] + 1; } /* * Sometimes, the BIOS lies about the chip. */ if ((*Chipset >= CHIP_ATI28800_4) && (*Chipset <= CHIP_ATI28800_6)) { EnableIOPorts(NUMPORTS, Ports); chip = rdinx(Ports[0], 0xAA) & 0x0F; if (chip < 7) { chip = SVGA_TYPE(V_ATI, chip); if (chip > *Chipset) *Chipset = chip; } DisableIOPorts(NUMPORTS, Ports); } } else { Chip_data = (((((bios[0] << 8) | bios[1]) << 8) | bios[2]) << 8) | bios[3]; *Chipset = CHIP_ATI_UNK; } } return(result); } static int MemProbe_ATI(Chipset) int Chipset; { int Mem = 0; if ((Chipset >= CHIP_ATI88800GXC) && !Crippled_Mach64) return (ATIMach_Descriptor.memcheck(CHIP_MACH64)); if ((Chipset >= CHIP_ATI68800_3) && !Crippled_Mach32) return (ATIMach_Descriptor.memcheck(CHIP_MACH32)); /* Ports array should already be set up */ EnableIOPorts(NUMPORTS, Ports); if (Crippled_Mach32) Chipset = CHIP_MACH32; else if (Crippled_Mach64) Chipset = CHIP_MACH64; switch (Chipset) { case CHIP_ATI18800: case CHIP_ATI18800_1: if (rdinx(Ports[0], 0xBB) & 0x20) Mem = 512; else Mem = 256; break; case CHIP_ATI28800_2: case CHIP_ATI28800_4: case CHIP_ATI28800_5: case CHIP_ATI28800_6: case CHIP_MACH32: case CHIP_MACH64: switch (rdinx(Ports[0], 0xB0) & 0x18) { case 0x00: Mem = 256; break; case 0x10: Mem = 512; break; case 0x08: case 0x18: Mem = 1024; break; } break; } DisableIOPorts(NUMPORTS, Ports); return(Mem); }