实现PCIe Linux设备驱动程序(想从内核驱动程序访问我的卡寄存器)

时间:2011-03-03 19:18:37

标签: linux-kernel pci

我正在编写一个设备驱动程序来访问PCIe卡上FPGA中的内存 卡片启动并被探测/找到: -

的/ proc / IOMEM

80000000-840fffff : PCI Bus #03
  80000000-83ffffff : 0000:03:00.0
  84000000-840fffff : 0000:03:00.0

所以读取ldd / etc我在request_mem_region编写了对80000000的调用,并通过ioremap_nocache

请求指向它的指针

1)我是否需要request_mem_region以及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

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);

输出: -

address:0xfd500000, data:0xffffffff

我可以从mmap用户空间阅读x80000000+KNOWN_REG_LOCATION

3)我已经尝试了__raw_readl / readl但也没有运气。

4)我可以只读取当前映射的地址x80000000吗?

1 个答案:

答案 0 :(得分:6)

伊恩,

我为设备(full source)编写了一个PCI驱动程序。寄存器空间的映射应该是相同的。我就是这样做的。

dm7820_device->pci[region].virt_addr = ioremap_nocache(address, length);
if (dm7820_device->pci[region].virt_addr == NULL) {
    printk(KERN_ERR "%s: ERROR: BAR%u remapping FAILED\n",
        &((dm7820_device->device_name)[0]), region);
    dm7820_release_resources();
    return -ENOMEM;
}

if (request_mem_region(address, length, &((dm7820_device->device_name)[0])) == NULL) {
    printk(KERN_ERR "%s: ERROR: I/O memory range %#lx-%#lx allocation FAILED\n",
        &((dm7820_device->device_name)[0]), address, (address + length - 1));
    dm7820_release_resources();
    return -EBUSY;
}

地址和长度值是从pci_resource_start()pci_resource_length()来电返回的。

然后,您可以使用ioread32()

使用dm7820_device->pci[region].virt_addr + <register offset>访问它

如果您有任何问题,请与我们联系。