目录
一、概述
主要总结一下掌握PCI驱动应该具备的PCI的基本知识
二、PCI
2.1 基本概念
下面通过一张图说明基本概念:
- PCI总线空间与处理器空间的隔离
PCI总线域(地址空间)和存储器域是通过HOST主桥进行隔离的,HOST主桥也称为PCI主桥,PCI总线控制器,它作为两个地址空间的桥梁:处理器通过HOST主桥才能访问PCI设备,PCI设备通过HOST主桥才能访问存储器。
- PCI设备
在PCI总线中有三类设备:PCI主设备,PCI从设备,桥设备
一个PCI设备可以是主设备也可以是PCI从设备,PCI规范将主从设备统称为PCI Agent设备。
HOST主桥是一个特殊的PCI设备,该设备可以获取PCI总线控制权访问PCI设备,也可以被PCI设备访问。但HOST主桥不是PCI设备。
PCI桥可以连接两条总线,上游PCI总线和下游PCI总线,其扩展的所有PCI总线属于同一个PCI域
HOST主桥、PCI桥、PCI设备构成了一棵PCI树形结构
2.2 PCI资源
一个设备通常具有以下资源:I/O port, MMIO,interrupt, DMA
2.2.1 配置空间
PCI是支持自举的总线,实现这一功能的关键在于每个PCI设备都有自己的配置空间,我们知道在一棵PCI总线的树上,可以通过BDF(bus:device:function)唯一的确定一个PCI设备。这样我们可以通过HOST主桥,通过指定BDF的方式,访问特定PCI设备的配置空间。
以x86为例,它提供了两个I/O port来访问配置空间,分别为CONFIG_ADDRESS(0xCF8)和CONFIG_DATA(0xCFC)
CONFIG_ADDRESS寄存器结构如下图:
下面来看一个pci agent的配置空间:
- Vendor ID,Device ID 标识PCI设备
- Header Type,第7位为1表示多功能设备,为0表示单功能设备;6~0位为1表示PCI桥配置空间,为0表示PCI Agent配置空间
- BAR0~5,保存PCI设备使用的MMIO的基地址,注意这个地址属于PCI总线域,使用要有一个转换;另外,通过向BAR寄存器写入0xffffffff,再读取获取PCI设备使用的BAR空间的长度。
- Command 包含I/O和MMIO的是能 (linux pci_enable_device)
接下来看一下PCI桥的配置空间:
- subordinate bus number 存放当前PCI子树中,编号最大的PCI总线号
- secondary bus number 存放当前PCI子树中,编号最小的PCI总线号
- primary bus number 存放该PCI桥上游的PCI总线号
一个PCI 桥能管理的总线号的范围是[subordinate bus number, secondary bus number],当进行PCI设备枚举时设置,上述三个初始化时设置为0,可用来判断PCI桥是否被配置过。
- I/O Limit, I/O Base,存放该PCI子树下,所有PCI设备使用的I/O地址空间的范围
- Memory Limit, Momory Base 存放PCI子树下,所有PCI设备使用的存储器地址空间的范围
- Prefetchable Memory Limit, Prefetchable Memory Base
2.2.2 BAR空间
系统通过配置空间获得了PCI整个拓扑,就可以为PCI设备分配I/O port和 MMIO了,我们知道,通过配置空间可以获取上述资源的大小,而当我们通过DFS将资源分配给整个PCI系统时,就可以在BAR里面写上该PCI设备对应的基地址了
对于BAR,还有以下注意的点:
- BAR寄存器最低位确定该PCI设备访问类型:1代表I/O port, 0代表MMIO
- BAR分为可预取和不可预取的,一般可预期的主要是设备ram,ram具有每次读取后内容不自动改变性质,因此可以预取,将不需要的数据直接丢到。不可预取类型主要指设备寄存器,有些寄存器本身就是设备FIFO,每次读取完毕后数据可能会改变,因此不能预取
2.2.3 PCI 中断
PCI总线使用INT A#, INT B#, INT C#, INT D#向处理器发送请求。但是PCI总线规范没有规定PCI设备的INT x信号如何与中断控制器相连,为此系统软件使用中断路由表存放INT x信号与中断控制器的连接关系。如在x86系统中由ACPI表中记录着中断路由表:
上表就说明了pci设备的连接关系,获取到这个信息,就可以处理对应设备的中断了
2.2.4 DMA
分为DMA read、 DMA write
简单说就是PCI设备将要写的数据放到pci域地址由主桥转换成存储器域地址从而完成写操作。
2.3 处理器访问PCI设备流程
主要分成两种情况:
- 处理器读写配置空间,使用ID译码方式(Bus Number, Device Number, Function number, Register num)
- 处理器读写BAR空间, 使用地址译码方式(存储器译码或者I/O 译码)
三、PCIe
PCI总线使用并行总线结构,在同一条总线上所有外部设备共享总线带宽,而PCIe总线使用高速差分总线,并采用端到端的连接方式,在同一条PCIe链路上只能各连一个设备,互为数据发送端和接收端。
3.1 基本概念
- lane
PCIe总线物理链路的一个数据通路,有两组差分信号(RX, TX),四根信号线。PCIe链路可以由多条Lane组成,如x1,x2,x4,x8,x12,x16,x32宽度的PCIe链路。PCIe总线物理链路间的数据传送使用基于时钟的同步传送机制,接收端使用CDR提取接收时钟,从而进行数据同步的操作。
- switch
3.2 PCIe资源
3.2.1 扩展配置空间
PCI配置空间由64字节组成(0x00~0x3F)有些设备还扩展了0x40~0xFF这段配置空间,这段空间主要存放一些与MSI/MSI-X和电源相关的一些Capability结构。在x86处理器上,上述空间统一用I/O port访问(CONFIG_ADDRESS/CONFIG_DATA)。除此之外,对于PCIe来说,它还支持0x100~0xFFF,从而将PCIe最大配置空间扩展到4K,这部分使用ECAM访问(MMIO)
PCIe的Capability结构示意如下图:
一个PCIe设备可以包含多个Capability结构,包括电源管理相关,PCIe总线结构相关,与中断相关的结构。每个Capability是一个单链表结构——Pointer指针指向下一个Capability结构的起始地址,而最后一个Capability的Pointer为0。每个Capability以ID选项唯一标识自身。
3.2.2 MSI/ MSI-X
MSI Capability结构有四种方式:
- message control控制是否使用64-bit地址,使能等特性
MSI capability可以类比于一个中断控制器的特性,Mask bits,由于MSI 最多使用32个中断向量,使用Mask屏蔽对应的中断请求。当mask为1时,产生中断时,对应的pending bits表示中断还没有向中断控制器提交,当mask清空时,提交中断,这样可以防止处理器丢失中断请求。
PCI设备通过MSI触发中断的方式是将Message Data的值写入到Message Address对应的地址中去
MSI-X
MSI最多只支持32个中断向量,且要求中断向量连续,为了改进,引入MSI-X,其Capability结构如下:
MSI-X使用MSI-X Table的形式,将多个entry存在BAR空间而非capability中,从而扩展了MSI-X中断数()
其中Message Control可以参考下表:
- Table BIR 存放MSI-X Table所在位置——bar空间的编号,Table Offset则对应在相应BAR空间的偏移
- PBA /PBA offset 描述Pending Table
看一下MSI-X Table表项结构:
- 其中vector就是mask
其中Message Address字段存储PCIe域地址,通过上层桥转换为存储域地址:
这个地址是APIC的MMIO地址:
fec00000-fec003ff : IOAPIC 0
fed00000-fed003ff : HPET 0
fed00000-fed003ff : pnp 00:04
fee00000-fee00fff : Local APIC
Message Data的格式:
系统软件初始化好vector对应Destination ID的对应关系,PCIe产生中断时将Message Data数据写入Message Address,就会产生Interrupt Message 总线事务,从而向CPU提交中断请求。