应用程序中pci配置空间读写
~~~~~~~~~~~~~~~~~~~~~~~
1. 概述
主要讲述在linux操作系统中应用程序如何读写pci配置空间。
2. 基本原理
对于pci设备,由cpu通过一个统一的入口地址向pci总桥发出命令,再由相应的pci桥间接地完成具体的读写操作。对于X86结构,pci总线的设计者在I/O地址空间保留了8个字节用于这个操作:0xcf8
-
0xcff。这8个字节分成两个32位的寄存器,0xcf8是地址寄存器,0xcfc是数据寄存器。cpu先往地址寄存器中写入目标地址,然后通过数据寄存器读写数据,写入地址寄存器中的目标地址是一种包括总线号、设备号、功能号以及配置寄存器地址的综合地址。具体如下:
bit31 1
bit30-bit24 保留
bit23-bit16 总线号
bit15-bit11 设备号
bit10-bit8 功能号
bit7-bit0 寄存器地址,最低两位为0
设备的这些信息都可以通过lspci命令获取。
3. ioport读写权限
由于要通过操作ioport,所以先要获取ioport的读写权限。
能获取读写权限的函数有两个ioperm()和iopl()。
由于pci的口地址比较高,要用iopl(3)获取权限。
4. 读程序
#define
PCI_CFG_DATA 0xcfc
#define
PCI_CFG_CTRL 0xcf8
void pci_read_config_byte(unsigned char bus,
unsigned char dev, unsigned char offset, unsigned char *val)
{
unsigned
char fun = 0;
outl((0x80000000 | ((bus)<<16)
|((dev)<<11) |
((fun)<<8) | (offset
& ~0x3)), PCI_CFG_CTRL);
*val =
inl(PCI_CFG_DATA) >> ((offset
& 3) * 8);
}
void pci_read_config_word(unsigned char bus,
unsigned char dev, unsigned char offset, unsig