pcie的8个capability(功能号)的查找

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

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值