PCI、PCIE配置空间的访问

一. 使用PCI兼容性配置访问机制

根据协议,x86上使用了两个I/O端口寄存器(OUT 和 IN 在汇编中是端口读写操作指令。端口是主机与外设进行数据交换使用的,分为数据端口,状态端口和控制端口三种。PC机给每一个端口分配了一个地址,所有端口成线性排列,形成一个独立于内存空间的I/O地址空间,一般用十六进制表示。8086中,端口地址的范围是0000H-FFFFH。 ):CONFIG_ADDRESS(物理地址0CF8H)和CONFIG_DATA(0CFCH),来访问PCI配置空间。

其中Bit 31位是使能位,写1。

总线号0-255,系统中最多有256个总线。

设备号0-31,每个总线最多挂载32个设备。

功能号0-7,每个设备对多8个function。

寄存器号:待访问配置空间寄存器的编号。

 

例如:

下面的x86汇编代码样本将使根复合体生成一个配置读请求事务,请求读总线4、设备0、功能0的VendorID配置寄存器:

 

mov %dx,0CF8h;设置寄存器%dx为 CONFIG_ADDRESS寄存器地址。

mov %eax,80040000h;使能位=1,Bus 1,Dev 0,Func 0,Reg 0。

out %dx,%eax;将%eax中的值写入端口CONFIG_ADDRESS。

mov %dx,0CFCh;设置寄存器%dx为 CONFIG_DATA寄存器地址。

in %ax,%dx;从%dx( CONFIG_DATA)读2个字节给%ax,这就是对应的VendorID的

 

二. 使用PCI Express增强配置访问机制

使用前述 PCI兼容配置访问机制只能访问到功能的4KB配置空间中的 PCI兼容配置寄存器区(256B),PCIE增强配置访问机制可以访问到整个4KB配置空间。两者访问方法的不同之处在于处理器向 Host-PCI桥表达自己配置访问意图的方式。映射于存储器的配置空间:PCIE增强的配置访问机制在系统存储器空间里划出一片256MB区域,将总容量为256MB的全部配置寄存器一对一地映射于这片存储器空间。处理器访问256MB配置空间的地址含义:

例如:

下面的x86汇编代码样本将使根复合体生成一个配置读请求事务,请求读总线4、设备0、功能0的Vendor ID配置寄存器(offset),本例假设增强配置寄存器映射存储器区域的256MB的基地址是50000000h(MMIO Configuration Space Base Address):

 

mov %ax,(50400000h); //配置寄存器映射的存储器读,这就直接获取了VendorID的值。

参考:PCI、PCI-X和PCIExpress的原理及体系结构-马鸣锦

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WinIoCtr是一个用于Windows的驱动程序,可以访问硬件I/O端口和内存映射的I/O地址。要使用WinIoCtr访问PCIe配置空间,您需要使用PCIe设备的PCI总线编号、设备编号、功能编号和配置寄存器偏移量来构建PCIe配置空间地址。 以下是访问PCIe配置空间的示例代码: ```c #include <windows.h> #include <stdio.h> #include "WinIoCtl.h" int main() { HANDLE hDriver; DWORD dwBytesReturned; BOOL bResult; // 打开WinIo驱动程序 hDriver = CreateFile("\\\\.\\WinIo", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (!hDriver) { printf("Failed to open WinIo driver\n"); return 1; } // 构建PCIe配置空间地址 DWORD dwBusNumber = 0; // PCI总线号 DWORD dwDeviceNumber = 1; // 设备号 DWORD dwFunctionNumber = 0; // 功能号 DWORD dwRegisterOffset = 0x10; // 配置寄存器偏移量 DWORD dwConfigAddress = (dwBusNumber << 16) | (dwDeviceNumber << 11) | (dwFunctionNumber << 8) | (dwRegisterOffset & 0xFC) | ((DWORD)0x80000000); // 发送IO控制码,读取PCIe配置寄存器值 DWORD dwConfigValue; bResult = DeviceIoControl(hDriver, IOCTL_WINIO_READ_PORT_U32, &dwConfigAddress, sizeof(DWORD), &dwConfigValue, sizeof(DWORD), &dwBytesReturned, NULL); if (!bResult) { printf("Failed to read PCIe configuration register\n"); CloseHandle(hDriver); return 1; } printf("PCIe configuration register value is 0x%08X\n", dwConfigValue); // 关闭WinIo驱动程序 CloseHandle(hDriver); return 0; } ``` 在此示例中,我们使用了WinIo的IOCTL_WINIO_READ_PORT_U32控制码来读取PCIe配置寄存器的值。您可以使用IOCTL_WINIO_WRITE_PORT_U32控制码来编写PCIe配置寄存器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值