Bios实习 学习篇- 6.PCIe学习(3)

配置空间深度解析(硬件寄存器级)

在PCIe里,每个设备都有一块配置空间(4KB),里面存: 这个设备是谁(厂商ID) 它是干嘛的(class code) 它用哪些地址(BAR) 怎么控制它(command寄存器)

00: 86 80 0e 10 07 04 10 00 00 00 00 02 00 00 00 00
10: 00 00 00 00 00 00 00 00 00 00 00 00 81 01 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 86 80 00 00
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00: 86 80 0e 10 07 04 10 00 00 00 00 02 00 00 00 00
    ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑
    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F

| 偏移 | 字节数 | 十六进制值 | 实际含义 |
|------|--------|-----------|---------|
| 0x00 | 2字节 | 86 80      | Vendor ID = 0x8086 (Intel) |
| 0x02 | 2字节 | 0e 10      | Device ID = 0x100e (Intel 82540EM网卡) |
| 0x04 | 2字节 | 07 04      | Command寄存器 = 0x0407 (启用I/O+内存+总线主控) |
| 0x06 | 2字节 | 10 00      | Status寄存器 = 0x0010 |
| 0x08 | 1字节 | 00         | Revision ID = 0 |
| 0x09 | 3字节 | 00 00 02   | Class Code = 0x020000 (网络控制器) |

而这块配置空间的“前64字节”叫:Header头部

这个Header不是统一格式,而是分两种:

1.Type 0 Header(端设备)

用于:真正干活的设备(Endpoint)

比如:显卡 、网卡、NVMe SSD ,Type 0 = “我是设备,请通过这些地址访问我”

2.Type 1 Header(桥设备)

用于:PCIe桥(Bridge)

比如:Root Complex(CPU侧)、PCIe Switch、PCIe-to-PCI桥,Type 1 = “我不是设备,我是中转站,我负责转发数据”

// Offset 0x00-0x3F (64B)
struct Type0_Header {
    uint16_t vendor_id;      // 0x00: 0xFFFF = 无设备
    uint16_t device_id;      // 0x02: 厂商分配
    uint16_t command;        // 0x04: 关键控制寄存器
    uint16_t status;         // 0x06: 状态寄存器
    uint8_t  revision_id;    // 0x08: 修订版本
    uint8_t  class_code[3];  // 0x09-0x0B: 0x030000 = VGA
    uint8_t  cache_line_sz;  // 0x0C: 缓存行大小
    uint8_t  latency_timer;  // 0x0D: PCI遗留
    uint8_t  header_type;    // 0x0E: [7]=多功能位, [6:0]=0x00
    uint8_t  bist;           // 0x0F: 内建自检
    
    // BAR寄存器 (关键!)
    uint32_t bar[6];         // 0x10-0x24: 基地址寄存器
    uint32_t cardbus_cis;    // 0x28: CardBus CIS指针
    
    uint16_t subsystem_vendor_id; // 0x2C
    uint16_t subsystem_id;   // 0x2E
    
    uint32_t rom_base;       // 0x30: ROM基地址
    uint8_t  cap_ptr;        // 0x34: 能力列表指针
    
    uint8_t  reserved[7];    // 0x35-0x3B
    uint8_t  interrupt_line; // 0x3C: IRQ线路
    uint8_t  interrupt_pin;  // 0x3D: 中断引脚 (1-4)
    uint8_t  min_grant;      // 0x3E: 最小延迟
    uint8_t  max_latency;    // 0x3F: 最大延迟
};
// 与Type 0前16字节相同
struct Type1_Header {
    // 0x00-0x0F: 同Type 0
    
    // 0x10-0x17: Primary/Secondary Bus配置
    uint8_t  primary_bus;    // 0x18: 上游总线号
    uint8_t  secondary_bus;  // 0x19: 下游总线号
    uint8_t  subordinate_bus; // 0x1A: 从属总线号
    uint8_t  secondary_latency; // 0x1B
    
    // 0x1C-0x1F: I/O基地址/限地址
    uint8_t  io_base;        // 0x1C: I/O空间基地址
    uint8_t  io_limit;       // 0x1D: I/O空间限地址
    
    // 0x20-0x27: Secondary Status/IO寄存器
    uint16_t secondary_status; // 0x1E
    uint16_t memory_base;    // 0x20: 内存空间基地址
    uint16_t memory_limit;   // 0x22: 内存空间限地址
    
    uint16_t prefetchable_memory_base; // 0x24
    uint16_t prefetchable_memory_limit; // 0x26
    
    uint32_t prefetchable_base_upper; // 0x28
    uint32_t prefetchable_limit_upper; // 0x2C
    
    uint16_t io_base_upper;  // 0x30
    uint16_t io_limit_upper; // 0x32
    
    uint8_t  cap_ptr;        // 0x34: 能力指针
    uint8_t  reserved[3];    // 0x35-0x37
    
    uint32_t expansion_rom;  // 0x38: 扩展ROM
    
    uint8_t  interrupt_line; // 0x3C
    uint8_t  interrupt_pin;  // 0x3D
    uint16_t bridge_control; // 0x3E: 桥控制寄存器
};

3.Capability结构链(硬件自动构建)

Capability链 = PCIe设备用“链表”方式挂载的一组“高级功能描述块”,这些结构是设备硬件自己提供的,不是CPU/软件创建的

为什么需要 Capability?前面那64B Header(你刚看的 struct)是固定格式

但问题是:设备功能越来越复杂,比如:MSI中断、PCIe链路信息、电源管理、热插拔、SR-IOV(虚拟化)

⚠️ 如果全塞进固定Header: 不够用、不灵活

所以PCIe设计了:🧠 扩展机制:Capability(能力结构)

Capability“链”的本质

它其实是一个单向链表(linked list)

配置空间(4KB):
[Header]
   ↓ (cap_ptr = 0x40)
[Capability A]
   ↓ (next_ptr)
[Capability B]
   ↓
[Capability C]
   ↓
NULL

起点:Header Type 寄存器(偏移 0x0E)+ Status 寄存器(偏移 0x06,bit 4 = “Capabilities List” 置 1)+ Capabilities Pointer(偏移 0x34,8 位指针,指向第一个 Capability 的起始偏移,通常 dword 对齐)。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务