【PCIe】配置空间

【PCIe】配置空间介绍PCI/PCIe配置空间。

大家好,又见面了,我是你们的朋友全栈君。

简介

PCI/PCIe设备有自己的独立地址空间,这部分空间会映射到整个系统的地址空间。

映射地址在BIOS/UEFI下指定(如果有的话,对于使用非BIOS启动的OS,不清楚),它有两种类型,一种是MMIO,一种是IO。对于MMIO的访问,跟访问内存的方式一样,它从称为PCIEXBAR的基地址开始,有很大的一段空间,这个PCIEXBAR的值根据不同的平台可能不同,大致可能值有0xC0000000、0xE0000000等,关于这个值是怎么使用的后面的章节会讲到;对于IO,它是一种比较老的访问PCI/PCIe设备的方式,而且占有的空间相比MMIO非常小,好像只有64K的空间。

PCI/PCIe设备使用的空间也有两个部分,一部分称为配置空间(通过MMIO);另一部分通过配置空间的BAR寄存器指定,是设备实现功能所需要用到的地址空间(有MMIO也有IO, 不过IO用的比较少了)。

PCI/PCIe配置空间的访问方式

PCI/PCIe设备的配置空间通过PCIEXBAR加上设备的Bus、Device、Fun号的转换来得到,BDF到地址的转换关系如下:

/**
  Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an
  address that can be passed to the PCI Library functions.

  @param  Bus       PCI Bus number. Range 0..255.
  @param  Device    PCI Device number. Range 0..31.
  @param  Function  PCI Function number. Range 0..7.
  @param  Register  PCI Register number. Range 0..255 for PCI. Range 0..4095
                    for PCI Express.

  @return The encoded PCI address.

**/
#define PCI_LIB_ADDRESS(Bus,Device,Function,Register)   \
  (((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20))

其中的Register是具体要访问的寄存器。

这是最常用的一种方式,通过将B/D/F转换成MMIO的地址,之后就可以通过MMIO的方式来访问,下面是一个例子:

UINT8
EFIAPI
PciExpressRead8 (
  IN      UINTN                     Address
  )
{
  ASSERT_INVALID_PCI_ADDRESS (Address);
  return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
}

不过这里有个问题,通过PCI_LIB_ADDRESS得到的并不是实际的系统地址空间,它算是一个偏移,还需要加上一个基地址(就是这个通过函数GetPciExpressBaseAddress()得到的)。在UEFI中这个基地址被设置成一个PCD变量:PcdPciExpressBaseAddress。它的值根据不同平台可能会不同。

不过重点不是它的值,重点是如何设置这个值,因为只有设置了这个值才能使用上面说的方式来读写PCI/PCIe配置空间。

而PCIEXBAR也是要写到PCI设备的配置空间中的,它会被写到B0/D0/F0/R060h这个寄存器(不同平台可能不同)。

这里就遇到了一个问题,该通过什么方式来写这个值呢?

实际上,需要注意几点:

1. 上述提供的访问PCI/PCIe配置空间的方式是PCIe的方式;

2. 早期在没有PCIe的时候,要访问配置空间时,使用的是两个IO端口,CFCh和CF8h,通过往一个端口指定寄存器,另一个端口写值的方式为指定寄存器赋值。

所以我们要注意,有两个配置空间的方式:

1. 传统方式,写IO端口CFCh和CF8h。只能访问PCI/PCIe设备的开始256个字节(因为PCI设备的配置空间本来就只有256个字节);

2. PCIe的方式,就是上面提到的方式,它可以方位4K个字节的配置空间。

PCI配置空间

由于PCI/PCIe设备分为Bridge和Agent两种,所以配置空间也有两种类型:

其中Agent的配置空间类型称为Type 00h:

【PCIe】配置空间

简单介绍其中的几个寄存器的意义:

Vendor ID,Device ID:标记了一个设备的生产厂商和具体的设备,比如Intel的设备Vendor ID通常是0x8086,Device ID就需要厂家自定义了,总之能够识别到具体是哪个设备就可以了。

Status:设备状态字,具体每个BIT的意义见下图:

【PCIe】配置空间

Command:设备状态字:

【PCIe】配置空间

Base Address Registers:决定PCI/PCIe设备空间映射到系统空间具体位置的寄存器,映射方式有两种,分别是IO和Memory映射:

【PCIe】配置空间

【PCIe】配置空间

处理器系统资源分为IO资源和MMIO资源两种,因此PCI/PCIe空间地址对应也有两种。

下面是Bridge的配置空间,它的类型被称为Type 01h:

【PCIe】配置空间

Type 01h中也有Vendor ID,Device ID,Status,Command等寄存器。

另外需要注意的是这里的BAR计算得到的系统空间是该桥下挂的所有设备的系统空间的总和。

另外Subordinate Bus Number、Secondary Bus Number和Primary Bus Number,这些寄存器共同确定了该桥上行和下行的所有Bus号。

PCIe配置空间

PCIe是在PCI基础上发展的协议,PCIe也有上述的PCI配置空间,并且在此基础之上进行了扩展,其扩展形式是通过一种称为Capability的寄存器块来完成的。

PCI配置空间的大小是256个字节,即0x00~0xFF,而PCIe的配置空间扩大到了0x00~0xFFF,下图是具体的布局。

【PCIe】配置空间

在原来的配置空间中,有一个寄存器指定了第一个Capability的位置,而第一个Capability又指定下一个Capability,构成了一串Capability,具体如下图所示:

【PCIe】配置空间

各个不同的Capability的作用不同,且不同的设备有不同的Capability,在这里不一一介绍了。

其它说明

处理器系统中会为所有的PCI/PCIe设备留足足够的空间,但是几乎没有系统会满配,所以很多的配置空间实际上是空的,此时如果去访问,就会得到全FF,表示设备不存在。

下面是linux下访问PCI/PCIe配置空间的一个例子:

【PCIe】配置空间

注:以上是一个Intel网卡的PCI/PCIe配置空间,这是虚拟机下的结果,真实机器上可能有所不同。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149973.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月17日 下午5:36
下一篇 2022年6月17日 下午5:36


相关推荐

  • hwclock设置时间

    hwclock设置时间功能说明 显示与设定硬件时钟 nbsp 语 法 hwclock adjust debug directisa hctosys show systohc test utc version setdate lt 日期与时间 gt nbsp 补充说明 在 Linux 中有硬件时钟与系统时钟等两种时钟 硬件时钟是指主机板上的时钟设备 也就是通常

    2026年3月18日
    2
  • Facebook 秘钥散列

    Facebook 秘钥散列先下载OpenSSL工具执行这个命令keytool-exportcert-aliasandroiddebugkey-keystoredebug.keystore>c:\openssl\bin\debug.txt其中androiddebugkey是你xxx.keystore文件的路径,debug是你.keystore文件的名字然后路径cd到openssl文件夹下的bin目录执行opensslsha1-binarydebug.txt>debug_sha.t

    2022年5月15日
    45
  • 智谱 GLM-4.7-Flash 模型发布并开源,可免费调用

    智谱 GLM-4.7-Flash 模型发布并开源,可免费调用

    2026年3月12日
    4
  • 百度浏览器评测

    百度浏览器评测百度今年在客户端方面的动作不断 目前已经推出了百度输入法 百度电脑管家 百度安全卫士 百度影音 百度压缩软件 而现在 百度客户端领域的重要产品百度浏览器已经进入了测试阶段 不久后将正式对外发布 百度在其公关稿里称 百度浏览器具备以下几点特性 第一 整合百度平台的热门应用 使用户一键触达 第二 采用沙箱安全技术将用户电脑与病毒木马隔离 第三 融合百度搜索技术的智能地址栏 第四 界面设计

    2026年3月17日
    2
  • Mysql分库分表实战(一)——一文搞懂Mysql数据库分库分表

    Mysql分库分表实战(一)——一文搞懂Mysql数据库分库分表由于业务需要 需要对 Mysql 数据库进行分库分表 故而最近一直在整理分库分表的相关知识 现手上的工作也告一段落了 抽空将自己最近的学习结果转化为博文 分享给大家 本博文打算做成一个系列的 首先是分库分表的理论知识的了解 其次是基于 Java 编程语言的分库分表的框架的开发 最后是分库分表的编制 让大家不仅仅从理论上了解 mysql 的分库分表 通过代码来更深层次的了解 理论是如何落地到实践的 最后非常感

    2026年3月20日
    2
  • 驱动开发必备硬件知识「建议收藏」

    驱动开发必备硬件知识「建议收藏」综述:在嵌入式领域,可分为硬件开发和软件开发。对于软件开发又可分为底层开发(模块驱动编写,uboot,内核),上层开发(应用,QT)。作为一名软件驱动开发的工程师,我们不需要去设计硬件的原理图,PCB。我们只需看懂硬件开发人员提供的硬件模块时序就行了,但是我们应该也需了解如下硬件知识。      一)处理器     1,可分为通用处理器(单片机,ARM),数字处理器(DSP),其他专用处理器…

    2022年7月22日
    13

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号