如何枚舉PCIE capability
1. Capability 的組織結構
根據PCIE SPEC 3.0,PCIEcapability的布局如下:落在offset0x00~0xff之間的屬于PCIE capability structure對應于PCI配置空間;而落在offset0x100~0x1000之間的屬于extendedPCIE capability, 對應于PCIEextended 配置空間。
2. Capability的檢索
根據PCIE規範,每個capability結構包括如下兩個部分:
· Capability ID: 用來标示屬于哪類的capabiliy
· Next capability pointer: 是一個從0算起的offset,制定了下一個capability的位置,其為0 表示最後一個capability.
根據規範,下面代碼include/linux/pci_regs.h歸納了capabilityID和各個capability名稱的對應關系:
/* Capability lists */
#define PCI_CAP_LIST_ID 0 /* Capability ID */
#define PCI_CAP_ID_PM 0x01 /* Power Management */
#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
#define PCI_CAP_ID_HT 0x08 /* HyperTransport */
#define PCI_CAP_ID_VNDR 0x09 /* Vendor specific */
#define PCI_CAP_ID_DBG 0x0A /* Debug port */
#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */
#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */
#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */
#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
#define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */
#define PCI_CAP_LIST_NEXT 1 /*Next capability in the list */
#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
#define PCI_CAP_SIZEOF 4
利用上面next capability pointer, 一旦找到第一個capability,就能順藤摸瓜找到挂在鍊子上的所有capability.那麼問題來了,第一個capability是如何定位到的呢?秘密就在driver/pci/pci.c中的函數:
static int__pci_bus_find_cap_start(struct pci_bus *bus, unsigned int devfn, u8 hdr_type)
它根據不同的hdr_type來傳回不同的起始位置:
static int__pci_bus_find_cap_start(struct pci_bus *bus,
unsigned int devfn, u8 hdr_type)
{
u16 status;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
return 0;
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;
}
3. 核心中和capability的相關代碼:
主要的代碼在driver/pci/pci.c,相關的函數有很多,下面列出很少的一部分:
int pci_find_capability(struct pci_dev*dev, int cap);
intpci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
int pci_find_ext_capability(struct pci_dev*dev, int cap)
本文轉自存儲之廚51CTO部落格,原文連結:http://blog.51cto.com/xiamachao/1685728 ,如需轉載請自行聯系原作者