/* $XFree86: xc/programs/Xserver/hw/xfree86/SuperProbe/ATI.c,v 3.11.2.6 1999/10/12 17:18:35 hohndel Exp $ */
/*
* (c) Copyright 1993,1994 by David Wexelblat <dwex@xfree86.org>
*
* 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 0x00CB:
case 0x00CC:
case 0x00CD:
case 0x00CE:
case 0x00D1:
case 0x00D2:
case 0x474C:
case 0x474D:
case 0x474E:
case 0x474F:
case 0x4752:
case 0x4753:
Mach64xTB = TRUE;
*Chipset = CHIP_ATI264XL;
break;
case 0x016C:
case 0x016D:
case 0x0171:
case 0x0172:
case 0x4C4D:
case 0x4C4E:
case 0x4C52:
case 0x4C53:
Mach64xTB = TRUE;
*Chipset = CHIP_ATIMOBILITY;
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);
}