2008-06-26 20:19:47 +02:00
|
|
|
|
2008-10-19 17:53:12 +02:00
|
|
|
#include "ati_pciids_gen.h"
|
|
|
|
#include "radeon_chipset_gen.h"
|
|
|
|
#include "radeon_chipinfo_gen.h"
|
2008-06-26 20:19:47 +02:00
|
|
|
|
2008-07-01 11:36:00 +02:00
|
|
|
|
|
|
|
|
2008-06-26 20:19:47 +02:00
|
|
|
const char *
|
|
|
|
xf86TokenToString(SymTabPtr table, int token)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; table[i].token >= 0 && table[i].token != token; i++){};
|
|
|
|
|
|
|
|
if (table[i].token < 0)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return(table[i].name);
|
|
|
|
}
|
|
|
|
|
2008-10-19 17:53:12 +02:00
|
|
|
|
|
|
|
|
|
|
|
const RADEONCardInfo *RadeonDevMatch(u16_t dev,const RADEONCardInfo *list)
|
|
|
|
{
|
|
|
|
while(list->pci_device_id)
|
|
|
|
{
|
|
|
|
if(dev == list->pci_device_id)
|
|
|
|
return list;
|
|
|
|
list++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-26 20:19:47 +02:00
|
|
|
RHDPtr FindPciDevice()
|
|
|
|
{
|
2009-01-27 01:31:09 +01:00
|
|
|
const RADEONCardInfo *dev;
|
|
|
|
u32_t bus, last_bus;
|
2008-06-26 20:19:47 +02:00
|
|
|
|
2009-01-27 01:31:09 +01:00
|
|
|
if( (last_bus = PciApi(1))==-1)
|
|
|
|
return 0;
|
2008-06-26 20:19:47 +02:00
|
|
|
|
2009-01-27 01:31:09 +01:00
|
|
|
for(bus=0;bus<=last_bus;bus++)
|
2008-06-26 20:19:47 +02:00
|
|
|
{
|
2009-01-27 01:31:09 +01:00
|
|
|
u32_t devfn;
|
2008-10-19 17:53:12 +02:00
|
|
|
|
2009-01-27 01:31:09 +01:00
|
|
|
for(devfn=0;devfn<256;devfn++)
|
2008-10-19 17:53:12 +02:00
|
|
|
{
|
2009-01-27 01:31:09 +01:00
|
|
|
u32_t id;
|
|
|
|
id = PciRead32(bus,devfn, 0);
|
2008-06-26 20:19:47 +02:00
|
|
|
|
2009-01-27 01:31:09 +01:00
|
|
|
if( (u16_t)id != VENDOR_ATI)
|
|
|
|
continue;
|
2008-06-26 20:19:47 +02:00
|
|
|
|
2009-01-27 01:31:09 +01:00
|
|
|
rhd.PciDeviceID = (id>>16);
|
2008-06-26 20:19:47 +02:00
|
|
|
|
2009-01-27 01:31:09 +01:00
|
|
|
if( (dev = RadeonDevMatch(rhd.PciDeviceID, RADEONCards))!=NULL)
|
2008-06-26 20:19:47 +02:00
|
|
|
{
|
2009-01-27 01:31:09 +01:00
|
|
|
u32_t reg2C;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
rhd.chipset = (char*)xf86TokenToString(RADEONChipsets, rhd.PciDeviceID);
|
|
|
|
if (!rhd.chipset){
|
|
|
|
dbgprintf("ChipID 0x%04x is not recognized\n", rhd.PciDeviceID);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
dbgprintf("Chipset: \"%s\" (ChipID = 0x%04x)\n",
|
|
|
|
rhd.chipset,rhd.PciDeviceID);
|
|
|
|
|
|
|
|
rhd.bus = bus;
|
|
|
|
rhd.devfn = devfn;
|
|
|
|
rhd.PciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7);
|
|
|
|
|
|
|
|
rhd.ChipFamily = dev->chip_family;
|
|
|
|
rhd.IsMobility = dev->mobility;
|
|
|
|
rhd.IsIGP = dev->igp;
|
|
|
|
rhd.HasCRTC2 = !dev->nocrtc2;
|
|
|
|
|
|
|
|
reg2C = PciRead32(bus,devfn, 0x2C);
|
|
|
|
|
|
|
|
rhd.subvendor_id = reg2C & 0xFFFF;;
|
|
|
|
rhd.subdevice_id = reg2C >> 16;
|
|
|
|
|
|
|
|
if (rhd.ChipFamily >= CHIP_FAMILY_R600)
|
|
|
|
dbgprintf("R600 unsupported yet.\nExit\n");
|
|
|
|
|
2009-02-11 07:52:01 +01:00
|
|
|
if( rhd.ChipFamily >= CHIP_FAMILY_R420)
|
|
|
|
rhd.gart_type = RADEON_IS_PCIE;
|
|
|
|
else
|
|
|
|
rhd.gart_type = RADEON_IS_PCI;
|
2009-01-27 01:31:09 +01:00
|
|
|
|
|
|
|
for (i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
u32_t base;
|
|
|
|
Bool validSize;
|
|
|
|
|
|
|
|
base = PciRead32(bus,devfn, PCI_MAP_REG_START + (i << 2));
|
|
|
|
if(base)
|
|
|
|
{
|
|
|
|
if (base & PCI_MAP_IO){
|
|
|
|
rhd.ioBase[i] = (u32_t)PCIGETIO(base);
|
|
|
|
rhd.memtype[i] = base & PCI_MAP_IO_ATTR_MASK;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
rhd.memBase[i] = (u32_t)PCIGETMEMORY(base);
|
|
|
|
rhd.memtype[i] = base & PCI_MAP_MEMORY_ATTR_MASK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rhd.memsize[i] = pciGetBaseSize(bus,devfn, i, TRUE, &validSize);
|
|
|
|
}
|
|
|
|
return &rhd;
|
2008-06-26 20:19:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2009-01-27 01:31:09 +01:00
|
|
|
return NULL;
|
2008-06-26 20:19:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-10-13 23:02:35 +02:00
|
|
|
u32_t pciGetBaseSize(int bus, int devfn, int index, Bool destructive, Bool *min)
|
2008-06-26 20:19:47 +02:00
|
|
|
{
|
|
|
|
int offset;
|
2008-10-13 23:02:35 +02:00
|
|
|
u32_t addr1;
|
|
|
|
u32_t addr2;
|
|
|
|
u32_t mask1;
|
|
|
|
u32_t mask2;
|
2008-06-26 20:19:47 +02:00
|
|
|
int bits = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* silently ignore bogus index values. Valid values are 0-6. 0-5 are
|
|
|
|
* the 6 base address registers, and 6 is the ROM base address register.
|
|
|
|
*/
|
|
|
|
if (index < 0 || index > 6)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (min)
|
|
|
|
*min = destructive;
|
|
|
|
|
|
|
|
/* Get the PCI offset */
|
|
|
|
if (index == 6)
|
|
|
|
offset = PCI_MAP_ROM_REG;
|
|
|
|
else
|
|
|
|
offset = PCI_MAP_REG_START + (index << 2);
|
|
|
|
|
|
|
|
addr1 = PciRead32(bus, devfn, offset);
|
|
|
|
/*
|
|
|
|
* Check if this is the second part of a 64 bit address.
|
|
|
|
* XXX need to check how endianness affects 64 bit addresses.
|
|
|
|
*/
|
|
|
|
if (index > 0 && index < 6) {
|
|
|
|
addr2 = PciRead32(bus, devfn, offset - 4);
|
|
|
|
if (PCI_MAP_IS_MEM(addr2) && PCI_MAP_IS64BITMEM(addr2))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (destructive) {
|
|
|
|
PciWrite32(bus, devfn, offset, 0xffffffff);
|
|
|
|
mask1 = PciRead32(bus, devfn, offset);
|
|
|
|
PciWrite32(bus, devfn, offset, addr1);
|
|
|
|
} else {
|
|
|
|
mask1 = addr1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if this is the first part of a 64 bit address. */
|
|
|
|
if (index < 5 && PCI_MAP_IS_MEM(mask1) && PCI_MAP_IS64BITMEM(mask1))
|
|
|
|
{
|
|
|
|
if (PCIGETMEMORY(mask1) == 0)
|
|
|
|
{
|
|
|
|
addr2 = PciRead32(bus, devfn, offset + 4);
|
|
|
|
if (destructive)
|
|
|
|
{
|
|
|
|
PciWrite32(bus, devfn, offset + 4, 0xffffffff);
|
|
|
|
mask2 = PciRead32(bus, devfn, offset + 4);
|
|
|
|
PciWrite32(bus, devfn, offset + 4, addr2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mask2 = addr2;
|
|
|
|
}
|
|
|
|
if (mask2 == 0)
|
|
|
|
return 0;
|
|
|
|
bits = 32;
|
|
|
|
while ((mask2 & 1) == 0)
|
|
|
|
{
|
|
|
|
bits++;
|
|
|
|
mask2 >>= 1;
|
|
|
|
}
|
|
|
|
if (bits > 32)
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (index < 6)
|
|
|
|
if (PCI_MAP_IS_MEM(mask1))
|
|
|
|
mask1 = PCIGETMEMORY(mask1);
|
|
|
|
else
|
|
|
|
mask1 = PCIGETIO(mask1);
|
|
|
|
else
|
|
|
|
mask1 = PCIGETROM(mask1);
|
|
|
|
if (mask1 == 0)
|
|
|
|
return 0;
|
|
|
|
bits = 0;
|
|
|
|
while ((mask1 & 1) == 0) {
|
|
|
|
bits++;
|
|
|
|
mask1 >>= 1;
|
|
|
|
}
|
|
|
|
/* I/O maps can be no larger than 8 bits */
|
|
|
|
|
|
|
|
if ((index < 6) && PCI_MAP_IS_IO(addr1) && bits > 8)
|
|
|
|
bits = 8;
|
|
|
|
/* ROM maps can be no larger than 24 bits */
|
|
|
|
if (index == 6 && bits > 24)
|
|
|
|
bits = 24;
|
|
|
|
return bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-02-11 07:52:01 +01:00
|
|
|
|
|
|
|
#define PCI_FIND_CAP_TTL 48
|
|
|
|
|
|
|
|
static int __pci_find_next_cap_ttl(PCITAG pciTag, u8_t pos,
|
|
|
|
int cap, int *ttl)
|
|
|
|
{
|
|
|
|
u8_t id;
|
|
|
|
|
|
|
|
while ((*ttl)--)
|
|
|
|
{
|
|
|
|
pos = pciReadByte(pciTag, pos);
|
|
|
|
if (pos < 0x40)
|
|
|
|
break;
|
|
|
|
pos &= ~3;
|
|
|
|
id = pciReadByte(pciTag, pos + PCI_CAP_LIST_ID);
|
|
|
|
if (id == 0xff)
|
|
|
|
break;
|
|
|
|
if (id == cap)
|
|
|
|
return pos;
|
|
|
|
pos += PCI_CAP_LIST_NEXT;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __pci_find_next_cap(PCITAG pciTag, u8_t pos, int cap)
|
|
|
|
{
|
|
|
|
int ttl = PCI_FIND_CAP_TTL;
|
|
|
|
|
|
|
|
return __pci_find_next_cap_ttl(pciTag, pos, cap, &ttl);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __pci_bus_find_cap_start(PCITAG pciTag)
|
|
|
|
{
|
|
|
|
u16_t status;
|
|
|
|
u8_t hdr_type;
|
|
|
|
|
|
|
|
status = pciReadWord(pciTag, PCI_STATUS);
|
|
|
|
if (!(status & PCI_STATUS_CAP_LIST))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
hdr_type = pciReadByte(pciTag, 0x0E);
|
|
|
|
switch (hdr_type)
|
|
|
|
{
|
|
|
|
case PCI_HEADER_TYPE_NORMAL:
|
|
|
|
case PCI_HEADER_TYPE_BRIDGE:
|
|
|
|
return PCI_CAPABILITY_LIST;
|
|
|
|
case PCI_HEADER_TYPE_CARDBUS:
|
|
|
|
return PCI_CB_CAPABILITY_LIST;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int pci_find_capability(PCITAG pciTag, int cap)
|
|
|
|
{
|
|
|
|
int pos;
|
|
|
|
|
|
|
|
pos = __pci_bus_find_cap_start(pciTag);
|
|
|
|
if (pos)
|
|
|
|
pos = __pci_find_next_cap(pciTag, pos, cap);
|
|
|
|
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ int drm_device_is_pcie(PCITAG pciTag)
|
|
|
|
{
|
|
|
|
return pci_find_capability(pciTag, PCI_CAP_ID_EXP);
|
|
|
|
}
|
|
|
|
|