这是用户在 2024-6-9 14:48 为 https://wiki.osdev.org/PCI 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?

PCI 外围组件互连

From OSDev Wiki
Jump to: navigation, search

Contents

 [hide 目录 [隐藏]

The PCI Bus  源文本:The PCI Bus 翻译文本:PCI 总线

The PCI (Peripheral Component Interconnect) bus was defined to establish a high performance and low cost local bus that would remain through several generations of products. By combining a transparent upgrade path from 132 MB/s (32-bit at 33 MHz) to 528 MB/s (64-bit at 66 MHz) and both 5 volt and 3.3 volt signalling environments, the PCI bus meets the needs of both low end desktop systems and high-end LAN servers. The PCI bus component and add-in card interface is processor independent, enabling an efficient transition to future processors, as well as use with multiple processor architectures. The disadvantage of the PCI bus is the limited number of electrical loads it can drive. A single PCI bus can drive a maximum of 10 loads. (Remember when counting the number of loads on the bus, a connector counts as one load and the PCI device counts as another, and sometimes two.)
PCI(外围组件互连)总线旨在建立一种高性能且低成本的局部总线,该总线能够贯穿多个产品代。通过提供从 132MB/s(32 位 33MHz)到 528MB/s(64 位 66MHz)的透明升级路径,并兼容 5 伏和 3.3 伏信号环境,PCI 总线满足了低端桌面系统与高端局域网服务器的不同需求。PCI 总线组件及扩展卡接口与处理器无关,便于向未来处理器平滑过渡,并可用于多种处理器架构。然而,PCI 总线的局限在于其驱动电气负载的数量有限,单个 PCI 总线最多可驱动 10 个负载。(计算总线上的负载数时,一个连接器算作一个负载,PCI 设备也算作一个,有时甚至算作两个。)

Configuration Space  配置空间

The PCI specification provides for totally software driven initialization and configuration of each device (or target) on the PCI Bus via a separate Configuration Address Space. All PCI devices, except host bus bridges, are required to provide 256 bytes of configuration registers for this purpose.
PCI 规范通过独立的配置地址空间,实现了对 PCI 总线上每个设备(或目标)完全由软件驱动的初始化和配置。除主机总线桥接器外,所有 PCI 设备均需为此提供 256 字节的配置寄存器。

Configuration read/write cycles are used to access the Configuration Space of each target device. A target is selected during a configuration access when its IDSEL signal is asserted. The IDSEL acts as the classic "chip select" signal. During the address phase of the configuration cycle, the processor can address one of 64 32-bit registers within the configuration space by placing the required register number on address lines 2 through 7 (AD[7..2]) and the byte enable lines.
配置读写周期用于访问每个目标设备的配置空间。在配置访问期间,当目标设备的 IDSEL 信号被激活时,即选定该目标。IDSEL 充当传统的“芯片选择”信号。在配置周期的地址阶段,处理器可以通过将所需的寄存器编号放置在地址线 2 至 7(AD[7..2])和字节使能线上,来寻址配置空间内 64 个 32 位寄存器中的一个。

PCI devices are inherently little-endian, meaning all multiple byte fields have the least significant values at the lower addresses. This requires a big-endian processor, such as a Power PC, to perform the proper byte-swapping of data read from or written to the PCI device, including any accesses to the Configuration Address Space.
PCI 设备本质上采用小端序,意味着所有多字节字段在较低地址处存放最不重要的值。这要求大端序处理器,如 Power PC,在从 PCI 设备读取或写入数据时,包括对配置地址空间的任何访问,执行适当的字节交换。

Systems must provide a mechanism that allows access to the PCI configuration space, as most CPUs do not have any such mechanism. This task is usually performed by the Host to PCI Bridge (Host Bridge). Two distinct mechanisms are defined to allow the software to generate the required configuration accesses. Configuration mechanism #1 is the preferred method, while mechanism #2 is provided for backwards compatibility. Only configuration mechanism #1 will be described here, as it is the only access mechanism that will be used in the future.
系统必须提供一种机制,允许访问 PCI 配置空间,因为大多数 CPU 不具备此类机制。此任务通常由主机到 PCI 桥接器(主机桥)执行。为使软件能够生成所需的配置访问,定义了两种不同的机制。配置机制#1 是首选方法,而机制#2 则是为了向后兼容而提供。此处仅描述配置机制#1,因为它是未来唯一将使用的访问机制。

Configuration Space Access Mechanism #1
配置空间访问机制 #1

Two 32-bit I/O locations are used, the first location (0xCF8) is named CONFIG_ADDRESS, and the second (0xCFC) is called CONFIG_DATA. CONFIG_ADDRESS specifies the configuration address that is required to be accesses, while accesses to CONFIG_DATA will actually generate the configuration access and will transfer the data to or from the CONFIG_DATA register.
使用两个 32 位 I/O 位置,第一个位置( 0xCF8 )命名为 CONFIG_ADDRESS,第二个( 0xCFC )称为 CONFIG_DATA。CONFIG_ADDRESS 指定需要访问的配置地址,而访问 CONFIG_DATA 实际上会生成配置访问,并将数据传输到或从 CONFIG_DATA 寄存器传出。

The CONFIG_ADDRESS is a 32-bit register with the format shown in following figure. Bit 31 is an enable flag for determining when accesses to CONFIG_DATA should be translated to configuration cycles. Bits 23 through 16 allow the configuration software to choose a specific PCI bus in the system. Bits 15 through 11 select the specific device on the PCI Bus. Bits 10 through 8 choose a specific function in a device (if the device supports multiple functions).
CONFIG_ADDRESS 是一个 32 位寄存器,其格式如下图所示。第 31 位是用于确定何时将访问 CONFIG_DATA 转换为配置周期的使能标志。第 23 至 16 位允许配置软件选择系统中的特定 PCI 总线。第 15 至 11 位用于在 PCI 总线上选择特定的设备。第 10 至 8 位用于在设备中选择特定功能(如果设备支持多个功能)。

The least significant byte selects the offset into the 256-byte configuration space available through this method. Since all reads and writes must be both 32-bits and aligned to work on all implementations, the two lowest bits of CONFIG_ADDRESS must always be zero, with the remaining six bits allowing you to choose each of the 64 32-bit words. If you don't need all 32 bits, you'll have to perform the unaligned access in software by aligning the address, followed by masking and shifting the answer.
最低有效字节通过此方法选择进入 256 字节配置空间的偏移量。由于所有读写操作必须在所有实现上均为 32 位且对齐,因此 CONFIG_ADDRESS 的最低两位必须始终为零,剩余的六位允许您选择 64 个 32 位字中的每一个。如果您不需要全部 32 位,则必须在软件中通过对齐地址、随后进行掩码和移位操作来执行未对齐访问。

Bit 31  第 31 位 Bits 30-24  位 30-24 Bits 23-16  位 23-16 Bits 15-11  位 15-11 Bits 10-8  位 10-8 Bits 7-0  位 7-0
Enable Bit  启用位 Reserved  已保留 Bus Number  公交编号 Device Number  设备编号 Function Number  功能编号 Register Offset1 寄存器偏移 1

1 Register Offset has to point to consecutive DWORDs, ie. bits 1:0 are always 0b00 (they are still part of the Register Offset).
1 寄存器偏移量必须指向连续的双字(DWORD),即位 1:0 始终为 0b00(它们仍属于寄存器偏移量的一部分)。

The following code segment illustrates the use of configuration mechanism #1 to read 16-bit fields from configuration space. Note that this segment, the outl(port, value) and inl(port) functions refer to the OUTL and INL Pentium assembly language instructions.
以下代码段展示了使用配置机制#1 从配置空间读取 16 位字段的方法。请注意,此段代码中的 outl(port, value)和 inl(port)函数对应于 Pentium 汇编语言中的 OUTL 和 INL 指令。

uint16_t pciConfigReadWord(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
    uint32_t address;
    uint32_t lbus  = (uint32_t)bus;
    uint32_t lslot = (uint32_t)slot;
    uint32_t lfunc = (uint32_t)func;
    uint16_t tmp = 0;
 
    // Create configuration address as per Figure 1
    address = (uint32_t)((lbus << 16) | (lslot << 11) |
              (lfunc << 8) | (offset & 0xFC) | ((uint32_t)0x80000000));
 
    // Write out the address
    outl(0xCF8, address);
    // Read in the data
    // (offset & 2) * 8) = 0 will choose the first word of the 32-bit register
    tmp = (uint16_t)((inl(0xCFC) >> ((offset & 2) * 8)) & 0xFFFF);
    return tmp;
}

When a configuration access attempts to select a device that does not exist, the host bridge will complete the access without error, dropping all data on writes and returning all ones on reads. The following code segment illustrates the read of a non-existent device.
当配置访问尝试选择一个不存在的设备时,主机桥将无错误地完成访问,写入时丢弃所有数据,读取时返回全 1。以下代码段演示了对不存在设备的读取操作。

uint16_t pciCheckVendor(uint8_t bus, uint8_t slot) {
    uint16_t vendor, device;
    /* Try and read the first configuration register. Since there are no
     * vendors that == 0xFFFF, it must be a non-existent device. */
    if ((vendor = pciConfigReadWord(bus, slot, 0, 0)) != 0xFFFF) {
       device = pciConfigReadWord(bus, slot, 0, 2);
       . . .
    } return (vendor);
}

Configuration Space Access Mechanism #2
配置空间访问机制 #2

This configuration space access mechanism was deprecated in PCI version 2.0. This means it's only likely to exist on hardware from around 1992 (when PCI 1.0 was introduced) to 1993 (when PCI 2.0 was introduced), which limits it to 80486 and early Pentium motherboards.
此配置空间访问机制在 PCI 版本 2.0 中已被弃用。这意味着它仅可能存在于 1992 年(PCI 1.0 引入时)至 1993 年(PCI 2.0 引入时)期间的硬件上,因此局限于 80486 及早期奔腾主板。

For access mechanism #2, the IO port at 0xCF8 is an 8-bit port and is used to enable/disable the access mechanism and set the function number. It has the following format:
对于访问机制#2,位于 0xCF8 的 IO 端口是一个 8 位端口,用于启用/禁用访问机制并设置功能号。其格式如下:

Bits 7-4  位 7-4 Bits 3-1  位 3-1 Bit 0  第 0 位
Key (0 = access mechanism disabled, non-zero = access mechanism enabled)
关键(0 = 访问机制禁用,非零 = 访问机制启用)
Function number  功能编号 Special cycle enabled if set
若设置则启用特殊循环

The IO port at 0xCFA (the "Forwarding Register") is also an 8-bit port, and is used to set the bus number for subsequent PCI configuration space accesses.
0xCFA 处的 IO 端口(即“转发寄存器”)同样是一个 8 位端口,用于设定后续 PCI 配置空间访问的总线号。

Once the access mechanism has been enabled; accesses to IO ports 0xC000 to 0xCFFF are used to access PCI configuration space. The IO port number has the following format:
一旦访问机制被启用,对 IO 端口 0xC0000xCFFF 的访问将用于访问 PCI 配置空间。IO 端口号具有以下格式:

Bits 15-12  位 15-12 Bits 11-8  位 11-8 Bits 7-2  位 7-2 Bits 1-0  位 1-0
Must be 1100b  必须是 1100b Device number  设备编号 Register index  寄存器索引 Must be zero  必须为零

Note that this limits the system to 16 devices per PCI bus.
请注意,这限制了系统每条 PCI 总线最多可连接 16 个设备。

Memory Mapped PCI Configuration Space Access
内存映射 PCI 配置空间访问

PCI Express introduced a new way to access PCI configuration space, where it's simply memory mapped and no IO ports are used. This access mechanism is described in PCI Express.
PCI Express 引入了一种访问 PCI 配置空间的新方式,其中配置空间被简单地内存映射,无需使用 IO 端口。这种访问机制在 PCI Express 规范中有详细描述。

Note that systems that do provide the memory mapped access mechanism are also required to support PCI access mechanism #1 for backwards compatibility.
请注意,提供内存映射访问机制的系统也必须支持 PCI 访问机制#1,以确保向后兼容性。

Detecting Configuration Space Access Mechanism/s
检测配置空间访问机制/s

In general there are 4 cases:
通常有四种情况:

  • Computer doesn't support PCI (either the computer is too old, or your OS is being run at some time in the future after PCI has been superseded)
    计算机不支持 PCI(要么是计算机太旧,要么是您的操作系统在未来某个时间点运行,此时 PCI 已被取代)
  • Computer supports mechanism #2
    计算机支持机制#2
  • Computer supports mechanism #1 but doesn't support the memory mapped access mechanism
    计算机支持机制#1,但不支持内存映射访问机制
  • Computer supports both mechanism #1 and the memory mapped access mechanism
    计算机同时支持机制#1 和内存映射访问机制

For BIOS systems, int 0x1A, AX=0xB101 will tell you if the system uses mechanism #1 or mechanism #2. If this function doesn't exist you can't be sure if the computer supports PCI or not. If it says mechanism #1 is supported you won't know if the memory mapped access mechanism is also supported or not.
对于 BIOS 系统, int 0x1A, AX=0xB101 将告知您系统采用机制#1 还是机制#2。如果此功能不存在,则无法确定计算机是否支持 PCI。若显示支持机制#1,则无法得知是否也支持内存映射访问机制。

For UEFI systems, it's extremely safe to assume that mechanism #2 is not supported; and you can test to see if the computer supports PCI or not by checking to see if the "PCI bus support" protocol exists. If PCI is supported, there's no easy way to determine if (e.g.) the computer supports mechanism #1 or not.
对于 UEFI 系统,可以非常安全地假设不支持机制#2;您可以通过检查是否存在“PCI 总线支持”协议来测试计算机是否支持 PCI。如果支持 PCI,则没有简单的方法来确定计算机是否支持机制#1(例如)。

For both BIOS and UEFI systems, you can check the ACPI tables to determine if the memory mapped access mechanism is supported.
对于 BIOS 和 UEFI 系统,您都可以检查 ACPI 表来确定是否支持内存映射访问机制。

This leaves a few cases uncovered (e.g. where you don't know if whether mechanism #1 or #2 are supported despite trying all of the above). For these cases the only option left is manual probing. This means 2 specific tests - whether mechanism #1 is supported, and if not whether mechanism #2 is supported. Please note that manual probing has risks; in that if there is no PCI (e.g. the system only has ISA) the IO port accesses might cause undefined behaviour (especially on systems where the ISA bus ignores highest 6 bits of the IO port address, where accessing IO port 0xCF8 is the same as accessing IO port 0xF8).
这导致少数情况未被覆盖(例如,尽管尝试了上述所有方法,仍无法确定是否支持机制#1 或#2)。对于这些情况,唯一的选择是手动探测。这意味着要进行两项具体测试——检查是否支持机制#1,若不支持,则检查是否支持机制#2。请注意,手动探测存在风险;如果系统不支持 PCI(例如,系统仅有 ISA 总线),则 IO 端口访问可能导致未定义行为(特别是在 ISA 总线忽略 IO 端口地址最高 6 位的系统中,访问 IO 端口 0xCF8 等同于访问 IO 端口 0xF8 )。

PCI Device Structure  PCI 设备结构

The PCI Specification defines the organization of the 256-byte Configuration Space registers and imposes a specific template for the space. Figures 2 & 3 show the layout of the 256-byte Configuration space. All PCI compliant devices must support the Vendor ID, Device ID, Command and Status, Revision ID, Class Code and Header Type fields. Implementation of the other registers is optional, depending upon the devices functionality.
PCI 规范定义了 256 字节配置空间寄存器的组织方式,并为该空间规定了特定的模板。图 2 和图 3 展示了 256 字节配置空间的布局。所有符合 PCI 标准的设备都必须支持供应商 ID、设备 ID、命令和状态、修订 ID、类代码以及头类型字段。其他寄存器的实现则根据设备功能可选。

Common Header Fields  常见头部字段

The following field descriptions are common to all Header Types:
以下字段描述适用于所有标题类型:

Register  注册 Offset  偏移量 Bits 31-24  位 31-24 Bits 23-16  位 23-16 Bits 15-8  位 15-8 Bits 7-0  位 7-0
0x0 0x0 Device ID  设备 ID Vendor ID  供应商 ID
0x1 0x4  0x4 Step 1: Identify the source text as a hexadecimal number. Step 2: Translate the hexadecimal number into Simplified Chinese. Step 3: Output the translated text without any additional text Status  状态 Command  命令
0x2 0x8 Class code  类代码 Subclass  子类 Prog IF  程序 IF Revision ID  修订 ID
0x3 0xC BIST Header type  标题类型 Latency Timer  延迟计时器 Cache Line Size  缓存行大小
...
  • Device ID: Identifies the particular device. Where valid IDs are allocated by the vendor.
    设备 ID:标识特定设备。有效 ID 由供应商分配。
  • Vendor ID: Identifies the manufacturer of the device. Where valid IDs are allocated by PCI-SIG (the list is here) to ensure uniqueness and 0xFFFF is an invalid value that will be returned on read accesses to Configuration Space registers of non-existent devices.
    供应商 ID:标识设备制造商。有效 ID 由 PCI-SIG 分配(列表见此)以确保唯一性,而 0xFFFF 是一个无效值,在读取不存在设备的配置空间寄存器时将返回该值。
  • Status: A register used to record status information for PCI bus related events.
    状态:用于记录与 PCI 总线相关事件状态信息的寄存器。
  • Command: Provides control over a device's ability to generate and respond to PCI cycles. Where the only functionality guaranteed to be supported by all devices is, when a 0 is written to this register, the device is disconnected from the PCI bus for all accesses except Configuration Space access.
    命令:提供对设备生成和响应 PCI 周期能力的控制。所有设备保证支持的唯一功能是,当向此寄存器写入 0 时,设备将从 PCI 总线断开,所有访问除外配置空间访问。
  • Class Code: A read-only register that specifies the type of function the device performs.
    类别代码:一个只读寄存器,用于指定设备执行的功能类型。
  • Subclass: A read-only register that specifies the specific function the device performs.
    子类:一个只读寄存器,用于指定设备执行的具体功能。
  • Prog IF(Programming Interface Byte): A read-only register that specifies a register-level programming interface the device has, if it has any at all.
    Prog IF(编程接口字节):一个只读寄存器,用于指定设备是否具有任何寄存器级别的编程接口。
  • Revision ID: Specifies a revision identifier for a particular device. Where valid IDs are allocated by the vendor.
    修订 ID:指定特定设备的修订标识符,有效 ID 由供应商分配。
  • BIST: Represents that status and allows control of a devices BIST (built-in self test).
    BIST:表示设备自检(BIST)的状态并允许对其进行控制。
  • Header Type: Identifies the layout of the rest of the header beginning at byte 0x10 of the header. If bit 7 of this register is set, the device has multiple functions; otherwise, it is a single function device. Types:
    头部类型:标识从头部字节 0x10 开始其余头部的布局。如果此寄存器的第 7 位被设置,则设备具有多种功能;否则,它是一个单功能设备。类型:
  • Latency Timer: Specifies the latency timer in units of PCI bus clocks.
    延迟计时器:以 PCI 总线时钟为单位指定延迟计时器。
  • Cache Line Size: Specifies the system cache line size in 32-bit units. A device can limit the number of cacheline sizes it can support, if a unsupported value is written to this field, the device will behave as if a value of 0 was written.
    缓存行大小:以 32 位单位指定系统缓存行大小。设备可以限制其支持的缓存行大小数量,如果向此字段写入不支持的值,设备将表现得如同写入了 0 值。

Remember that the PCI devices follow little ENDIAN ordering. The lower addresses contain the least significant portions of the field. Software to manipulate this structure must take particular care that the endian-ordering follows the PCI devices, not the CPUs.
请记住,PCI 设备遵循小端字节序排列。较低的地址包含字段的最不重要部分。操作此结构的软件必须特别注意,字节序排列应遵循 PCI 设备,而非 CPU。

Command Register  命令寄存器

Here is the layout of the Command register:
这里是命令寄存器的布局:

Bits 11-15  位 11-15 Bit 10  第 10 位 Bit 9  第 9 位 Bit 8  第 8 位 Bit 7  第 7 位 Bit 6  位 6 Bit 5  位 5 Bit 4  第 4 位 Bit 3  第 3 位 Bit 2  第 2 位 Bit 1  位 1 Bit 0  第 0 位
Reserved  已保留 Interrupt Disable  中断禁用 Fast Back-to-Back Enable
快速连续使能
SERR# Enable  SERR# 启用 Reserved  已保留 Parity Error Response  奇偶校验错误响应 VGA Palette Snoop  VGA 调色板窥探 Memory Write and Invalidate Enable
内存写入与无效化使能
Special Cycles  特殊周期 Bus Master  总线主控器 Memory Space  内存空间 I/O Space  输入/输出空间
RW RO RW RO RW RO RO RO RW RW RW
  • Interrupt Disable - If set to 1 the assertion of the devices INTx# signal is disabled; otherwise, assertion of the signal is enabled.
    中断禁用 - 若设置为 1,则设备的 INTx#信号断言被禁用;否则,信号断言被启用。
  • Fast Back-Back Enable - If set to 1 indicates a device is allowed to generate fast back-to-back transactions; otherwise, fast back-to-back transactions are only allowed to the same agent.
    快速连续启用 - 若设置为 1,表示允许设备生成快速连续交易;否则,快速连续交易仅允许针对同一代理。
  • SERR# Enable - If set to 1 the SERR# driver is enabled; otherwise, the driver is disabled.
    SERR# 启用 - 若设置为 1,则 SERR#驱动程序启用;否则,驱动程序禁用。
  • Bit 7 - As of revision 3.0 of the PCI local bus specification this bit is hardwired to 0. In earlier versions of the specification this bit was used by devices and may have been hardwired to 0, 1, or implemented as a read/write bit.
    第 7 位 - 自 PCI 本地总线规范 3.0 版起,此位被硬编码为 0。在早期版本的规范中,此位由设备使用,可能被硬编码为 0、1,或实现为可读写位。
  • Parity Error Response - If set to 1 the device will take its normal action when a parity error is detected; otherwise, when an error is detected, the device will set bit 15 of the Status register (Detected Parity Error Status Bit), but will not assert the PERR# (Parity Error) pin and will continue operation as normal.
    奇偶错误响应 - 若设置为 1,设备在检测到奇偶错误时将采取正常动作;否则,当检测到错误时,设备将设置状态寄存器第 15 位(检测到的奇偶错误状态位),但不激活 PERR#(奇偶错误)引脚,并继续正常操作。
  • VGA Palette Snoop - If set to 1 the device does not respond to palette register writes and will snoop the data; otherwise, the device will trate palette write accesses like all other accesses.
    VGA 调色板窥探 - 若设置为 1,设备不会响应调色板寄存器写入操作,而是会窥探数据;否则,设备将像对待其他访问一样处理调色板写入访问。
  • Memory Write and Invalidate Enable - If set to 1 the device can generate the Memory Write and Invalidate command; otherwise, the Memory Write command must be used.
    内存写入与无效化使能 - 若设置为 1,设备可生成内存写入与无效化命令;否则,必须使用内存写入命令。
  • Special Cycles - If set to 1 the device can monitor Special Cycle operations; otherwise, the device will ignore them.
    特殊循环 - 若设置为 1,设备可监控特殊循环操作;否则,设备将忽略这些操作。
  • Bus Master - If set to 1 the device can behave as a bus master; otherwise, the device can not generate PCI accesses.
    总线主控 - 若设置为 1,设备可作为总线主控;否则,设备无法发起 PCI 访问。
  • Memory Space - If set to 1 the device can respond to Memory Space accesses; otherwise, the device's response is disabled.
    内存空间 - 若设置为 1,设备可响应内存空间访问;否则,设备响应功能将被禁用。
  • I/O Space - If set to 1 the device can respond to I/O Space accesses; otherwise, the device's response is disabled.
    I/O 空间 - 若设置为 1,设备可响应 I/O 空间访问;否则,设备的响应功能将被禁用。

If the kernel configures the BARs of the devices, the kernel also have to enable bits 0 and 1 for it to activate.
若内核配置了设备的基地址寄存器(BARs),则还需启用位 0 和位 1 以激活设备。

Status Register  状态寄存器

Here is the layout of the Status register:
这里是状态寄存器的布局:

Bit 15  第 15 位 Bit 14  第 14 位 Bit 13  第 13 位 Bit 12  第 12 位 Bit 11  第 11 位 Bits 9-10  位 9-10 Bit 8  第 8 位 Bit 7  第 7 位 Bit 6  第 6 位 Bit 5  第 5 位 Bit 4  第 4 位 Bit 3  第 3 位 Bits 0-2  位 0-2
Detected Parity Error  检测到奇偶校验错误 Signaled System Error  信号系统错误 Received Master Abort  收到主中止 Received Target Abort  收到目标中止 Signaled Target Abort  信号目标中止 DEVSEL Timing  设备选择时序 Master Data Parity Error
主数据奇偶校验错误
Fast Back-to-Back Capable
快速连续处理能力
Reserved  已保留 66 MHz Capable  66 MHz 兼容 Capabilities List  功能列表 Interrupt Status  中断状态 Reserved  已保留
RW1C RW1C RW1C RW1C RW1C RO RW1C RO RO RO RO RO
  • Detected Parity Error - This bit will be set to 1 whenever the device detects a parity error, even if parity error handling is disabled.
    检测到奇偶校验错误 - 每当设备检测到奇偶校验错误时,无论奇偶校验错误处理是否被禁用,此位都将被设置为 1。
  • Signalled System Error - This bit will be set to 1 whenever the device asserts SERR#.
    信号系统错误 - 每当设备断言 SERR#时,此位将设置为 1。
  • Received Master Abort - This bit will be set to 1, by a master device, whenever its transaction (except for Special Cycle transactions) is terminated with Master-Abort.
    收到主设备中止 - 每当主设备的事务(特殊周期事务除外)因主设备中止而终止时,此位将被设置为 1。
  • Received Target Abort - This bit will be set to 1, by a master device, whenever its transaction is terminated with Target-Abort.
    收到目标中止 - 此位将由主设备设置为 1,每当其事务因目标中止而终止时。
  • Signalled Target Abort - This bit will be set to 1 whenever a target device terminates a transaction with Target-Abort.
    信号化目标中止 - 每当目标设备以目标中止方式终止交易时,此位将被设置为 1。
  • DEVSEL Timing - Read only bits that represent the slowest time that a device will assert DEVSEL# for any bus command except Configuration Space read and writes. Where a value of 0x0 represents fast timing, a value of 0x1 represents medium timing, and a value of 0x2 represents slow timing.
    DEVSEL 时序 - 只读位,表示设备在除配置空间读写外的任何总线命令下,最慢的 DEVSEL# 信号确认时间。其中, 0x0 值代表快速时序, 0x1 值代表中速时序, 0x2 值代表慢速时序。
  • Master Data Parity Error - This bit is only set when the following conditions are met. The bus agent asserted PERR# on a read or observed an assertion of PERR# on a write, the agent setting the bit acted as the bus master for the operation in which the error occurred, and bit 6 of the Command register (Parity Error Response bit) is set to 1.
    主数据奇偶校验错误 - 仅当满足以下条件时,此位才会被设置。总线代理在读取时断言 PERR#或在写入时观察到 PERR#的断言,设置该位的代理作为发生错误操作的总线主控,并且命令寄存器(奇偶校验错误响应位)的第 6 位设置为 1。
  • Fast Back-to-Back Capable - If set to 1 the device can accept fast back-to-back transactions that are not from the same agent; otherwise, transactions can only be accepted from the same agent.
    快速连续处理能力 - 若设置为 1,设备可接受来自不同代理的快速连续交易;否则,仅能接受来自同一代理的交易。
  • Bit 6 - As of revision 3.0 of the PCI Local Bus specification this bit is reserved. In revision 2.1 of the specification this bit was used to indicate whether or not a device supported User Definable Features.
    第 6 位 - 自 PCI 局部总线规范 3.0 修订版起,此位被保留。在 2.1 修订版中,此位用于指示设备是否支持用户自定义特性。
  • 66 MHz Capable - If set to 1 the device is capable of running at 66 MHz; otherwise, the device runs at 33 MHz.
    66 MHz 兼容 - 若设置为 1,设备可运行于 66 MHz;否则,设备运行于 33 MHz。
  • Capabilities List - If set to 1 the device implements the pointer for a New Capabilities Linked list at offset 0x34; otherwise, the linked list is not available.
    功能列表 - 若设置为 1,设备将在偏移量 0x34 处实现新功能链接列表的指针;否则,链接列表不可用。
  • Interrupt Status - Represents the state of the device's INTx# signal. If set to 1 and bit 10 of the Command register (Interrupt Disable bit) is set to 0 the signal will be asserted; otherwise, the signal will be ignored.
    中断状态 - 表示设备的 INTx#信号状态。如果设置为 1 且命令寄存器(中断禁用位)的第 10 位设置为 0,则信号将被断言;否则,信号将被忽略。

Header Type 0x0  报头类型 0x0

This table is applicable if the Header Type is 0x0. (Figure 2)
该表适用于标题类型为 0x0 的情况。(图 2)

Register  注册 Offset  偏移量 Bits 31-24  位 31-24 Bits 23-16  位 23-16 Bits 15-8  位 15-8 Bits 7-0  位 7-0
0x0 0x0 Device ID  设备 ID Vendor ID  供应商 ID
0x1 0x4 Status  状态 Command  命令
0x2 0x8  0x8 Translated Text: 0x8 Class code  类代码 Subclass  子类 Prog IF  程序 IF Revision ID  修订 ID
0x3 0xC BIST Header type  标题类型 Latency Timer  延迟计时器 Cache Line Size  缓存行大小
0x4 0x10 Base address #0 (BAR0)  基地址 #0 (BAR0)
0x5 0x14 Base address #1 (BAR1)  基地址 #1 (BAR1)
0x6 0x18 Base address #2 (BAR2)  基地址 #2 (BAR2)
0x7 0x1C Base address #3 (BAR3)  基地址 #3 (BAR3)
0x8 0x20 Base address #4 (BAR4)  基地址 #4 (BAR4)
0x9 0x24 Base address #5 (BAR5)  基地址 #5 (BAR5)
0xA 0x28 Cardbus CIS Pointer  Cardbus CIS 指针
0xB 0x2C Subsystem ID  子系统 ID Subsystem Vendor ID  子系统供应商 ID
0xC 0x30 Expansion ROM base address
扩展 ROM 基地址
0xD 0x34 Reserved  已保留 Capabilities Pointer  功能指针
0xE 0x38 Reserved  已保留
0xF  十六进制数 0xF 0x3C Max latency  最大延迟 Min Grant  最小授权 Interrupt PIN  中断 PIN 码 Interrupt Line  中断线

The following field descriptions apply if the Header Type is 0x0:
以下字段描述适用于标题类型为 0x0 时:

  • CardBus CIS Pointer: Points to the Card Information Structure and is used by devices that share silicon between CardBus and PCI.
    CardBus CIS 指针:指向卡信息结构,供共享 CardBus 和 PCI 之间硅片的设备使用。
  • Interrupt Line: Specifies which input of the system interrupt controllers the device's interrupt pin is connected to and is implemented by any device that makes use of an interrupt pin. For the x86 architecture this register corresponds to the PIC IRQ numbers 0-15 (and not I/O APIC IRQ numbers) and a value of 0xFF defines no connection.
    中断线:指定设备的硬件中断引脚连接到系统中断控制器的哪个输入,任何使用中断引脚的设备都会实现这一点。对于 x86 架构,此寄存器对应于 PIC IRQ 编号 0-15(而非 I/O APIC IRQ 编号),值为 0xFF 表示无连接。
  • Interrupt Pin: Specifies which interrupt pin the device uses. Where a value of 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, and 0x0 means the device does not use an interrupt pin.
    中断引脚:指定设备使用哪个中断引脚。其中, 0x1 表示 INTA#, 0x2 表示 INTB#, 0x3 表示 INTC#, 0x4 表示 INTD#,而 0x0 表示设备不使用中断引脚。
  • Max Latency: A read-only register that specifies how often the device needs access to the PCI bus (in 1/4 microsecond units).
    最大延迟:一个只读寄存器,指定设备需要访问 PCI 总线的频率(以 1/4 微秒为单位)。
  • Min Grant: A read-only register that specifies the burst period length, in 1/4 microsecond units, that the device needs (assuming a 33 MHz clock rate).
    Min Grant:一个只读寄存器,以 1/4 微秒为单位指定设备所需的突发周期长度(假设时钟频率为 33MHz)。
  • Capabilities Pointer: Points (i.e. an offset into this function's configuration space) to a linked list of new capabilities implemented by the device. Used if bit 4 of the status register (Capabilities List bit) is set to 1. The bottom two bits are reserved and should be masked before the Pointer is used to access the Configuration Space.
    能力指针:指向(即此函数配置空间的偏移量)设备实现的新能力链表。当状态寄存器(能力列表位)的第 4 位设置为 1 时使用。最低两位保留,使用指针访问配置空间前应先屏蔽这两位。

Header Type 0x1 (PCI-to-PCI bridge)
头部类型 0x1(PCI 到 PCI 桥接器)

This table is applicable if the Header Type is 0x1 (PCI-to-PCI bridge) (Figure 3)
此表适用于当头部类型为 0x1 (PCI-至-PCI 桥接器)(图 3)

Register  注册 Offset  偏移量 Bits 31-24  位 31-24 Bits 23-16  位 23-16 Bits 15-8  位 15-8 Bits 7-0  位 7-0
0x0 0x0 Device ID  设备 ID Vendor ID  供应商 ID
0x1 0x4 Status  状态 Command  命令
0x2 0x8 Class code  类代码 Subclass  子类 Prog IF  程序 IF Revision ID  修订 ID
0x3 0xC BIST Header type  标题类型 Latency Timer  延迟计时器 Cache Line Size  缓存行大小
0x4  0x4 Here is the translation: 0x4 0x10 Base address #0 (BAR0)  基地址 #0 (BAR0)
0x5 0x14 Base address #1 (BAR1)  基地址 #1 (BAR1)
0x6 0x18 Secondary Latency Timer  次级延迟计时器 Subordinate Bus Number  从属总线编号 Secondary Bus Number  辅助总线编号 Primary Bus Number  主总线编号
0x7 0x1C Secondary Status  次要状态 I/O Limit  输入/输出限制 I/O Base  输入/输出基地址
0x8 0x20 Memory Limit  内存限制 Memory Base  内存库
0x9 0x24 Prefetchable Memory Limit
预取内存限制
Prefetchable Memory Base  预取内存基址
0xA 0x28 Prefetchable Base Upper 32 Bits
可预取基址高 32 位
0xB 0x2C Prefetchable Limit Upper 32 Bits
预取上限高 32 位
0xC 0x30 I/O Limit Upper 16 Bits
输入/输出限制高 16 位
I/O Base Upper 16 Bits
输入/输出基址高 16 位
0xD 0x34 Reserved  已保留 Capability Pointer  能力指针
0xE 0x38 Expansion ROM base address
扩展 ROM 基地址
0xF  十六进制数:0xF 0x3C Bridge Control  桥梁控制 Interrupt PIN  中断个人识别码 Interrupt Line  中断线
Header Type Register  头部类型寄存器

Here is the layout of the Header Type register:
这里是头部类型寄存器的布局:

Bit 7  第 7 位 Bits 6-0  位 6-0
MF Header Type  头部类型
  • MF - If MF = 1 Then this device has multiple functions.
    多功 - 若 MF = 1,则此设备具备多功能。
  • Header Type - 0x0 Standard Header - 0x1 PCI-to-PCI Bridge - 0x2 CardBus Bridge
    头部类型 - 0x0 标准头部 - 0x1 PCI 至 PCI 桥接器 - 0x2 CardBus 桥接器
BIST Register  内置自检寄存器

Here is the layout of the BIST register:
这里是 BIST 寄存器的布局:

Bit 7  第 7 位 Bit 6  第 6 位 Bits 4-5  位 4-5 Bits 0-3  位 0-3
BIST Capable  内置自检功能 Start BIST  启动 BIST Reserved  已保留 Completion Code  完成码
  • BIST Capable - Will return 1 the device supports BIST.
    BIST 支持 - 若设备支持 BIST,则返回 1。
  • Start BIST - When set to 1 the BIST is invoked. This bit is reset when BIST completes. If BIST does not complete after 2 seconds the device should be failed by system software.
    启动 BIST - 当设置为 1 时,将调用 BIST。此位在 BIST 完成后重置。如果 BIST 在 2 秒后仍未完成,系统软件应判定设备故障。
  • Completion Code - Will return 0, after BIST execution, if the test completed successfully.
    完成代码 - 在 BIST 执行后,如果测试成功完成,将返回 0。

Header Type 0x2 (PCI-to-CardBus bridge)
头部类型 0x2(PCI 至 CardBus 桥接器)

This table is applicable if the Header Type is 0x2 (PCI-to-CardBus bridge)
此表适用于当头部类型为 0x2 (PCI 到 CardBus 桥接器)的情况

Register  注册 Offset  偏移 Bits 31-24  位 31-24 Bits 23-16  位 23-16 Bits 15-8  位 15-8 Bits 7-0  位 7-0
0x0 0x0 Device ID  设备 ID Vendor ID  供应商 ID
0x1 0x4 Status  状态 Command  命令
0x2 0x8 Class code  类代码 Subclass  子类 Prog IF  程序 IF Revision ID  修订 ID
0x3 0xC BIST Header type  标题类型 Latency Timer  延迟计时器 Cache Line Size  缓存行大小
0x4 0x10 CardBus Socket/ExCa base address
CardBus 插槽/ExCa 基地址
0x5 0x14 Secondary status  次要地位 Reserved  已保留 Offset of capabilities list
能力列表的偏移量
0x6 0x18 CardBus latency timer  CardBus 延迟定时器 Subordinate bus number  从属总线编号 CardBus bus number  CardBus 总线编号 PCI bus number  PCI 总线编号
0x7 0x1C Memory Base Address 0  内存基地址 0
0x8 0x20 Memory Limit 0  内存限制 0
0x9 0x24 Memory Base Address 1  内存基地址 1
0xA 0x28 Memory Limit 1  内存限制 1
0xB 0x2C I/O Base Address 0  输入/输出基地址 0
0xC 0x30 I/O Limit 0  输入/输出限制 0
0xD 0x34 I/O Base Address 1  输入/输出基地址 1
0xE 0x38 I/O Limit 1  输入/输出限制 1
0xF  十六进制数 0xF 0x3C Bridge Control  桥梁控制 Interrupt PIN  中断个人识别码 Interrupt Line  中断线
0x10 0x40 Subsystem Vendor ID  子系统供应商 ID Subsystem Device ID  子系统设备标识符
0x11 0x44 16-bit PC Card legacy mode base address
16 位 PC 卡传统模式基地址

Base Address Registers  基地址寄存器

Base Address Registers (or BARs) can be used to hold memory addresses used by the device, or offsets for port addresses. Typically, memory address BARs need to be located in physical ram while I/O space BARs can reside at any memory address (even beyond physical memory). To distinguish between them, you can check the value of the lowest bit. The following tables describe the two types of BARs:
基地址寄存器(或 BARs)可用于保存设备使用的内存地址或端口地址的偏移量。通常,内存地址 BARs 需要位于物理 RAM 中,而 I/O 空间 BARs 可以位于任何内存地址(甚至超出物理内存范围)。为区分它们,可检查最低位值。以下表格描述了两种类型的 BARs:

Memory Space BAR Layout
内存空间 BAR 布局
Bits 31-4  位 31-4 Bit 3  第 3 位 Bits 2-1  位 2-1 Bit 0  第 0 位
16-Byte Aligned Base Address
16 字节对齐基地址
Prefetchable  可预取的 Type  类型 Always 0  始终为 0
I/O Space BAR Layout
I/O 空间 BAR 布局
Bits 31-2  位 31-2 Bit 1  位 1 Bit 0  第 0 位
4-Byte Aligned Base Address
四字节对齐基地址
Reserved  已保留 Always 1  始终 1

The Type field of the Memory Space BAR Layout specifies the size of the base register and where in memory it can be mapped. If it has a value of 0x0 then the base register is 32-bits wide and can be mapped anywhere in the 32-bit Memory Space. A value of 0x2 means the base register is 64-bits wide and can be mapped anywhere in the 64-bit Memory Space (A 64-bit base address register consumes 2 of the base address registers available). A value of 0x1 is reserved as of revision 3.0 of the PCI Local Bus Specification. In earlier versions it was used to support memory space below 1MB (16-bit wide base register that can be mapped anywhere in the 16-bit Memory Space).
Memory 空间 BAR 布局中的 Type 字段指定了基址寄存器的大小及其在内存中的映射位置。若其值为 0x0 ,则基址寄存器为 32 位宽,可映射至 32 位内存空间的任意位置。值为 0x2 表示基址寄存器为 64 位宽,可映射至 64 位内存空间的任意位置(64 位基地址寄存器占用两个可用基地址寄存器)。修订版 3.0 的 PCI 本地总线规范中,值 0x1 被保留。在早期版本中,它用于支持低于 1MB 的内存空间(16 位宽的基址寄存器,可映射至 16 位内存空间的任意位置)。

When a base address register is marked as Prefetchable, it means that the region does not have read side effects (reading from that memory range doesn't change any state), and it is allowed for the CPU to cache loads from that memory region and read it in bursts (typically cache line sized). Hardware is also allowed to merge repeated stores to the same address into one store of the latest value. If you are using paging and want maximum performance, you should map prefetchable MMIO regions as WT (write-through) instead of UC (uncacheable). On x86, frame buffers are the exception, they should be almost always be mapped WC (write-combining).
当基地址寄存器被标记为可预取时,意味着该区域不存在读取副作用(从该内存范围读取不会改变任何状态),并允许 CPU 对该内存区域进行缓存加载并以突发方式读取(通常为缓存行大小)。硬件还可以将重复存储到同一地址的操作合并为最新值的一次存储。若使用分页并追求最高性能,应将可预取的 MMIO 区域映射为 WT(直写式)而非 UC(不可缓存)。在 x86 架构中,帧缓冲区为例外,它们几乎总是应被映射为 WC(写组合)。

Address and size of the BAR
基地址和 BAR 大小

When you want to retrieve the actual base address of a BAR, be sure to mask the lower bits. For 16-bit Memory Space BARs, you calculate (BAR[x] & 0xFFF0). For 32-bit Memory Space BARs, you calculate (BAR[x] & 0xFFFFFFF0). For 64-bit Memory Space BARs, you calculate ((BAR[x] & 0xFFFFFFF0) + ((BAR[x + 1] & 0xFFFFFFFF) << 32)) For I/O Space BARs, you calculate (BAR[x] & 0xFFFFFFFC).
当您需要获取基地址寄存器(BAR)的实际基地址时,务必屏蔽低位。对于 16 位内存空间 BAR,计算方式为 (BAR[x] & 0xFFF0) 。对于 32 位内存空间 BAR,计算方式为 (BAR[x] & 0xFFFFFFF0) 。对于 64 位内存空间 BAR,计算方式为 ((BAR[x] & 0xFFFFFFF0) + ((BAR[x + 1] & 0xFFFFFFFF) << 32)) 。对于 I/O 空间 BAR,计算方式为 (BAR[x] & 0xFFFFFFFC)

Before attempting to read the information about the BAR, make sure to disable both I/O and memory decode in the command byte. You can restore the original value after completing the BAR info read. This is needed as some devices are known to decode the write of all ones to the register as an (unintended) access.
在尝试读取 BAR 信息之前,请确保在命令字节中禁用 I/O 和内存解码。读取 BAR 信息后,您可以恢复原始值。这是因为某些设备已知将向寄存器写入全 1 的操作用作(非预期的)访问。

To determine the amount of address space needed by a PCI device, you must save the original value of the BAR, write a value of all 1's to the register, then read it back. The amount of memory can then be determined by masking the information bits, performing a bitwise NOT ('~' in C), and incrementing the value by 1. The original value of the BAR should then be restored. The BAR register is naturally aligned and as such you can only modify the bits that are set. For example, if a device utilizes 16 MB it will have BAR0 filled with 0xFF000000 (0x1000000 after decoding) and you can only modify the upper 8-bits. [1]
要确定 PCI 设备所需的地址空间大小,必须先保存基地址寄存器(BAR)的原始值,向该寄存器写入全 1 的值,然后读回。通过屏蔽信息位,执行按位取反(C 语言中的'~'),并将结果加 1,即可计算出所需内存量。之后应恢复 BAR 的原始值。BAR 寄存器自然对齐,因此只能修改已设置的位。例如,若设备使用 16MB 空间,BAR0 将填充为 0xFF000000(解码后为 0x1000000),此时仅能修改高 8 位。

Class Codes  类别代码

The Class Code, Subclass, and Prog IF registers are used to identify the device's type, the device's function, and the device's register-level programming interface, respectively.
类代码、子类和程序接口寄存器分别用于标识设备的类型、设备的功能以及设备的寄存器级编程接口。

The following table details most of the known device types and functions:
下表详细列出了大多数已知设备类型及其功能:

Class Code  类别代码 Subclass  子类 Prog IF  程序 IF
0x0 - Unclassified  0x0 - 未分类 0x0 - Non-VGA-Compatible Unclassified Device
0x0 - 非 VGA 兼容未分类设备
--
0x1 - VGA-Compatible Unclassified Device
0x1 - 兼容 VGA 的未分类设备
--
0x1 - Mass Storage Controller
0x1 - 大容量存储控制器
0x0 - SCSI Bus Controller
0x0 - SCSI 总线控制器
--
0x1 - IDE Controller
0x1 - IDE 控制器
0x0 - ISA Compatibility mode-only controller
0x0 - 仅支持 ISA 兼容模式的控制器
0x5 - PCI native mode-only controller
0x5 - 仅支持 PCI 原生模式的控制器
0xA - ISA Compatibility mode controller, supports both channels switched to PCI native mode
0xA - ISA 兼容模式控制器,支持两个通道切换至 PCI 原生模式
0xF - PCI native mode controller, supports both channels switched to ISA compatibility mode
0xF - PCI 原生模式控制器,支持两个通道切换至 ISA 兼容模式
0x80 - ISA Compatibility mode-only controller, supports bus mastering
0x80 - 仅支持 ISA 兼容模式的控制器,支持总线主控
0x85 - PCI native mode-only controller, supports bus mastering
0x85 - 仅支持 PCI 原生模式的控制器,支持总线主控
0x8A - ISA Compatibility mode controller, supports both channels switched to PCI native mode, supports bus mastering
0x8A - ISA 兼容模式控制器,支持双通道切换至 PCI 原生模式,支持总线主控
0x8F - PCI native mode controller, supports both channels switched to ISA compatibility mode, supports bus mastering
0x8F - PCI 本机模式控制器,支持两个通道切换至 ISA 兼容模式,支持总线主控
0x2 - Floppy Disk Controller
0x2 - 软盘控制器
--
0x3 - IPI Bus Controller
0x3 - IPI 总线控制器
--
0x4 - RAID Controller
0x4 - RAID 控制器
--
0x5 - ATA Controller
0x5 - ATA 控制器
0x20 - Single DMA  0x20 - 单通道 DMA
0x30 - Chained DMA  0x30 - 链式 DMA
0x6 - Serial ATA Controller
0x6 - 串行 ATA 控制器
0x0 - Vendor Specific Interface
0x0 - 供应商特定接口
0x1 - AHCI 1.0
0x2 - Serial Storage Bus
0x2 - 串行存储总线
0x7 - Serial Attached SCSI Controller
0x7 - 串行连接 SCSI 控制器
0x0 - SAS
0x1 - Serial Storage Bus
0x1 - 串行存储总线
0x8 - Non-Volatile Memory Controller
0x8 - 非易失性内存控制器
0x1 - NVMHCI
0x2 - NVM Express
0x80 - Other  0x80 - 其他 --
0x2 - Network Controller
0x2 - 网络控制器
0x0 - Ethernet Controller
0x0 - 以太网控制器
--
0x1 - Token Ring Controller
0x1 - 令牌环控制器
--
0x2 - FDDI Controller
0x2 - FDDI 控制器
--
0x3 - ATM Controller
0x3 - ATM 控制器
--
0x4 - ISDN Controller
0x4 - ISDN 控制器
--
0x5 - WorldFip Controller
0x5 - 世界菲普控制器
--
0x6 - PICMG 2.14 Multi Computing Controller
0x6 - PICMG 2.14 多计算控制器
--
0x7 - Infiniband Controller
0x7 - Infiniband 控制器
--
0x8 - Fabric Controller
0x8 - 结构控制器
--
0x80 - Other  0x80 - 其他 --
0x3 - Display Controller
0x3 - 显示控制器
0x0 - VGA Compatible Controller
0x0 - VGA 兼容控制器
0x0 - VGA Controller  0x0 - VGA 控制器
0x1 - 8514-Compatible Controller
0x1 - 8514 兼容控制器
0x1 - XGA Controller
0x1 - XGA 控制器
--
0x2 - 3D Controller (Not VGA-Compatible)
0x2 - 3D 控制器(非 VGA 兼容)
--
0x80 - Other  0x80 - 其他 --
0x4 - Multimedia Controller
0x4 - 多媒体控制器
0x0 - Multimedia Video Controller
0x0 - 多媒体视频控制器
--
0x1 - Multimedia Audio Controller
0x1 - 多媒体音频控制器
--
0x2 - Computer Telephony Device
0x2 - 计算机电话设备
--
0x3 - Audio Device
0x3 - 音频设备
--
0x80 - Other  0x80 - 其他 --
0x5 - Memory Controller
0x5 - 内存控制器
0x0 - RAM Controller
0x0 - 内存控制器
--
0x1 - Flash Controller
0x1 - 闪存控制器
--
0x80 - Other  0x80 - 其他 --
0x6 - Bridge  0x6 - 桥接 0x0 - Host Bridge
0x0 - 主机桥接器
--
0x1 - ISA Bridge
0x1 - ISA 桥接器
--
0x2 - EISA Bridge
0x2 - EISA 桥接器
--
0x3 - MCA Bridge
0x3 - MCA 桥接器
--
0x4 - PCI-to-PCI Bridge
0x4 - PCI 至 PCI 桥接器
0x0 - Normal Decode  0x0 - 正常解码
0x1 - Subtractive Decode  0x1 - 减法解码
0x5 - PCMCIA Bridge
0x5 - PCMCIA 桥接器
--
0x6 - NuBus Bridge
0x6 - NuBus 桥接器
--
0x7 - CardBus Bridge
0x7 - CardBus 桥接器
--
0x8 - RACEway Bridge
0x8 - RACEway 桥接器
0x0 - Transparent Mode  0x0 - 透明模式
0x1 - Endpoint Mode  0x1 - 端点模式
0x9 - PCI-to-PCI Bridge
0x9 - PCI 至 PCI 桥接器
0x40 - Semi-Transparent, Primary bus towards host CPU
0x40 - 半透明,主总线朝向主机 CPU
0x80 - Semi-Transparent, Secondary bus towards host CPU
0x80 - 半透明,通往主机 CPU 的辅助总线
0x0A - InfiniBand-to-PCI Host Bridge
0x0A - InfiniBand 到 PCI 主机桥接器
--
0x80 - Other  0x80 - 其他 --
0x7 - Simple Communication Controller
0x7 - 简易通信控制器
0x0 - Serial Controller
0x0 - 串行控制器
0x0 - 8250-Compatible (Generic XT)
0x0 - 兼容 8250(通用 XT)
0x1 - 16450-Compatible  0x1 - 兼容 16450
0x2 - 16550-Compatible  0x2 - 兼容 16550
0x3 - 16650-Compatible  0x3 - 兼容 16650
0x4 - 16750-Compatible  0x4 - 兼容 16750
0x5 - 16850-Compatible  0x5 - 兼容 16850
0x6 - 16950-Compatible  0x6 - 兼容 16950
0x1 - Parallel Controller
0x1 - 并行控制器
0x0 - Standard Parallel Port
0x0 - 标准并行端口
0x1 - Bi-Directional Parallel Port
0x1 - 双向并行端口
0x2 - ECP 1.X Compliant Parallel Port
0x2 - ECP 1.X 兼容并行端口
0x3 - IEEE 1284 Controller
0x3 - IEEE 1284 控制器
0xFE - IEEE 1284 Target Device
0xFE - IEEE 1284 目标设备
0x2 - Multiport Serial Controller
0x2 - 多端口串行控制器
--
0x3 - Modem  0x3 - 调制解调器 0x0 - Generic Modem  0x0 - 通用调制解调器
0x1 - Hayes 16450-Compatible Interface
0x1 - 海斯 16450 兼容接口
0x2 - Hayes 16550-Compatible Interface
0x2 - 海斯 16550 兼容接口
0x3 - Hayes 16650-Compatible Interface
0x3 - 海斯 16650 兼容接口
0x4 - Hayes 16750-Compatible Interface
0x4 - 海斯 16750 兼容接口
0x4 - IEEE 488.1/2 (GPIB) Controller
0x4 - IEEE 488.1/2 (GPIB) 控制器
--
0x5 - Smart Card Controller
0x5 - 智能卡控制器
--
0x80 - Other  0x80 - 其他 --
0x8 - Base System Peripheral
0x8 - 基础系统外设
0x0 - PIC  0x0 - 外围接口控制器 0x0 - Generic 8259-Compatible
0x0 - 通用 8259 兼容型
0x1 - ISA-Compatible  0x1 - 兼容 ISA
0x2 - EISA-Compatible  0x2 - EISA 兼容
0x10 - I/O APIC Interrupt Controller
0x10 - I/O APIC 中断控制器
0x20 - I/O(x) APIC Interrupt Controller
0x20 - I/O(x) APIC 中断控制器
0x01 - DMA Controller
0x01 - DMA 控制器
0x00 - Generic 8237-Compatible
0x00 - 通用 8237 兼容型
0x01 - ISA-Compatible  0x01 - 兼容 ISA
0x02 - EISA-Compatible  0x02 - EISA 兼容
0x02 - Timer  0x02 - 定时器 0x00 - Generic 8254-Compatible
0x00 - 通用 8254 兼容
0x01 - ISA-Compatible  0x01 - 兼容 ISA
0x02 - EISA-Compatible  0x02 - EISA 兼容
0x03 - HPET  0x03 - HPET 翻译:0x03 - 高精度事件定时器
0x3 - RTC Controller
0x3 - RTC 控制器
0x0 - Generic RTC  0x0 - 通用实时时钟
0x1 - ISA-Compatible  0x1 - 兼容 ISA
0x4 - PCI Hot-Plug Controller
0x4 - PCI 热插拔控制器
--
0x5 - SD Host controller
0x5 - SD 主机控制器
--
0x6 - IOMMU --
0x80 - Other  0x80 - 其他 --
0x9 - Input Device Controller
0x9 - 输入设备控制器
0x0 - Keyboard Controller
0x0 - 键盘控制器
--
0x1 - Digitizer Pen
0x1 - 数位笔
--
0x2 - Mouse Controller
0x2 - 鼠标控制器
--
0x3 - Scanner Controller
0x3 - 扫描控制器
--
0x4 - Gameport Controller
0x4 - 游戏端口控制器
0x0 - Generic  0x0 - 通用
0x10 - Extended  0x10 - 扩展
0x80 - Other  0x80 - 其他 --
0xA - Docking Station
0xA - 对接站
0x0 - Generic  0x0 - 通用 --
0x80 - Other  0x80 - 其他 --
0xB - Processor  0xB - 处理器 0x0 - 386 --
0x1 - 486 --
0x2 - Pentium  0x2 - 奔腾 --
0x3 - Pentium Pro
0x3 - 奔腾 Pro
--
0x10 - Alpha  0x10 - 阿尔法 --
0x20 - PowerPC  0x20 - PowerPC 翻译: 0x20 - 高性能计算平台 --
0x30 - MIPS  0x30 - MIPS 翻译:0x30 - MIPS --
0x40 - Co-Processor  0x40 - 协处理器 --
0x80 - Other  0x80 - 其他 --
0xC - Serial Bus Controller
0xC - 串行总线控制器
0x0 - FireWire (IEEE 1394) Controller
0x0 - 火线(IEEE 1394)控制器
0x0 - Generic  0x0 - 通用
0x10 - OHCI  0x10 - OHCI 翻译:0x10 - OHCI
0x1 - ACCESS Bus Controller
0x1 - 访问总线控制器
--
0x2 - SSA  0x2 - SSA 翻译:0x2 - 单一安全分析器 --
0x3 - USB Controller
0x3 - USB 控制器
0x0 - UHCI Controller  0x0 - UHCI 控制器
0x10 - OHCI Controller  0x10 - OHCI 控制器
0x20 - EHCI (USB2) Controller
0x20 - EHCI(USB2)控制器
0x30 - XHCI (USB3) Controller
0x30 - XHCI(USB3)控制器
0x80 - Unspecified  0x80 - 未指定
0xFE - USB Device (Not a host controller)
0xFE - USB 设备(非主机控制器)
0x4 - Fibre Channel
0x4 - 光纤通道
--
0x5 - SMBus Controller
0x5 - SMBus 控制器
--
0x6 - InfiniBand Controller
0x6 - InfiniBand 控制器
--
0x7 - IPMI Interface
0x7 - IPMI 接口
0x0 - SMIC  0x0 - 中芯国际
0x1 - Keyboard Controller Style
0x1 - 键盘控制器样式
0x2 - Block Transfer  0x2 - 块传输
0x8 - SERCOS Interface (IEC 61491)
0x8 - SERCOS 接口(IEC 61491)
--
0x9 - CANbus Controller
0x9 - CAN 总线控制器
--
0x80 - Other  0x80 - 其他 --
0xD - Wireless Controller
0xD - 无线控制器
0x0 - iRDA Compatible Controller
0x0 - iRDA 兼容控制器
--
0x1 - Consumer IR Controller
0x1 - 消费红外控制器
--
0x10 - RF Controller
0x10 - 射频控制器
--
0x11 - Bluetooth Controller
0x11 - 蓝牙控制器
--
0x12 - Broadband Controller
0x12 - 宽带控制器
--
0x20 - Ethernet Controller (802.1a)
0x20 - 以太网控制器(802.1a)
--
0x21 - Ethernet Controller (802.1b)
0x21 - 以太网控制器(802.1b)
--
0x80 - Other  0x80 - 其他 --
0xE - Intelligent Controller
0xE - 智能控制器
0x0 - I20  0x0 - I20 翻译:0x0 - I20 --
0xF - Satellite Communication Controller
0xF - 卫星通信控制器
0x1 - Satellite TV Controller
0x1 - 卫星电视控制器
--
0x2 - Satellite Audio Controller
0x2 - 卫星音频控制器
--
0x3 - Satellite Voice Controller
0x3 - 卫星语音控制器
--
0x4 - Satellite Data Controller
0x4 - 卫星数据控制器
--
0x10 - Encryption Controller
0x10 - 加密控制器
0x0 - Network and Computing Encrpytion/Decryption
0x0 - 网络与计算加密/解密
--
0x10 - Entertainment Encryption/Decryption
0x10 - 娱乐加密/解密
--
0x80 - Other  0x80 - 其他 --
0x11 - Signal Processing Controller
0x11 - 信号处理控制器
0x0 - DPIO Modules
0x0 - DPIO 模块
--
0x1 - Performance Counters
0x1 - 性能计数器
--
0x10 - Communication Synchronizer
0x10 - 通信同步器
--
0x20 - Signal Processing Management
0x20 - 信号处理管理
--
0x80 - Other  0x80 - 其他 --
0x12 - Processing Accelerator
0x12 - 处理加速器
-- --
0x13 - Non-Essential Instrumentation
0x13 - 非必要仪表设备
-- --
0x14 - 0x3F (Reserved)
0x14 - 0x3F (保留)
-- --
0x40 - Co-Processor  0x40 - 协处理器 -- --
0x41 - 0xFE (Reserved)
0x41 - 0xFE(保留)
-- --
0xFF - Unassigned Class (Vendor specific)
0xFF - 未分配类(厂商特定)
-- --

Enumerating PCI Buses  枚举 PCI 总线

There are 3 ways to enumerate devices on PCI buses. The first way is "brute force", checking every device on every PCI bus (regardless of whether the PCI bus exists or not). The second way avoids a lot of work by figuring out valid bus numbers while it scans, and is a little more complex as it involves recursion. For both of these methods you rely on something (firmware) to have configured PCI buses properly (setting up PCI to PCI bridges to forward request from one bus to another). The third method is like the second method, except that you configure PCI bridges while you're doing it.
枚举 PCI 总线上的设备有三种方法。第一种是“暴力法”,即检查每个 PCI 总线上的每个设备(无论该 PCI 总线是否存在)。第二种方法通过在扫描过程中确定有效总线号来避免大量工作,这种方法稍微复杂一些,因为它涉及递归。对于这两种方法,你都依赖于(固件)已经正确配置了 PCI 总线(设置 PCI 到 PCI 桥接器以将请求从一个总线转发到另一个总线)。第三种方法类似于第二种,不同之处在于你在执行过程中配置 PCI 桥接器。

For all 3 methods, you need to be able to check if a specific device on a specific bus is present and if it is multi-function or not. Pseudo-code might look like this:
对于所有 3 种方法,您需要能够检查特定总线上的特定设备是否存在,以及它是否为多功能设备。伪代码可能如下所示:

 void checkDevice(uint8_t bus, uint8_t device) {
     uint8_t function = 0;
 
     vendorID = getVendorID(bus, device, function);
     if (vendorID == 0xFFFF) return; // Device doesn't exist
     checkFunction(bus, device, function);
     headerType = getHeaderType(bus, device, function);
     if( (headerType & 0x80) != 0) {
         // It's a multi-function device, so check remaining functions
         for (function = 1; function < 8; function++) {
             if (getVendorID(bus, device, function) != 0xFFFF) {
                 checkFunction(bus, device, function);
             }
         }
     }
 }
 
 void checkFunction(uint8_t bus, uint8_t device, uint8_t function) {
 }

Please note that if you don't check bit 7 of the header type and scan all functions, then some single-function devices will report details for "function 0" for every function.
请注意,若未检查头部类型中的第 7 位且遍历所有功能,则某些单功能设备将对每个功能报告“功能 0”的详细信息。

"Brute Force" Scan  "暴力破解"扫描

For the brute force method, the remaining code is relatively simple. Pseudo-code might look like this:
对于暴力破解方法,剩余的代码相对简单。伪代码可能如下所示:

 void checkAllBuses(void) {
     uint16_t bus;
     uint8_t device;
 
     for (bus = 0; bus < 256; bus++) {
         for (device = 0; device < 32; device++) {
             checkDevice(bus, device);
         }
     }
 }

For this method, there are 32 devices per bus and 256 buses, so you call "checkDevice()" 8192 times.
对于此方法,每条总线上有 32 个设备,共有 256 条总线,因此您需要调用"checkDevice()"8192 次。

Recursive Scan  递归扫描

The first step for the recursive scan is to implement a function that scans one bus. Pseudo-code might look like this:
递归扫描的第一步是实现一个函数,该函数扫描一条总线。伪代码可能如下所示:

 void checkBus(uint8_t bus) {
     uint8_t device;
 
     for (device = 0; device < 32; device++) {
         checkDevice(bus, device);
     }
 }

The next step is to add code in "checkFunction()" that detects if the function is a PCI to PCI bridge. If the device is a PCI to PCI bridge then you want to extract the "secondary bus number" from the bridge's configuration space and call "checkBus()" with the number of the bus on the other side of the bridge.
下一步是在"checkFunction()"中添加代码,以检测该功能是否为 PCI 到 PCI 桥接器。如果设备是 PCI 到 PCI 桥接器,则需要从桥接器的配置空间中提取“辅助总线号”,并使用桥另一侧的总线号调用“checkBus()”。

Pseudo-code might look like this:
伪代码可能看起来像这样:

 void checkFunction(uint8_t bus, uint8_t device, uint8_t function) {
     uint8_t baseClass;
     uint8_t subClass;
     uint8_t secondaryBus;
 
     baseClass = getBaseClass(bus, device, function);
     subClass = getSubClass(bus, device, function);
     if ((baseClass == 0x6) && (subClass == 0x4)) {
         secondaryBus = getSecondaryBus(bus, device, function);
         checkBus(secondaryBus);
     }
 }

The final step is to handle systems with multiple PCI host controllers correctly. Start by checking if the device at bus 0, device 0 is a multi-function device. If it's not a multi-function device, then there is only one PCI host controller and bus 0, device 0, function 0 will be the PCI host controller responsible for bus 0. If it's a multi-function device, then bus 0, device 0, function 0 will be the PCI host controller responsible for bus 0; bus 0, device 0, function 1 will be the PCI host controller responsible for bus 1, etc (up to the number of functions supported).
最后一步是正确处理具有多个 PCI 主机控制器的系统。首先检查总线 0、设备 0 处的设备是否为多功能设备。如果不是多功能设备,则只有一个 PCI 主机控制器,总线 0、设备 0、功能 0 将是负责总线 0 的 PCI 主机控制器。如果是多功能设备,则总线 0、设备 0、功能 0 将是负责总线 0 的 PCI 主机控制器;总线 0、设备 0、功能 1 将是负责总线 1 的 PCI 主机控制器,以此类推(直至支持的功能数上限)。

Pseudo-code might look like this:
伪代码可能看起来像这样:

 void checkAllBuses(void) {
     uint8_t function;
     uint8_t bus;
 
     headerType = getHeaderType(0, 0, 0);
     if ((headerType & 0x80) == 0) {
         // Single PCI host controller
         checkBus(0);
     } else {
         // Multiple PCI host controllers
         for (function = 0; function < 8; function++) {
             if (getVendorID(0, 0, function) != 0xFFFF) break;
             bus = function;
             checkBus(bus);
         }
     }
 }

Recursive Scan With Bus Configuration
递归扫描与总线配置

This is similar to the recursive scan above; except that you set the "secondary bus" field in PCI to PCI bridges (using something like setSecondaryBus(bus, device, function, nextBusNumber++); instead of the getSecondaryBus();). However; if you are configuring PCI buses you are also responsible for configuring the memory areas/BARs in PCI functions, and ensuring that PCI bridges forward requests from their primary bus to their secondary buses.
这与上述递归扫描类似;区别在于你在 PCI 中将“辅助总线”字段设置为 PCI 桥接器(使用类似 setSecondaryBus(bus, device, function, nextBusNumber++); 而非 getSecondaryBus(); )。但若你在配置 PCI 总线,还需负责配置 PCI 功能中的内存区域/基地址寄存器(BARs),并确保 PCI 桥接器将其主总线的请求转发至辅助总线。

Writing code to support this without a deep understanding of PCI specifications is not recommended; and if you have a deep understanding of PCI specifications you have no need for pseudo code. For this reason there will be no example code for this method here.
不深入理解 PCI 规范而编写支持代码并不推荐;若你已深入理解 PCI 规范,则无需伪代码。因此,此处不会提供此方法的示例代码。

Configuring PCI-to-PCI bridges
配置 PCI 到 PCI 桥接器

To configure this the kernel has to forget about BIOS for a moment, first scan the root PCI device, (check if it is multi-function to scan multiple buses). Root bus is always 0.
要配置此功能,内核需暂时忽略 BIOS,首先扫描根 PCI 设备,(检查其是否为多功能的以扫描多个总线)。根总线始终为 0。

Secondary and subordinate bus acts as a range start-end of what buses the PCI-to-PCI bridge will manage.
次级和从属总线充当 PCI-to-PCI 桥接器管理总线的范围起止点。

Then, after this step it's up to implementation: Scan each device, then if a bridge is found, allocate a bus number to it (note: PCI-to-PCI bridges can have multiple bridges within them). Scan that bus and find more devices, once you find more bridges add 1 to the subordinate bus for each bridge found, because PCI-to-PCI bridges can manage multiple bridges.
随后,此步骤之后取决于实施细节:逐一扫描每个设备,若发现桥接器,则为其分配一个总线号(注意:PCI 到 PCI 桥接器内部可能包含多个桥接器)。接着扫描该总线并寻找更多设备,一旦找到更多桥接器,每发现一个桥接器,就将从属总线数加 1,因为 PCI 到 PCI 桥接器能够管理多个桥接器。

And this is just the beginning: After allocating bus numbers, you need to allocate MMIO, it would be trivial if it wasn't for the fact that PCI has 3 areas the kernel manages: IO, Prefetch and Memory.
而这仅仅是开始:分配完总线编号后,还需分配 MMIO,若非 PCI 有内核管理的三个区域——IO、预取和内存,这一过程本应轻而易举。

A bridge can manage multiple buses, but that means it spans all the memory of these buses, if device 1 is behind bridge 2, which is behind bridge 1, then bridge 2 will contain the memory area of device 1 + any other device's areas, supposing IO is 4M, Memory is 16M and Prefetch is 5MB (supposing there are 3 devices in bridge's 2 bus), bridge 2 would contain those, take in reference table for Header type 0x1. However, bridge 1 will contain the areas of bridge 2 + any other devices in bridge's 1 bus.
一个桥接器可以管理多个总线,但这意味着它涵盖了这些总线的所有内存。如果设备 1 位于桥接器 2 之后,而桥接器 2 又位于桥接器 1 之后,那么桥接器 2 将包含设备 1 的内存区域以及任何其他设备的区域。假设 IO 为 4M,内存为 16M,预取为 5MB(假设桥接器 2 的总线上有 3 个设备),桥接器 2 将包含这些内容,并参考表头类型 0x1 。然而,桥接器 1 将包含桥接器 2 的区域以及桥接器 1 总线上的任何其他设备区域。

Once all memory areas are allocated, the devices can be used. Note that PCI-to-PCI bridges also have BAR's.
一旦所有内存区域分配完毕,设备即可使用。请注意,PCI 到 PCI 桥接器也具有基地址寄存器(BAR)。

If the kernel does not configure a PCI-to-PCI bridge, the BIOS will probably do, however on environments without BIOS, this method is mandatory otherwise devices behind that bridge won't show up.
如果内核未配置 PCI 到 PCI 桥接器,BIOS 可能会代为处理,但在无 BIOS 的环境中,此方法必不可少,否则桥接器后的设备将无法显示。

IRQ Handling  中断请求处理

If you're using the old PIC, your life is really easy. You have the Interrupt Line field of the header, which is read/write (you can change it's value!) and it says which interrupt will the PCI device fire when it needs attention.
如果你使用的是旧的 PIC,你的生活真的很轻松。你拥有头部的中断线字段,它是可读写的(你可以更改其值!),它指明了 PCI 设备在需要关注时将触发哪个中断。

If you plan to use the I/O APIC, things aren't so easy. Basically the PCI bus specifies that there are 4 interrupt pins. They are labeled INTA#, INTB#, INTC#, and INTD#. You find out what pin a device is using by reading the Interrupt Pin field of the header. So far, so good.
若计划使用 I/O APIC,事情就不那么简单了。基本上,PCI 总线规定有 4 个中断引脚,分别标记为 INTA#、INTB#、INTC#和 INTD#。要了解设备使用哪个引脚,需通过读取头部的“中断引脚”字段来确定。到目前为止,一切顺利。

The only problem is that the PCI pins correspond to an arbitrary I/O APIC pin. It's up to the programmer to find the mapping. How is that done? You must parse the MP Tables or the ACPI tables. The MP tables are easy, only they aren't supported on newer hardware. The ACPI tables, however, involve parsing AML, which is not an easy task. If one wants to take a shortcut, you can use ACPICA.
唯一的问题是 PCI 引脚对应于一个任意的 I/O APIC 引脚。这需要程序员去查找映射关系。如何实现呢?必须解析 MP 表或 ACPI 表。MP 表较为简单,但新硬件上不支持。而 ACPI 表则涉及解析 AML,这并非易事。若想走捷径,可使用 ACPICA。

Once you've found the I/O APIC pin, all you do is map that to an IRQ using the I/O APIC redirection table. See the I/O APIC article for more information on this.
一旦找到 I/O APIC 引脚,只需将其映射到 I/O APIC 重定向表中的 IRQ 即可。更多信息请参阅 I/O APIC 相关文章。

Alternatively, you could just use MSI or MSI-X, and skip complicated ACPI.
或者,您也可以直接使用 MSI 或 MSI-X,跳过复杂的 ACPI。

Message Signaled Interrupts
消息信号中断

Message Signaled Interrupts, or MSI, have been supported since PCI 2.2. However, support for them is mandatory in PCIe devices, so you can be sure that they're usable on modern hardware.
消息信号中断(MSI)自 PCI 2.2 起得到支持。然而,在 PCIe 设备中对其支持是强制性的,因此您可以确信它们在现代硬件上是可用的。

Use of MSI and MSI-X are mutually exclusive.
MSI 和 MSI-X 的使用是互斥的。

Enabling MSI  启用 MSI

First, check that the device has a pointer to the capabilities list (status register bit 4 set to 1). Then, traverse the capabilities list. The low 8 bits of a capability register are the ID - 0x05 for MSI. The next 8 bits are the offset (in PCI Configuration Space) of the next capability.
首先,确认设备具有指向能力列表的指针(状态寄存器位 4 设为 1)。接着,遍历能力列表。能力寄存器的低 8 位是 ID—— 0x05 代表 MSI。接下来的 8 位是下一个能力的偏移量(在 PCI 配置空间中)。

The MSI capability is as follows:
MSI 功能如下:

Register  注册 Offset  偏移量 Bits 31-24  位 31-24 Bits 23-16  位 23-16 Bits 15-8  位 15-8 Bits 7-0  位 7-0
Cap + 0x0  帽 + 0x0 Cap + 0x0  帽 + 0x0 Message Control  消息控制 Next pointer  下一指针 Capability ID = 05  能力 ID = 05
Cap + 0x1  帽 + 0x1 Cap + 0x4  帽 + 0x4 Message Address [Low]  消息地址 [低]
Cap + 0x2  帽 + 0x2 Cap + 0x8  帽 + 0x8 [Message Address High]  消息地址高位
Cap + 0x2/0x3  帽 + 0x2/0x3 Cap + 0x8/0xC Reserved  已保留 Message Data  消息数据
Cap + 0x4  帽 + 0x4 Cap + 0x10  帽 + 0x10 [Mask]  翻译文本:[面具]
Cap + 0x5  帽 + 0x5 Cap + 0x14  帽 + 0x14 [Pending]  待定

Here is the layout of the message control register:
消息控制寄存器的布局如下:

Bits 15-9  位 15-9 Bit 8  第 8 位 Bit 7  第 7 位 Bits 6-4  位 6-4 Bits 3-1  位 3-1 Bit 0  第 0 位
Reserved  已保留 Per-vector masking  逐向量掩码 64-bit  64 位 Multiple Message Enable  多消息启用 Multiple Message Capable
多消息能力
Enable  启用

The message address/data is architecture specific. On x86(-64), it is as follows:
消息地址/数据与架构相关。在 x86(-64)上,情况如下:

uint64_t arch_msi_address(uint64_t *data, size_t vector, uint32_t processor, uint8_t edgetrigger, uint8_t deassert) {
	*data = (vector & 0xFF) | (edgetrigger == 1 ? 0 : (1 << 15)) | (deassert == 1 ? 0 : (1 << 14));
	return (0xFEE00000 | (processor << 12));
}

MSI interrupts seem to be invariably edge triggered high.
MSI 中断似乎总是高电平边沿触发。

Multiple messages: 多条消息:

MME / MMI Interrupts  中断
000 1
001 2
010 4
011 8
100 16
101 32

In MME, specifies the number of low bits of Message Data that may be modified by the device.
在 MME 中,指定设备可以修改的消息数据低位的位数。

Therefore, the interrupt vector block allocated must be aligned accordingly.
因此,分配的中断向量块必须相应地对齐。

Interrupt masking 中断屏蔽

If capable, you can mask individual messages by setting the corresponding bit (1 << n), in the mask register.
若具备此功能,您可通过设置掩码寄存器中对应的位(1 << n)来屏蔽单个消息。

If a message is pending, then the corresponding bit in the pending register is set.
若消息处于待处理状态,则待处理寄存器中对应的位将被置位。

Note that the PCI specification doesn't specify the location of these registers if the message address is 32-bit. This is because a function that supports masking is required to implement 64-bit addressing!
请注意,如果消息地址为 32 位,PCI 规范并未指定这些寄存器的位置。这是因为需要支持掩码功能的函数来实现 64 位寻址!

Enabling MSI-X  启用 MSI-X

Like for MSI, you have to find the MSI-X capability, but the ID for MSI-X is 0x11
与 MSI 类似,您需要找到 MSI-X 功能,但 MSI-X 的 ID 是 0x11

The structure is as follows:
结构如下:

Register  注册 Offset  偏移 Bits 31-24  位 31-24 Bits 23-16  位 23-16 Bits 15-8  位 15-8 Bits 7-3  位 7-3 Bits 2-0  位 2-0
Cap + 0x0  帽 + 0x0 Cap + 0x0  帽 + 0x0 Message Control  消息控制 Next Pointer  下一指针 Capability ID = 11  能力 ID = 11
Cap + 0x1  帽 + 0x1 Cap + 0x4  帽 + 0x4 Table Offset  表偏移 BIR
Cap + 0x2  帽 + 0x2 Cap + 0x8  帽 + 0x8 Pending Bit Offset  待定位偏移 Pending Bit BIR  待定位 BIR

Unlike MSI, MSI-X supports 2048 interrupts. This is achieved by maintaining a table of interrupts in the PCI device's address space. The wording of the PCI 3.0 specification indicates that this must be via a Memory BAR.
与 MSI 不同,MSI-X 支持 2048 个中断。这是通过在 PCI 设备的地址空间中维护一个中断表来实现的。PCI 3.0 规范的措辞表明,这必须通过内存基址寄存器(Memory BAR)来完成。

BIR specifies which BAR is used for the Message Table. This may be a 64-bit BAR, and is zero-indexed (so BIR=0, BAR0, offset 0x10 into the header).
BIR 指定用于消息表的 BAR。这可能是一个 64 位 BAR,并且是零索引的(因此 BIR=0,BAR0,偏移量 0x10 进入头部)。

Table Offset is an offset into that BAR where the Message Table lives. Note that it is 8-byte aligned - so simply mask BIR.
表偏移是指消息表所在 BAR 中的偏移量。请注意,它是 8 字节对齐的——因此只需屏蔽 BIR 即可。

The format of Message Control is as follows:
消息控制格式如下:

Bit 15  第 15 位 Bit 14  位 14 Bits 13-11  位 13-11 Bits 10-0  位 10-0
Enable  启用 Function Mask  功能掩码 Reserved  已保留 Table Size  表格大小

Table Size is N - 1 encoded, and is the number of entries in the MSI-X table. This field is Read-Only.
表大小为 N-1 编码,表示 MSI-X 表中的条目数。此字段为只读。

Now you have all the information you need to find the MSI-X table:
现在你已掌握寻找 MSI-X 表所需的所有信息:

Bits 127-96  位 127-96 Bits 95-64  位 95-64 Bits 63-32  位 63-32 Bits 31-0  位 31-0
Vector Control (0)  矢量控制(0) Message Data (0)  消息数据 (0) Message Address High (0)
消息地址高位(0)
Message Address Low (0)  消息地址低(0)
Vector Control (1)  矢量控制(1) Message Data (1)  消息数据 (1) Message Address High (1)
消息地址高位(1)
Message Address Low (1)  消息地址低位(1)
... ... ... ...
Vector Control (N - 1)
矢量控制(N - 1)
Message Data (N - 1)
消息数据(N - 1)
Message Address High (N - 1)
消息地址高位(N - 1)
Message Address Low (N - 1)
消息地址低位(N - 1)

Vector Control is as follows:
矢量控制如下:

Bits 31-1  位 31-1 Bit 0  第 0 位
Reserved  已保留 Masked  已屏蔽

Note that Message Address is is 4-byte aligned, so, again, mask the low bits. The interrupt is masked if Masked is set to 1.
注意,消息地址是 4 字节对齐的,因此再次需要屏蔽低位。如果 Masked 设置为 1,则中断被屏蔽。

Message Address and Data are as they were for MSI - architecture specific. However, unlike with MSI, you can specify independent vectors for all the interrupts, only limited by having the same upper 32-bit message address.
消息地址和数据与 MSI 时相同——特定于架构。然而,与 MSI 不同的是,您可以为所有中断指定独立向量,仅受限于拥有相同的 32 位高位消息地址。

Multi-function Devices  多功能设备

Multi-function devices behave in the same manner as normal PCI devices. The easiest way to detect a multi-function device is bit 7 of the header type field. If it is set (value = 0x80), the device is multi-function -- else it is not. Make sure you mask this bit when you determine header type. To detect the number of functions you need to scan the PCI configuration space for every function - unused functions have vendor 0xFFFF. Device IDs and Class codes vary between functions. Functions are not necessarily in order - you can have function 0x0, 0x1 and 0x7 in use.
多功能设备的行为与普通 PCI 设备相同。检测多功能设备最简单的方法是检查头部类型字段的第 7 位。如果该位被设置(值为 0x80 ),则设备为多功能设备——否则不是。在确定头部类型时,务必屏蔽此位。要检测功能数量,需要扫描 PCI 配置空间中的每个功能——未使用的功能具有供应商 0xFFFF 。设备 ID 和类代码在不同功能之间可能不同。功能不一定按顺序排列——可能正在使用功能 0x00x10x7

Disclaimer  免责声明

This text originates from "Pentium on VME", unknown author, md5sum d292807a3c56881c6faba7a1ecfd4c79. The original document is apparently no longer present on the Web ...
此文本源自“Pentium on VME”,作者未知,md5sum 值为 d292807a3c56881c6faba7a1ecfd4c79。原文件显然已无法在网络上找到...

Closest match: [2] 最接近匹配:[2]

References  参考文献

  • PCI Local Bus Specification, revision 3.0, PCI Special Interest Group, August 12, 2002
    PCI 本地总线规范,修订版 3.0,PCI 特别兴趣小组,2002 年 8 月 12 日

See Also  相关内容

Articles  文章

External Links  外部链接

Personal tools
Variants
Actions
Navigation 导航
About 关于
Toolbox 工具箱
In other languages 在其他语言中