PCIE学习系列 二(PCIE枚举)

先提出几个问题,带着问题来分析,如果这些问题你都知道答案,那么也不用看这篇文章。

  1. 如何知道整个系统有哪些PCIe设备?
  2. 如何读写某个PCIe设备的数据?
  3. 什么叫PCIe枚举?
  4. 枚举的步骤是什么?
  5. 按什么顺序枚举设备?
  6. 每个PCIe设备所需空间大小如何确定?

PCIe枚举

PCIE枚举的作用是自动检测和识别连接到PCIe总线上的设备,并对这些设备进行初始化和配置,以便操作系统和应用程序可以与这些设备进行通信和控制。
枚举的发起者是计算机系统中的主机,通常是基本输入/输出系统(BIOS)。遍历PCIe总线上的设备,自动检测和识别每个设备的存在,使得系统和驱动开发人员可以知道有哪些设备连接到了PCIe总线上。
PCIe枚举过程为每个PCIe设备分配IO地址、内存地址和中断等资源。这确保了设备能够正常访问系统资源,并避免了冲突和资源浪费的问题。
后面介绍到的配置空间读取都是使用的内存映射方式,而不是IO方式访问。

PCIe枚举的步骤

PCIe的枚举步骤大致如下:

  1. PCIe控制器初始化,初始化PCIe控制器,为每个PCIe控制器分配资源;
  2. 枚举根节点,根结点通常是集成在CPU的内部;
  3. 枚举子设备,根据配置空间读出来的信息来判断是否存在设备;
  4. 遍历整个PCIe结构,扫描所有PCIe节点;
  5. 分配资源,当枚举到某一个设备后,host就会给他分配资源,IO空间、MEM空间,现在一般只用MEM空间;
  6. PCIe设备配置空间的一些寄存器填写(bar、command等);

当枚举完成后,每个PCIe设备的地址也都分配好了,通过Bar寄存器地址就可以知道对应设备的数据寄存器了。

如果对枚举这一部分有兴趣可以阅读一下Linux的源码
drivers\pci\probe.c
int pci_host_probe(struct pci_host_bridge *bridge)

枚举的顺序是怎么样的?由什么确定枚举顺序?

PCIe主控枚举采用的是深度优先的策略;每个总线都必须被分配一个唯一的总线号。Bus 0,通常分配给RC(Root Complex),配置软件分配总线号的过程中,首先从Bus 0/Device 0/Function 0开始搜索其他的设备。当找到一个设备之后,软件就给这个新设备分配一个与上一级总线的总线号不同的、数字更大的编号,一旦新总线被分配了一个总线号之后,软件就会从新总线继续搜索,而不是在上一级总线上继续搜索其他设备。这被称为“深度优先搜索(depth first search)。
由上面的方式可以知道,关于枚举总是先从BDF 0:0.0开始,并根据深度优先枚举,那么如果整个PCI拓扑不变,枚举的顺序也就不会变化了,即由硬件的PCIe拓扑连接方式决定。

如何判断当前PCIe设备是否在位?

一般枚举是通过Vendor ID或者Device ID来判断,如果读取出来的Vendor ID或Device ID为0xFFFF或者为0x0000,则说明是没有接正常的设备。

如何知道PCIe设备需要多大的Bar空间?

在host分配资源之前需要知道此PCIe设备需要多大的空间,host端会执行以下步骤来获取size:

  1. 向bar0寄存器写入0xffffffff,硬件设计的某些位是只读的,所以不会全写进去(硬件正是通过控制只读的位来设置设备所需的空间大小)
  2. 回读bar0寄存器,Bar寄存器的结构如下所示:关于bar寄存器的具体解读可以查看 PCIe学习系列一
    在这里插入图片描述
  3. 判断设备空间类型、计算size
    根据bar0,首先根据第0位来判断是IO类型还是MEM类型,然后根据第1、2位判断是32bit还是64bit,根据第3位判断是否可预取;
    如果地址是32bit,size = (~(bar_response & 0xf )) + 1,bar_response为回读的值
    例如写0xffffffff,回读的值为0xfff00008,那我们就知道这个类型为32bit可预取的mem空间,需要大小为1M;
    如果地址是64bit,此时就再去读取下一个bar的内容,所得的便是高32位,再加上低32位再去计算size,size = (~(((bar_upper_response << 32) | bar_response) & 0xf )) + 1,bar_response为bar0回读的值,bar_upper_response为之后一个bar回读的值;

主控制器如何分配空间?

主控制器根据计算得到的size分配空间,为了提高对设备的访问效率,分配给某个设备的Bar地址需要按照他所需要的size对齐。例如某个PCIe mem空间的基地址为0x58000000,某个设备所需空间为0x100000000(256M),则起始地址就会变成:0x60000000,那么0x58000000 ~ 0x60000000这一段空间就浪费了,所以在枚举的时候最好先分配size小的设备,避免造成资源的浪费。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值