来源:https://www.jianshu.com/p/574e9a2cbc4e

每个PCIe设备,有这么一段空间,Host软件可以读取它获得该设备的一些信息,也可以通过它来配置该设备,这段空间就叫做PCIe的配置空间。不同于每个设备的其它空间,PCIe设备的配置空间是协议规定好的,哪个地方放什么内容,都是有定义的。PCI或者PCI-X时代就有配置空间的概念,那时的配置空间如下:

图6.1

整个配置空间就是一系列寄存器的集合,其中Type 0是Endpoint的配置,Type 1是Bridge(PCIe时代就是Switch)的配置,都由两部分组成:64 Bytes的Header+192Bytes的Capability结构,后者是设备告诉Host它有多牛逼,都会什么绝活。

进入PCIe时代,PCIe能耐更大,192 Bytes不足以罗列它的绝活。为了保持后向兼容,又要不把绝活落下,怎么办?很简单,我扩展后者的空间,整个配置空间由256 Bytes扩展成4KB,前面256 Bytes保持不变:

图6.2

PCIe有什么能耐(Capability)我们不看,我们先挑软柿子捏,先看看只占64 Bytes的Configuration Header。

图6.3

像Device ID,Vendor ID,Class Code和Revision ID,是只读寄存器,PCIe设备通过这些寄存器告诉Host软件,这是哪个厂家的设备、设备ID是多少、以及是什么类型的(网卡?显卡?桥?)设备。

其它的我们暂时不看,我们看看重要的BAR(Base Address Register)。

对Endpoint Configuration(Type 0),提供了最多6个BAR,而对Switch(Type 1)来说,只有2个。BAR是干什么用的?

每个PCIe设备,都有自己的内部空间,这部分空间如果开放给Host(软件或者CPU)访问,那么Host怎样才能往这部分空间写入数据,或者读数据呢?

我们知道,CPU只能直接访问Host内存(Memory)空间(或者IO空间,我们不考虑),不对PCIe等外设直接操作。怎么办?记得皇帝身边那个有根的太监吗?Root Complex,RC。RC可以为CPU分忧。

解决办法是:CPU如果想访问某个设备的空间,由于它不能(或者不屑)亲自跟那些PCIe外设打交道,因此叫太监RC去办。比如,如果CPU想读PCIe外设的数据,先叫RC通过TLP把数据从PCIe外设读到Host内存,然后CPU从Host内存读数据;如果CPU要往外设写数据,则先把数据在内存中准备好,然后叫RC通过TLP写入到PCIe设备。完美!

图6.4

上图例子中,最左边虚线的表示CPU要读Endpoint A的数据,RC则通过TLP(经历Switch)数据交互获得数据,并把它写入到系统内存中,然后CPU从内存中读取数据(紫色箭头所示),从而CPU间接完成对PCIe设备数据的读取。

具体实现就是上电的时候,系统把PCIe设备开放的空间(系统软件可见)映射到内存空间,CPU要访问该PCIe设备空间,只需访问对应的内存空间。RC检查该内存地址,如果发现该内存空间地址是某个PCIe设备空间的映射,就会触发其产生TLP,去访问对应的PCIe设备,读取或者写入PCIe设备。

一个PCIe设备,可能有若干个内部空间(属性可能不一样,比如有些可预读,有些不可预读)需要映射到内存空间,设备出厂时,这些空间的大小和属性都写在Configuration BAR寄存器里面,然后上电后,系统软件读取这些BAR,分别为其分配对应的系统内存空间,并把相应的内存基地址写回到BAR。(BAR的地址其实是PCI总线域的地址,CPU访问的是存储器域的地址,CPU访问PCIe设备时,需要把总线域地址转换成存储器域的地址。)

图6.5

如上图例子,一个Native PCIe Endpoint,只支持Memory Map,它有两个不同属性的内部空间要开放给系统软件,因此,它可以分别映射到系统内存空间的两个地方;还有一个Legacy Endpoint,它既支持Memory Map,还支持IO Map,它也有两个不同属性的内部空间,分别映射到系统内存空间和IO空间。

来个例子,看一下一个PCIe设备,系统软件是如何为其分配映射空间的。

图6.6

上电时,系统软件首先会读取PCIe设备的BAR0,得到数据:

图6.7

然后系统软件往该BAR0写入全1,得到:

图6.8

BAR寄存器有些bit是只读的,是PCIe设备在出厂前就固定好的bit,写全1进去,如果值保持不变,就说明这些bit是厂家固化好的,这些固化好的bit提供了这块内部空间的一些信息:

怎么解读?低12没变,表明该设备空间大小是4KB(2的12次方),然后低4位表明了该存储空间的一些属性(IO映射还是内存映射,32bit地址还是64bit地址,能否预取?做过单片机的人可能知道,有些寄存器只要一读,数据就会清掉,因此,对这样的空间,是不能预读的,因为预读会改变原来的值),这些都是PCIe设备在出厂前都设置好的,提供给系统软件的信息。

然后系统软件根据这些信息,在系统内存空间找到这样一块地方来映射这4KB的空间,把分配的基地址写入到BAR0:

图6.9

从而最终完成了该PCIe空间的映射。一个PCIe设备可能有若干个内部空间需要开放出来,系统软件依次读取BAR1,BAR2。。。,直到BAR5,完成所有内部空间的映射。

上面主要讲了Endpoint的BAR,Switch也有两个BAR,今天不打算讲,下节讲TLP路由,再回过头来讲。继续说配置空间。

前面说每个PCIe设备都有一个配置空间,其实这样说是不准确的,而是每个PCIe设备至少有一个配置空间。一个PCIe设备,它可能具有多个功能(function),比如既能当硬盘,还能当网卡。每个功能对应一个配置空间。

在一个PCIe拓扑结构里,一条总线下面可以挂几个设备,而每个设备可以具有几个功能,如下所示:

图6.10

因此,在整个PCIe系统中,只要知道了Bus+Device+Function,就能找到对应的Function。寻址基本单元是功能(function),它的ID就由Bus+Device+Function组成 (BDF)。一个PCIe系统,可以最多有256条Bus,每条Bus上可以挂最多32个Device,而每个Device最多又能实现8个Function,而每个Function对应着4KB的配置空间。上电的时候,这些配置空间都是需要映射到Host的内存空间,因此,需要占用内存空间是:256*32*8*4KB =256MB。在这个动辄4GB、8GB内存的时代,256MB算不了什么。

系统软件是如何读取Configuration空间呢?不能通过BAR中的地址,为什么?别忘了BAR是在Configuration中的,你首先要读取Configuration,才能得到BAR。前面不是系统为所有可能的Configuration预留了256MB内存空间吗?系统软件想访问哪个Configuration,只需指定相应Function对应的内存空间地址,RC发现这个地址是Configuration映射空间,就会产生相应的Configuration Read TLP去获得相应Function的Configuration。

再回想一下前面介绍的Configuration Read TLP的Header格式:

图6.11

Bus Number + Device + Function就唯一决定了目标设备; Ext Reg Number + Register Number相当于配置空间的偏移。找到了设备,然后指定了配置空间的偏移,就能找到具体想访问的配置空间的某个位置。

结束前,强调一下,只有RC才能发起Configuration的访问请求,其他设备是不允许对别的设备进行Configuration读写的。

作者:idorax
链接:https://www.jianshu.com/p/574e9a2cbc4e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

[转载] PCIE配置和地址空间相关推荐

  1. PCIe的内存地址空间、I/O地址空间和配置地址空间

    PCIe的内存地址空间.I/O地址空间和配置地址空间 pci设备与其它接口的设备(如i2c设备)最大的不同是存在内存地址空间和配置地址空间,本文分析一下它们的用途. 首先区分一下IO空间和内存空间 c ...

  2. 7.PCIE配置空间读写软件

    软件-7.PCIE配置空间读写 软件-7.PCIE配置空间读写 软件-7.PCIE配置空间读写 软件读写配置空间 驱动层接口 原理分析 驱动层代码接口 驱动层接口与原理 相关参考 基础知识 raw_p ...

  3. 转载 PCIe学习(二):PCIe DMA关键模块分析之一

    版权声明:本文为CSDN博主「CLGo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/cllovexyh/a ...

  4. 转载 PCIe学习(三):PCIe DMA关键模块分析之二

    版权声明:本文为CSDN博主「CLGo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/cllovexyh/a ...

  5. CS9:转载:怎样配置Win Radius 当使用Cisco交换机时

    客户问题: 希望咨询Windows Server 2003作为Radius server时系统和交换机需要的配置方法. 提供参考举例: 安装IAS Server,IP地址为172.16.1.200. ...

  6. PCIe配置空间和PCI设备中的寄存器

    1.访问PCI配置空间,PCI基本配置空间的读写使用下列函数: 原型定义在<linux/pci.h> int pci_read_config_byte(struct pci_dev *pd ...

  7. 2020-11-05 转载 国内配置Electron开发环境的正确方式

    原作者: 国内配置Electron开发环境的正确方式 https://blog.yasking.org/a/zh-install-electron-development-2020.html http ...

  8. [转载]hostapd配置解析

    转载自:老丁的Linux:http://laoding.blog.51cto.com/980622/1697015 hostapd 的配置文件位于 /etc/hostapd/hostapd.conf ...

  9. 转载:配置nginx支持pathinfo功能

    原文地址:http://linuxguest.blog.51cto.com/195664/694319 nginx模式不支持pathinfo模式,类似info.php/hello形式的url会被提示找 ...

最新文章

  1. 在疫情防控一线,技术能发挥什么作用?
  2. ZOJ 2334 HDU 1512 Monkey King
  3. POJ 1459--最大流算法
  4. 键盘各个键对应的ASCLL值
  5. CentOS7.2最小化安装后系统优化
  6. 洛谷 - P2761 软件补丁问题(spfa+状压)
  7. Codeforces Round #709 (Div. 1) C. Skyline Photo dp + 单调栈优化
  8. Jquery提交form表单
  9. Thymeleaf 简介、教程
  10. svn ignore 的用法
  11. jQuery lazyload
  12. Ubuntu通过apt-get安装指定版本和查询软件源有多少个版本
  13. 谈谈纽微特3万SIP奖金的事
  14. DELPHI2007 安装ACTIVEX插件的方法
  15. JavaScript--对象类型详解
  16. foobox 3.8(foobar2000 CUI配置)
  17. 51单片机实训(一)————Keil 基本操作
  18. 计算机计算累计公式,““请问Excel表格求的合计数为什么和用计算器累加出的合计数不一致...
  19. 【机器学习】【可解释性】LIME
  20. 邮箱客户端设置 服务器设置,263邮箱客户端设置

热门文章

  1. 6-8 简单阶乘计算(10 分) 本题要求实现一个计算非负整数阶乘的简单函数。
  2. MOOC清华《程序设计基础》第1章第5题:银行存款问题
  3. SQLServer 导入mdf和ldf文件出现:无法打开物理文件 D:\XX.mdf。操作系统错误 5:5(拒绝访问。)的解决方案
  4. xp系统怎么启动任务计划服务器,WinXP系统如何关闭计划任务服务?关闭计划任务服务的方法...
  5. DSP时钟以及QP的TICKS
  6. 香港理工大学林婉瑜博士实验室招收全奖博士生/博士后
  7. 存储ic载板_PCB行业分析:从PCB、IC载板到类载板
  8. mini usb 管脚图
  9. shape形状标签可实现corners 圆角效果
  10. Android Studio开发之蓝牙通信