Patch by Mike A. Harris to implement proper AGP/PCI autodetection in Radeon driver by walking the PCI capabilities list. This patch is ported forward from the patch I wrote for XFree86 4.3.0, and I consider it to be a temporary radeon driver specific fix. In the future, this should be reimplemented in os-support somewhere, and hooks put in all drivers to detect AGP/PCI using this method. --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c.mharris-radeon-agp-detect-via-pci-cap-list 2004-03-08 16:54:31.000000000 -0500 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2004-03-08 17:10:00.000000000 -0500 @@ -2258,27 +2258,65 @@ #ifdef XF86DRI /* AGP/PCI */ - - /* There are signatures in BIOS and PCI-SSID for a PCI card, but - * they are not very reliable. Following detection method works for - * all cards tested so far. Note, checking AGP_ENABLE bit after - * drmAgpEnable call can also give the correct result. However, - * calling drmAgpEnable on a PCI card can cause some strange lockup - * when the server restarts next time. + /* Proper autodetection of an AGP capable device requires examining + * PCI config registers to determine if the device implements extended + * PCI capabilities, and then walking the capability list as indicated + * in the PCI 2.2 and AGP 2.0 specifications, to determine if AGP + * capability is present. The procedure is outlined as follows: + * + * 1) Test bit 4 (CAP_LIST) of the PCI status register of the device + * to determine wether or not this device implements any extended + * capabilities. If this bit is zero, then the device is a PCI 2.1 + * or earlier device and is not AGP capable, and we can conclude it + * to be a PCI device. + * + * 2) If bit 4 of the status register is set, then the device implements + * extended capabilities. There is an 8 bit wide capabilities pointer + * register located at offset 0x34 in PCI config space which points to + * the first capability in a linked list of extended capabilities that + * this device implements. The lower two bits of this register are + * reserved and MBZ so must be masked out. + * + * 3) The extended capabilities list is formed by one or more extended + * capabilities structures which are aligned on DWORD boundaries. + * The first byte of the structure is the capability ID (CAP_ID) + * indicating what extended capability this structure refers to. The + * second byte of the structure is an offset from the beginning of + * PCI config space pointing to the next capability in the linked + * list (NEXT_PTR) or NULL (0x00) at the end of the list. The lower + * two bits of this pointer are reserved and MBZ. By examining the + * CAP_ID of each capability and walking through the list, we will + * either find the AGP_CAP_ID (0x02) indicating this device is an + * AGP device, or we'll reach the end of the list, indicating it is + * a PCI device. + * + * Mike A. Harris + * + * References: + * - PCI Local Bus Specification Revision 2.2, Chapter 6 + * - AGP Interface Specification Revision 2.0, Section 6.1.5 */ - agpCommand = pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG); - pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, - agpCommand | RADEON_AGP_ENABLE); - if (pciReadLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG) - & RADEON_AGP_ENABLE) { - info->IsPCI = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "AGP card detected\n"); - } else { - info->IsPCI = TRUE; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PCI card detected\n"); + info->IsPCI = TRUE; + + if (pciReadWord(info->PciTag, RADEON_STATUS_PCI_CONFIG) & RADEON_CAP_LIST) { + CARD8 cap_ptr, cap_id; + + cap_ptr = pciReadByte(info->PciTag, RADEON_CAPABILITIES_PTR_PCI_CONFIG) & RADEON_CAP_PTR_MASK; + + while(cap_ptr != RADEON_CAP_ID_NULL) { + cap_id = pciReadByte(info->PciTag, cap_ptr); + if (cap_id == RADEON_CAP_ID_AGP) { + info->IsPCI = FALSE; + break; + } else { + cap_ptr = pciReadByte(info->PciTag, cap_ptr + 1) & RADEON_CAP_PTR_MASK; + } + } } - pciWriteLong(info->PciTag, RADEON_AGP_COMMAND_PCI_CONFIG, agpCommand); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s card detected\n", + (info->IsPCI) ? "PCI" : "AGP"); if ((s = xf86GetOptValString(info->Options, OPTION_BUS_TYPE))) { if (strcmp(s, "AGP") == 0) { --- xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h.mharris-radeon-agp-detect-via-pci-cap-list 2004-03-08 16:56:14.000000000 -0500 +++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h 2004-03-08 16:59:29.000000000 -0500 @@ -65,6 +65,13 @@ # define RADEON_AGP_APER_SIZE_8MB (0x3e << 0) # define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) # define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) +#define RADEON_STATUS_PCI_CONFIG 0x06 +# define RADEON_CAP_LIST 0x10 +#define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */ +#define RADEON_CAPABILITIES_PTR_PCI_CONFIG 0x34 /* offset in PCI config*/ +# define RADEON_CAP_PTR_MASK 0xfc /* mask off reserved bits of CAP_PTR */ +# define RADEON_CAP_ID_NULL 0x00 /* End of capability list */ +# define RADEON_CAP_ID_AGP 0x02 /* AGP capability ID */ #define RADEON_AGP_COMMAND 0x0f60 /* PCI */ #define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ # define RADEON_AGP_ENABLE (1<<8)