[转载]PCI/PCIe基础——配置空间
转载地址:http://blog.csdn.net/jiangwei0512/article/details/51603525
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) << ) | (((Device) & 0x1f) << ) | (((Bus) & 0xff) << ))
其中的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:
简单介绍其中的几个寄存器的意义:
Vendor ID,Device ID:标记了一个设备的生产厂商和具体的设备,比如Intel的设备Vendor ID通常是0x8086,Device ID就需要厂家自定义了,总之能够识别到具体是哪个设备就可以了。
Status:设备状态字,具体每个BIT的意义见下图:
Command:设备状态字:
Base Address Registers:决定PCI/PCIe设备空间映射到系统空间具体位置的寄存器,映射方式有两种,分别是IO和Memory映射:
处理器系统资源分为IO资源和MMIO资源两种,因此PCI/PCIe空间地址对应也有两种。
下面是Bridge的配置空间,它的类型被称为Type 01h:
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,下图是具体的布局。
在原来的配置空间中,有一个寄存器指定了第一个Capability的位置,而第一个Capability又指定下一个Capability,构成了一串Capability。
具体的Capability表示什么,需要根据不同的设备来确定,再次不多做介绍。
其它说明
处理器系统中会为所有的PCI/PCIe设备留足足够的空间,但是几乎没有系统会满配,所以很多的配置空间实际上是空的,此时如果去访问,就会得到全FF,表示设备不存在。
下面是Linux下访问PCI/PCIe配置空间的一个例子:
注:以上是一个Intel网卡的PCI/PCIe配置空间,这是虚拟机下的结果,真实机器上可能有所不同。
[转载]PCI/PCIe基础——配置空间的更多相关文章
- 2.3 PCI桥与PCI设备的配置空间
PCI设备都有独立的配置空间,HOST主桥通过配置读写总线事务访问这段空间.PCI总线规定了三种类型的PCI配置空间,分别是PCI Agent设备使用的配置空间,PCI桥使用的配置空间和Cardbus ...
- 如何访问pcie整个4k的配置空间
目前用于访问PCIe配置空间寄存器的方法需要追溯到原始的PCI规范.为了发起PCI总线配置周期,Intel实现的PCI规范使用IO空间的CF8h和CFCh来分别作为索引和数据寄存器,这种方法可以访问所 ...
- 怎样訪问pcie整个4k的配置空间
眼下用于訪问PCIe配置空间寄存器的方法须要追溯到原始的PCI规范. 为了发起PCI总线配置周期,Intel实现的PCI规范使用IO空间的CF8h和CFCh来分别作为索引和数据寄存器,这样的方法能够訪 ...
- PCIe设备的配置空间
关于PCI设备的配置空间网上已经有很多资料了,如下图就是PCI设备必须支持的64个字节的配置空间,范围为0x00-0x3f. 很多PCI设备仅仅支持者64字节的配置空间.PCI和PCIe配置空间的区别 ...
- 【PCIE-2】---PCIE配置空间及访问方式简介
对新手来说,第一步了解PCIE的相关基本概念,第二步了解PCIE配置空间,第三步深入研究PCIE设备枚举方式.本章主要总结第二步的PCIE配置空间 按照国际惯例,先提问题: 1. 什么是PCIE的配置 ...
- 2.4 PCI总线的配置
PCI总线定义了两类配置请求,一个是Type 00h配置请求,另一个是Type 01h配置请求.PCI总线使用这些配置请求访问PCI总线树上的设备配置空间,包括PCI桥和PCI Agent设备的配置空 ...
- PCI、PCIE配置空间的訪问(MCFG,Bus,Device,Funtion)
一般来说,在x86平台上,有两大类方式能够訪问这一区间的寄存器, 1,配置机制1#或者配置机制2# 訪问时借助in/out指令.请注意,这样的方式有别于一般的in/out指令訪问PCI的IO空 ...
- Linux PCI/PCI-E设备配置空间读取与修改
Linux PCI/PCI-E设备配置空间读取与修改 1 前言 PCI和PCI Express,是计算机常使用的一种高速总线.操作系统中的PCI/PCI-E设备驱动以及操作系统内核,都需要访问PCI及 ...
- PCI配置空间简介
一.PCI配置空间简介 PCI有三个相互独立的物理地址空间:设备存储器地址空间.I/O地址空间和配置空间.配置空间是PCI所特有的一个物理空间.由于PCI支持设备即插即用,所以PCI设备不占用固定的内 ...
随机推荐
- 如何用hexo+github搭建个人博客
搭建环境 1.安装 Node.js: https://nodejs.org/en/ windows下点击链接,下载安装即可;Linux下更加简单,在终端下输入sudo apt-get install ...
- 多校hdu5726 线段树+预处理
第一问是没有修改的线段树,第二问暴力预处理,因为gcd的结果不会很多 在预处理阶段需要把每个区间的gcd相等的数量储存起来(用map容器),在一个序列例如:12467,枚举左区间L直到n此处时间为O( ...
- 解析远程域名主机的IP地址
我们知道,计算机在访问远程主机的时候,本质上是通过IP地址来进行访问的,但我们实际在使用的时候,例如我们想访问百度的主页,我们是通过在浏览器的地址栏输入百度的域名来进行访问的,因此,计算机需要将百度的 ...
- python使用笔记
修改文件模板,支持中文. File -> Settings -> Editor -> File and Code templates -> python Scropt 在里面加 ...
- 使用log4j2打印Log,log4j不能打印日志信息,log4j2不能打印日志信息,log4j和logj2,idea控制台信息乱码(文末)
说来惭愧,今天就写了个"hello world",了解了一下log4j的日志. 本来是想在控制台打印个log信息,也是遇到坎坷重重,开始也没去了解log4j就来使用,log4j配置 ...
- windows 10系统更新失败的解决办法
最近遇到一个问题,系统总是自动下载一个更新,看样子是个补丁吧,但是每次提醒重新启动以安装更新,但每次又安装失败,回退.就这样,下载,重启,安装失败,下载......一直循环,搞得都不敢关机了,因为这样 ...
- Swagger自动生成接口文档
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- Microsoft SQL Server for Linux安装和配置
虽说mssql for linux早已经出来了,但原本没有打算这么早就去尝试的,无奈之下还是得先尝试用了,这里分几篇介绍我在用mssql for linux时遇到的问题,不得不说作为先吃螃蟹的人总是要 ...
- 详解 Android 通信
详解 Android 通信 :http://www.androidchina.net/5028.html
- sql生成excel
gosp_configure 'show advanced options',1reconfiguregosp_configure 'xp_cmdshell',1reconfiguregoEXEC m ...