0,0 → 1,288 |
|
#include "ati_pciids_gen.h" |
#include "radeon_chipset_gen.h" |
#include "radeon_chipinfo_gen.h" |
|
|
|
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); |
} |
|
|
|
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; |
} |
|
|
RHDPtr FindPciDevice() |
{ |
const RADEONCardInfo *dev; |
u32_t bus, last_bus; |
|
if( (last_bus = PciApi(1))==-1) |
return 0; |
|
for(bus=0;bus<=last_bus;bus++) |
{ |
u32_t devfn; |
|
for(devfn=0;devfn<256;devfn++) |
{ |
u32_t id; |
id = PciRead32(bus,devfn, 0); |
|
if( (u16_t)id != VENDOR_ATI) |
continue; |
|
rhd.PciDeviceID = (id>>16); |
|
if( (dev = RadeonDevMatch(rhd.PciDeviceID, RADEONCards))!=NULL) |
{ |
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"); |
|
if( rhd.ChipFamily >= CHIP_FAMILY_R420) |
rhd.gart_type = RADEON_IS_PCIE; |
else |
rhd.gart_type = RADEON_IS_PCI; |
|
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; |
} |
} |
}; |
return NULL; |
} |
|
|
|
u32_t pciGetBaseSize(int bus, int devfn, int index, Bool destructive, Bool *min) |
{ |
int offset; |
u32_t addr1; |
u32_t addr2; |
u32_t mask1; |
u32_t mask2; |
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; |
} |
|
|
|
#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); |
} |
|