简体   繁体   English

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

[英]Implementing PCIe Linux device driver (want to access my card registers from kernel driver)

I'm writing a device driver to access the memory in a FPGA on a PCIe card. 我正在编写一个设备驱动程序来访问PCIe卡上FPGA中的内存。
The card boots and is probed/found :- 卡片启动并被探测/发现: -

/proc/iomem 的/ proc / IOMEM

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

So reading ldd/etc I coded up a call to request_mem_region at the 80000000 , and requested a pointer to it via ioremap_nocache 所以读取ldd / etc我在80000000编写了对request_mem_region的调用,并通过ioremap_nocache请求指向它的指针

1) Do I need to request_mem_region as well as a ioremap_nocache , cant I use just the latter? 1)我是否需要request_mem_region以及ioremap_nocache ,我不能只使用后者?

/proc/iomem After insmod my device driver :- / proc / iomem insmod我的设备驱动程序后: -

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

2) Doesnt look quite right to me...? 2)对我来说看起来不太合适......?

Anyway, reads don't work (its not coded like below, it has checks etc) :- 无论如何,读取不起作用(它没有编码如下,它有检查等) : -

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

Outputs :- 产出: -

address:0xfd500000, data:0xffffffff

I can read the x80000000+KNOWN_REG_LOCATION from mmap userspace. 我可以从mmap用户空间读取x80000000+KNOWN_REG_LOCATION

3) I've tried __raw_readl / readl with no luck as well. 3)我已经尝试了__raw_readl / readl没有运气。

4) Can I just read at the currently mapped address x80000000 ? 4)我可以只读取当前映射的地址x80000000吗?

Ian, 伊恩

I wrote a PCI driver for a device ( full source ). 我为设备编写了一个PCI驱动程序( 完整源代码 )。 The mapping of the register space should be the same though. 寄存器空间的映射应该是相同的。 Here is how I do it. 我就是这样做的。

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

The address and length values are returned from pci_resource_start() and pci_resource_length() calls. 地址和长度值从pci_resource_start()pci_resource_length()调用返回。

Then you can access it using ioread32() using dm7820_device->pci[region].virt_addr + <register offset> 然后你可以使用ioread32()使用dm7820_device->pci[region].virt_addr + <register offset>来访问它。

Let me know if you have any questions. 如果您有任何疑问,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM