1、访问PCI配置空间,PCI基本配置空间的读写使用下列函数: 原型定义在<linux/pci.h>
int pci_read_config_byte(struct pci_dev *pdev, int where, u8 *val);
int pci_read_config_word(struct pci_dev *pdev, int where, u8 *val);
int pci_read_config_dword(struct pci_dev *pdev, int where, u8 *val); 通过8位、16位或32位的数据传输访问配置空间。 从由pdev标识的设备空间读入一个、两个或四个字节的数据。 参数where是从配置空间起始位置计算的字节偏移量。 从配置空间获得的值通过指针val返回。 函数本身的返回值是错误代码。
int pci_write_config_byte(struct pci_dev *pdev, int where, u8 *val); int pci_write_config_word(struct pci_dev *pdev, int where, u8 *val); int pci_write_config_dword(struct pci_dev *pdev, int where, u8 *val); 向由pdev标识的设备配置空间写入一个、两个或四个字节。 where是偏移量 指针val是要写入的值
2、访问PCI设备的IO或内存空间。
一个PCI设备可实现多达6个IO基地址寄存器,每个寄存器可以是内存地址也可以是IO地址。
PCI配置空间中的6个基地址寄存器,每个都为32位,它们代表PCI的6个IO区域。在linux内核中,PCI设备的IO区域已被集成到通用资源管理,所以要想获得PCI设备的基地址在存储器域的物理地址,要通过下面的函数:
unsigned long pci_resource_start(struct pci_dev *pdev, int bar); 该函数返回6个PCI IO区域中的第bar个的基地址值(存储器域的物理地址)。bar代表基地址寄存器(base address register),取值为0到5. unsigned long pci_resource_start(struct pci_dev *pdev, int bar); 该函数返回6个PCI IO区域中的第bar个的尾地址值(存储器域的物理地址)。bar代表基地址寄存器(base address register),取值为0到5.
// 将存储器域的物理地址映射为虚拟地址; // mem = ioremap(phymem, pci_resource_len(pdev, 0)); void *ioremap(unsigned long phys_addr, unsigned long size)
这样就可以完成配置空间的访问,而且通过PCI配置空间中的6个基地址寄存器,我们可以在CPU侧通过MEM读写访问PCIE设备。