我正在尝试从可加载的内核模块读取和写入 PCI 设备。
因此我关注了这篇文章:
pci_enable_device(dev);
pci_request_regions(dev, "expdev");
bar1 = pci_iomap(dev, 1, 0);
// void iowrite32(u32 val, void __iomem *addr)
iowrite32( 0xaaaaaaaa, bar1 + 0x060000); /* offset from device spec */
Run Code Online (Sandbox Code Playgroud)
但最终设备并没有按预期完成他的工作。然后我查看了后面的地址bar1,发现了一个非常大的值ffffbaaaaa004500。
在这一点上,我真的不明白那里发生了什么,什么是对的。我可以解释bar1为内核地址空间内的地址,该地址直接0x60000指向与 PCI 芯片选择地址偏移的基地址吗?
我写的值怎么会bar1 + offset复制到设备上?iowrite32和后面的机制是如何工作的pci_iomap?
感谢致敬
亚历克斯
PS:我成功测试了从同一地址的回读。
PCI设备的寄存器描述:
PCIBAR0PCI 基地址 0;用于内存映射配置寄存器PCIBAR1PCI 基地址 1;用于 I/O 映射的配置寄存器PCIBAR2PCI 基地址 2;用于本地地址空间 0PCIBAR3PCI 基地址 3;用于本地地址空间 1PCIBAR4 未使用的基地址PCIBAR5 …我正在编写一个设备驱动程序来访问PCIe卡上FPGA中的内存.
卡片启动并被探测/发现: -
的/ proc/IOMEM
80000000-840fffff : PCI Bus #03
80000000-83ffffff : 0000:03:00.0
84000000-840fffff : 0000:03:00.0
Run Code Online (Sandbox Code Playgroud)
所以,读LDD /等我编写了一个调用request_mem_region的80000000,并通过请求指向它的指针ioremap_nocache
1)我是否需要request_mem_region和a一样ioremap_nocache,我不能只使用后者?
/ proc/iomem insmod我的设备驱动程序后: -
80000000-840fffff : PCI Bus #03
80000000-83ffffff : 0000:03:00.0
80000000-8003ffff : fp2
84000000-840fffff : 0000:03:00.0
Run Code Online (Sandbox Code Playgroud)
2)对我来说看起来不太合适......?
无论如何,读取不起作用(它没有编码如下,它有检查等): -
#define BAR_ADDR 0x80000000
void *base = ioremap_nocache(BAR_ADDR, 0x40000);
void *address = base + KNOWN_REG_LOCATION;
int data = ioread32(address);
printk("fp2: address:0x%08x, data:0x%08x\n", address, data);
Run Code Online (Sandbox Code Playgroud)
产出: -
address:0xfd500000, data:0xffffffff
Run Code Online (Sandbox Code Playgroud)
我可以 …