PCIe的capability代表PCIe设备是否具备某种功能,例如在
static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
{
if (dev->driver->device_is_agp != NULL) {
int err = (*dev->driver->device_is_agp) (dev);
if (err != 2) {
return err;
}
}
return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
}
中就通过pci_find_capability 来查询当前的PCIe设备是否具有Accelerated Graphics Port 的能力
从pcie的spec看 0x00~0xFF 这256 byte输入pci设备的capability 而0x100~0x1000,也就是4k-256 byte这一段输入pcie的capability. 明白这点后继续看pci_find_capability
int pci_find_capability(struct pci_dev *dev, int cap)
{
int pos;
pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
if (pos)
pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
return pos;
}
在pci_find_capability 中首先通过__pci_bus_find_cap_start 来找到地一个capability的地址
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;
}
return 0;
}
从__pci_bus_find_cap_start 中可以看出pci设备其实可以分成3类,除了之前讲的type 0/1 外还有type2
但是type0 和 type 1 第一个capability的其开始地址是一样的,都是PCI_CAPABILITY_LIST == 0x34
找到其开始地址后,就调用__pci_find_next_cap 来scan整个capability 空间,看是否可以找到我们需要的capability
static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap)
{
int ttl = PCI_FIND_CAP_TTL;
return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl);
}
注意这里的ttl 等于48,表示pci设备最多支持48 个capability
static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap, int *ttl)
{
u8 id;
u16 ent;
pci_bus_read_config_byte(bus, devfn, pos, &pos);
while ((*ttl)--) {
if (pos < 0x40)
break;
pos &= ~3;
pci_bus_read_config_word(bus, devfn, pos, &ent);
id = ent & 0xff;
if (id == 0xff)
break;
if (id == cap)
return pos;
pos = (ent >> 8);
}
return 0;
}
从__pci_find_next_cap_ttl 中可以看到pos 不能超过0x40.从pos &= ~3; 可以看出capablity 是用最后3个byte来表示,也就是一个pci设备最多支持8个 capability,因此这个就对应之前讲的segment:bus:device:fn中的fn
也就是说一个slot中最多只能有8个fn,因此pci_find_capability 的第二个行参最多只能8个取值,分别如下:
* %PCI_CAP_ID_PM Power Management
* %PCI_CAP_ID_AGP Accelerated Graphics Port
* %PCI_CAP_ID_VPD Vital Product Data
* %PCI_CAP_ID_SLOTID Slot Identification
* %PCI_CAP_ID_MSI Message Signalled Interrupts
* %PCI_CAP_ID_CHSWP CompactPCI HotSwap
* %PCI_CAP_ID_PCIX PCI-X
* %PCI_CAP_ID_EXP PCI Express
static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
{
if (dev->driver->device_is_agp != NULL) {
int err = (*dev->driver->device_is_agp) (dev);
if (err != 2) {
return err;
}
}
return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
}
中就通过pci_find_capability 来查询当前的PCIe设备是否具有Accelerated Graphics Port 的能力
从pcie的spec看 0x00~0xFF 这256 byte输入pci设备的capability 而0x100~0x1000,也就是4k-256 byte这一段输入pcie的capability. 明白这点后继续看pci_find_capability
int pci_find_capability(struct pci_dev *dev, int cap)
{
int pos;
pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);
if (pos)
pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
return pos;
}
在pci_find_capability 中首先通过__pci_bus_find_cap_start 来找到地一个capability的地址
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;
}
return 0;
}
从__pci_bus_find_cap_start 中可以看出pci设备其实可以分成3类,除了之前讲的type 0/1 外还有type2
但是type0 和 type 1 第一个capability的其开始地址是一样的,都是PCI_CAPABILITY_LIST == 0x34
找到其开始地址后,就调用__pci_find_next_cap 来scan整个capability 空间,看是否可以找到我们需要的capability
static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap)
{
int ttl = PCI_FIND_CAP_TTL;
return __pci_find_next_cap_ttl(bus, devfn, pos, cap, &ttl);
}
注意这里的ttl 等于48,表示pci设备最多支持48 个capability
static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
u8 pos, int cap, int *ttl)
{
u8 id;
u16 ent;
pci_bus_read_config_byte(bus, devfn, pos, &pos);
while ((*ttl)--) {
if (pos < 0x40)
break;
pos &= ~3;
pci_bus_read_config_word(bus, devfn, pos, &ent);
id = ent & 0xff;
if (id == 0xff)
break;
if (id == cap)
return pos;
pos = (ent >> 8);
}
return 0;
}
从__pci_find_next_cap_ttl 中可以看到pos 不能超过0x40.从pos &= ~3; 可以看出capablity 是用最后3个byte来表示,也就是一个pci设备最多支持8个 capability,因此这个就对应之前讲的segment:bus:device:fn中的fn
也就是说一个slot中最多只能有8个fn,因此pci_find_capability 的第二个行参最多只能8个取值,分别如下:
* %PCI_CAP_ID_PM Power Management
* %PCI_CAP_ID_AGP Accelerated Graphics Port
* %PCI_CAP_ID_VPD Vital Product Data
* %PCI_CAP_ID_SLOTID Slot Identification
* %PCI_CAP_ID_MSI Message Signalled Interrupts
* %PCI_CAP_ID_CHSWP CompactPCI HotSwap
* %PCI_CAP_ID_PCIX PCI-X
* %PCI_CAP_ID_EXP PCI Express