实施PCIe Linux设备驱动程序(想从内核驱动程序访问我的卡寄存器) [英] Implementing PCIe Linux device driver (want to access my card registers from kernel driver)

查看:958
本文介绍了实施PCIe Linux设备驱动程序(想从内核驱动程序访问我的卡寄存器)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写设备驱动程序以访问PCIe卡上FPGA中的内存.
卡启动并被探测/发现:-

I'm writing a device driver to access the memory in a FPGA on a PCIe card.
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

因此,读取ldd/etc时,我在80000000处编写了对request_mem_region的调用,并通过ioremap_nocache

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

1)我是否需要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?

/proc/iomem在insmod我的设备驱动程序之后:-

/proc/iomem After insmod my device driver :-

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

2)我看起来不太正确吗??

2) Doesnt look quite right to me...?

无论如何,读取不起作用(它的编码不像下面那样,它具有校验等):-

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

输出:-

address:0xfd500000, data:0xffffffff

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

I can read the x80000000+KNOWN_REG_LOCATION from mmap userspace.

3)我也尝试过__raw_readl/readl,但也没有运气.

3) I've tried __raw_readl/readl with no luck as well.

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

4) Can I just read at the currently mapped address x80000000?

推荐答案

Ian,

我为设备编写了PCI驱动程序(完整来源).寄存器空间的映射应该相同.这是我的方法.

I wrote a PCI driver for a device (full source). 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;
}

地址和长度值是从pci_resource_start()pci_resource_length()调用返回的.

The address and length values are returned from pci_resource_start() and pci_resource_length() calls.

然后您可以使用dm7820_device->pci[region].virt_addr + <register offset>

如果您有任何疑问,请告诉我.

Let me know if you have any questions.

这篇关于实施PCIe Linux设备驱动程序(想从内核驱动程序访问我的卡寄存器)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆