[TED] linux下的PCI备忘

来源:互联网 发布:淘宝服务中心在哪 编辑:程序博客网 时间:2024/06/05 10:13


网上关于PCI驱动的文章很多,这里做个备忘加深印象。

主机启动过程中会检测所有PCI设备并且收集信息,通常就是PCI设备的访问空间信息也就是地址空间。之后Linux Kernel就可以通过访问BIOS的保留空间直接取得指定的PCI设备的基地址以及其他寄存器。这个工作一般都是由BIOS完成,当然如果主机不支持BIOS,Linux就会自己去扫描所有总线获取PCI信息。

下图就是PCI设备的地址空间:

PCI 设备的配置空间起始段


如果我们知道设备的供应商编号和型号我们可以通过linux下的API取得这个结构

struct pci_dev *pdev;

pdev = pci_get_device(Vendor, id, NULL);

其中Vendor是厂商的编号 比如Intel通用编号:

#define PCI_VENDOR_ID_INTEL        0x8086
id是设备的型号, 比如:

#define PCI_DEVICE_ID_INTEL_ICH10_2    0x3a18


在使用前需要先激活设备:

pci_enable_device(struct pci_dev);


在这段地址空间中,我们主要关注BAR(Base address Register),也就是基地址空间。

我们先来看看它的结构




其中:

bit 0: 0 表示地址空间被映射在内存空间中

             1 表示地址空间被映射在IO空间中,需要通过ioremap将物理地址转换成虚拟地址 或者 通过in(reg),out(val,reg) 直接读写IO

bit 1:  保留位0

以下仅对内存空间类型有效

bit 2:  0 32位地址 1 64位地址

bit 3:  0  不可预取 1 可以预取

基于上面的方法我们可以通过linux的API访问地址空间以取得基地址

pci_read_config_dword(pdev,  PCI_BASE_1ST, &base);
根据映射类型选择IO
base &= PCI_BASE_ADDRESS_IO_MASK;

或者MEM

base &= PCI_BASE_ADDRESS_MEM_MASK;

基地址寄存器除了保存基地址和类型以外还标识出地址空间的大小

可以通过下么的方法读出:

1) 往寄存器里写 0xFFFFFFFF

2) 读出寄存器的值,并取反

3) 上一步结果加1












0 0