目前用于访问PCIe配置空间寄存器的方法需要追溯到原始的PCI规范。为了发起PCI总线配置周期,Intel实现的PCI规范使用IO空间的CF8h和CFCh来分别作为索引和数据寄存器,这种方法可以访问所有PCI设备的255 bytes配置寄存器。Intel Chipsets目前仍然支持这种访问PCI配置空间的方法。

PCIe规范在PCI规范的基础上,将配置空间扩展到4K bytes,至于为什么扩展到4K,具体可以参考PCIe规范,这些功能都需要配置空间。原来的CF8/CFC方法仍然可以访问所有PCIe设备配置空间的头255 bytes,但是该方法访问不了剩下的(4K-255)配置空间。怎么办呢?Intel提供了另外一种PCIe配置空间访问方法。Intel Chipset通过将配置空间映射到内存地址空间,PCIe配置空间可以像对映射范围内的内存进行read/write一样来访问了。这种映射是由北桥芯片来完成的,但是不同芯片的映射方式也是不同的。

1、CF8h/CFCH Method

Intel Chipsets使用IO空间的CF8h/CFCh地址来访问PCI设备的配置寄存器,该方法同样可以访问PCIe设备的头255配置寄存器。

为了对已知PCI设备发起一个PCI总线配置周期,软件必须执行以下步骤:

  1. PCI设备的总线号必须被填写到IO地址CF8h的[23:16] bits

  2. PCI设备的设备号必须被填写到IO地址CF8h的[15:11] bits

  3. PCI设备的功能号必须被填写到IO地址CF8h的[10:8] bits

  4. 需要访问的寄存器双字地址必须被填写到IO地址CF8h的[7:2] bits

  5. CF8h的最高位为配置位,该位必须设置为1

  6. 对于写操作,将设备的特定信息组合成一个双字(4bytes)后,写到CFCh地址

  7. 对于读操作,将设备的特定信息组合成一个双字后,把数据从CFCh读回来

当执行6或者7步骤时,相应的PCI配置read/write cycle被Created by Intel Chipset,并在需要时传递到整个系统。在步骤4配置需要读写的寄存器地址时,该空间只有6位,也就说只有64个地址可写,但是PCI配置空间不是256吗?别急,记得是双字地址,一个Dword=4 bytes,也就是说4 * 64 = 256,刚好,不是吗?

2、Memory Mapped Method

PCIe规范为每个PCIe设备添加了更多的配置寄存器,空间为4K,尽管CF8h/CFCh方法仍然能够访问lower 255 bytes,但是必须提供另外一种方法来访问剩下的4K range寄存器。Intel的解决方案是使用了预留256MB内存地址空间,对这段内存的任何访问都会发起PCI 配置cycle。但是为什么是256MB???听我慢慢解释给大家听:犹豫4K的配置空间是directly mapped to memory的,那么PCIe规范必须保证所有的PCIe设备的配置空间占用不同的内存地址,按照PCIe规范,支持最多256个buses,每个Bus支持最多32个PCI devices,每个device支持最多8个function,也就是说:占用内存的最大值为:256 * 32 * 8 * 4K = 256MB。

这段256MB的内存区将根据intel chipset的不同,可以映射到系统内存映射范围内的任何位置,一般北桥芯片都会有一个寄存器来指明PCI配置空间的内存映射地址,它叫PCIe Configuration Register Base Address Register (BAR),如下图:

当软件访问指定PCIe设备的配置寄存器时,必须正确计算该寄存器映射到内存的具体地址,那么怎么计算呢,参考上图我们可以知道,busNo=0,deviceNo=0,funcNo=0的地址刚好是BAR,一条总线占用的最大空间计算如下:

SIZE_PER_BUS = 4K * 32 * 8 = 256K = 1M = 100000h

SIZE_PER_DEVICE = 4K * 8 = 8000h

SIZE_PER_FUNC = 4K = 1000h

访问总线号为busNo,设备号为DevNo,功能号为funcNo的offset寄存器的计算公式是:

Memory Address = PCIe Configuration Register Base Address Register (BAR)

+ busNo * SIZE_PER_BUS

+ devNo * SIZE_PER_DEVICE

+ funcNo * SIZE_PER_FUNC

+ offset

For example, to access the following configuration register:

    • PCI Express Configuration Register F0000000h

    • Bus Number 15h

    • Device Number 00h

    • Function Number 05h

    • Register Offset 84h

Memory Address = F0000000h + 15h * 100000h + 00h * 8000h  + 05h * 1000h + 84h

= F1505084h

现在我们可以从已知的busNo,devNo,funcNo和offset来计算映射后的内存地址,那么反过来,给定的内存地址,我们想知道这个地址的busNo, devNo, funcNo和offset信息,可以吗?当然可以,计算公式如下:

busNo = (Memory Address - BAR) / SIZE_PER_BUS;

devNo = (Memory Address - BAR - busNo * SIZE_PER_BUS) / SIZE_PER_DEVICE;

funcNo = (Memory Address - BAR - busNo * SIZE_PER_BUS

- devNo * SIZE_PER_DEVICE) / SIZE _PER_FUNC;

offset = Memory Address - BAR - busNo * SIZE_PER_BUS - devNo * SIZE_PER_DEVICE

- funcNo * SIZE_PER_FUNC;

又或offset = Memory Address & 0x0FFFh;(为什么是0x0FFFh?自己想想啦)

想起来了么?因此PCIe的配置空间大小就是4K啊。

3、芯片组的异同

上面说的BAR,也就是PCI配置空间寄存器映射到内存的基地址寄存器,在intel chipset中的实现方式也千差万别。在前期的intel chipset中,该寄存器被包含在芯片组(MCH ,GMCH)的内存控制器部分。

另外,由于被PCIe配置空间占用的256M内存空间会屏蔽掉DRAM使用该段内存区,大部分的Intel Chipset允许BIOS来配置该空间大小,因此在实际应用中,一般就应用前面几个总线号,BIOS通过检测PCIe总线的扩展深度来动态设置该映射内存区的大小,比如PM965芯片组,如果配置软件检测系统使用不大于64的总线号,那么该软件将编程内存映射大小为64M,剩下的(256M-64M = 192M)留给DRAM。

4、PCIe配置空间的内存映射对32bit系统的影响

由于PCIe配置空间占用了256M内存空间,而且该被占用空间对DRAM来说是不可用的,这意味着256M空间消失于系统内存,这在32bit系统中更为明显。

比如,在32 bit WINxp中,理论上可以访问到的内存是4G,如果4G空间都被DRAM给占用,由于PCIe的存在,被PCIe占用的那部分内存空间对OS来说是不可用的,莫名的消失了最多256M内存,这也是大部分Intel Chipset允许BIOS来配置该空间大小的原因。

在64 bit 系统中,不存在这个问题,因为系统可以访问超过4G的内存空间,Intel Chipset会包含控制逻辑把该PCIe的内存映射到above 4G,这样跟DRAM就没有冲突。在64bit系统中,不可能使用2的64次方的内存吧。哈哈,总会没有使用到的内存空间。

5、访问PCIe配置空间的C转换代码

//**********************************************************************

unsigned long PCIeBase = 0xF0000000UL;

unsigned long FinalAddress;

unsigned long Bus = 0;

unsigned long Device = 0;

unsigned long Function = 0;

unsigned long Register = 0;

//**********************************************************************

void Convert_to_Memory()

{

    FinalAddress = PCIeBase +

                        (Bus*0x100000UL) +

                        (Device*0x8000) +

                        (Function*0x1000) +

                        Register;

}

//**********************************************************************

void Convert_to_Register()

{

    Bus = (FinalAddress-PCIeBase) / (0x100000UL);

    Device = (FinalAddress-PCIeBase - (Bus*0x100000UL)) / (0x8000);

    Function = (FinalAddress-PCIeBase - (Bus*0x100000UL) -

    (Device*0x8000)) / (0x1000);

    Register = (FinalAddress) & (0x00000FFF)

}

如何访问pcie整个4k的配置空间的更多相关文章

  1. 怎样訪问pcie整个4k的配置空间

    眼下用于訪问PCIe配置空间寄存器的方法须要追溯到原始的PCI规范. 为了发起PCI总线配置周期,Intel实现的PCI规范使用IO空间的CF8h和CFCh来分别作为索引和数据寄存器,这样的方法能够訪 ...

  2. PCIe设备的配置空间

    关于PCI设备的配置空间网上已经有很多资料了,如下图就是PCI设备必须支持的64个字节的配置空间,范围为0x00-0x3f. 很多PCI设备仅仅支持者64字节的配置空间.PCI和PCIe配置空间的区别 ...

  3. 2.3 PCI桥与PCI设备的配置空间

    PCI设备都有独立的配置空间,HOST主桥通过配置读写总线事务访问这段空间.PCI总线规定了三种类型的PCI配置空间,分别是PCI Agent设备使用的配置空间,PCI桥使用的配置空间和Cardbus ...

  4. 【PCIE-2】---PCIE配置空间及访问方式简介

    对新手来说,第一步了解PCIE的相关基本概念,第二步了解PCIE配置空间,第三步深入研究PCIE设备枚举方式.本章主要总结第二步的PCIE配置空间 按照国际惯例,先提问题: 1. 什么是PCIE的配置 ...

  5. [转载]PCI/PCIe基础——配置空间

    转载地址:http://blog.csdn.net/jiangwei0512/article/details/51603525 PCI/PCIe设备有自己的独立地址空间,这部分空间会映射到整个系统的地 ...

  6. PCI、PCIE配置空间的訪问(MCFG,Bus,Device,Funtion)

    一般来说,在x86平台上,有两大类方式能够訪问这一区间的寄存器,   1,配置机制1#或者配置机制2#   訪问时借助in/out指令.请注意,这样的方式有别于一般的in/out指令訪问PCI的IO空 ...

  7. OCM_第十五天课程:Section6 —》数据库性能调优 _SQL 访问建议 /SQL 性能分析器/配置基线模板/SQL 执行计划管理/实例限制

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  8. PCI配置空间简介

    一.PCI配置空间简介 PCI有三个相互独立的物理地址空间:设备存储器地址空间.I/O地址空间和配置空间.配置空间是PCI所特有的一个物理空间.由于PCI支持设备即插即用,所以PCI设备不占用固定的内 ...

  9. 在Linux下访问Windows共享目录的配置方法

    在Linux下访问Windows共享目录的配置方法 1.在Windows上设置一个共享目录 如:将d:\RedHat_disk设置为共享目录 2.在Windows上创建一个用户,如tommy,密码11 ...

随机推荐

  1. HashMap原理总结

    来总结一下HashMap的原理 1.HashMap当中有一个内部类,它叫Node,然后这个Node呢,它其实是实现了Map.Entry接口,这个接口当中有几个抽象的方法和几个具体的方法.其中Map.E ...

  2. 洛谷 [P1314] 聪明的质检员(NOIP2011 D2T2)

    ###一道二分答案加前缀和### 题目中已经暗示的很明显了 "尽可能靠近" " 最小值" 本题的主要坑点在于 long long 的使用 ##abs函数不支持l ...

  3. UOJ 241. 【UR #16】破坏发射台 [矩阵乘法]

    UOJ 241. [UR #16]破坏发射台 题意:长度为 n 的环,每个点染色,有 m 种颜色,要求相邻相对不能同色,求方案数.(定义两个点相对为去掉这两个点后环能被分成相同大小的两段) 只想到一个 ...

  4. bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]

    4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...

  5. POJ 3581 Sequence [后缀数组]

    Sequence Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6911   Accepted: 1543 Case Tim ...

  6. Windows下为Lua脚本进行加密处理

    缘由 想对Lua脚本进行安全性处理,可惜一直没有想到很好的解决方案,考虑过用原生Lua将脚本编译成二进制代码,也考虑过用zlib将文件进行加密压缩处理,但是感觉都不是最佳方案,今天忽然想到有个东西叫L ...

  7. [Python Study Notes]WdSaveFormat 枚举

    WdSaveFormat 枚举 指定要在保存文档时使用的格式. 版本信息 已添加版本: 名称 值 说明 wdFormatDocument 0 Microsoft Word 格式. wdFormatDO ...

  8. 在阿里云上搭建 Spark 实验平台

    在阿里云上搭建 Spark 实验平台 Hadoop2.7.3+Spark2.1.0 完全分布式环境 搭建全过程 [传统文化热爱者] 阿里云服务器搭建spark特别坑的地方 阿里云实现Hadoop+Sp ...

  9. Nginx:413 Request Entity Too Large解决

    最近在做给博客添加上传PDF的功能,但是在测试上传文件的过程中遇到了413 Request Entity Too Large错误.不过这个无错误是很好解决的,这个错误的出现是因为上传的文件大小超过了N ...

  10. Android App 压力测试方法(Monkey)

    一.为什么要开展压力测试 a.提高产品的稳定性:b.提高产品的留存率 二.什么时候开展压力测试 a.首轮功能测试通过后:b.下班后的夜间进行 三.7个基础知识(理论部分) 3.1 手动测试场景与自动测 ...