我对 PCI 总线/设备/功能枚举感到困惑。查看维基百科页对于 PCI 配置,我看到对于给定的总线,主设备将使用功能 0 请求所有设备的供应商 ID 和设备 ID。如果返回所有 0xFF,则表示没有设备,枚举继续。如果找到有效的设备 ID 和供应商 ID,则表示有一个 PCI 单元,并且将对其进行枚举。我不确定 bus.device.function 中的设备是如何确定的。
例如,假设我有一个带有一条 PCI 总线和一个 PCI 外设的 CPU。我知道 CPU 会查看总线 0(默认情况下),并会检查功能 0 上的所有设备编号。外设的设备编号是如何确定的?
答案1
设备由硬件线 IDSEL 确定,它是每个 PCI 端点的输入。在配置事务期间,IDSEL 用于向 PCI 端点(或桥)指示它当前已被选中。在确定实际设备号方面,这是由主机硬件完成的。例如,如果主板有两个 PCI 端点插槽,则从 CPU 到端点将有两条离散的 IDSEL 线。如下图所示:
此外,在实践中,将这些 IDSEL 线与 32 位地址/数据总线的单热映射绑定在一起似乎很常见。进行配置时,地址线将断言一个单热地址,例如 0x00000010。地址/数据总线的一位将作为特定端点的 IDSEL 引入。由于每条总线有 32 个可能的设备,因此效果很好。作为一个例子,假设有一块主板有 5 个可能的设备。以下可能是示例映射。
答案2
[bus/device/function/offset] 总共有 32 位。
偏移{位 7:2} 直接解释为 PCI 设备 AD7:2 信号 - 这允许最多 64 DW 的配置寄存器。
功能{位 10:9} 直接解释为 PCI 设备 AD10:9 信号 - 这允许一个 PCI 设备中最多有 8 个功能。
设备 {位 15:11} 解释为 AD31:11 信号,每个信号都连接到设备 IDSEL 引脚。虽然理论上最多有 32 个 (2^5) 设备,但使用此方法实际上只能在本地总线上连接 21 个设备 (AD11 至 AD31)。IDSEL 是初始化设备选择,在配置事务期间用作芯片选择。
顺便提一句
配置寄存器事务有两种类型:
类型0(AD1:0 为 2'b00):AD7:2 信号用于最多 64 个 DW 的配置寄存器。AD10:9 信号用于一个 PCI 设备中最多 8 个功能。AD31:11 信号无关紧要,因此可用于区分每个设备上的 IDSEL。只有本地总线上的设备才响应此类型。
类型1(AD1:0 为 2'b01):位 AD 31:2 值与 [总线/设备/功能/偏移] 非常相似。只有 PCI-to-PCI 桥接器响应此类型,如果它与其本地总线号匹配,则桥接器将其转换为 TYPE0,否则将其抛出。