linux pcie设备驱动,linux-kernel – 实现PCIe Linux设备驱动程序(想从内核驱动程序访问我的卡寄存器)...

我正在编写一个设备驱动程序来访问PCIe卡上FPGA中的内存.

卡片启动并被探测/发现: –

的/ 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请求指向它的指针

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吗?

伊恩

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

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()调用返回.

然后你可以使用imad32()使用dm7820_device-> pci [region] .virt_addr< register offset>来访问它.

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里提供一个简单的 PCIe 设备驱动示例程序,包括一些基本操作和 DMA 驱动代码。这个示例程序可以作为学习 PCIe 设备驱动和 DMA 驱动的参考,但是需要根据具体的硬件设备进行修改和适配。 示例程序代码如下: ```c #include <linux/init.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/dma-mapping.h> #define MY_VENDOR_ID 0x1234 #define MY_DEVICE_ID 0x5678 // 定义设备结构体 struct my_device { struct pci_dev *pdev; void *bar0_addr; }; // PCI 设备匹配函数 static int my_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int err = 0; struct my_device *dev = NULL; // 初始化设备结构体 dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { err = -ENOMEM; goto err_out; } dev->pdev = pdev; // 映射 BAR0 dev->bar0_addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); if (!dev->bar0_addr) { err = -ENOMEM; goto err_free_dev; } // 初始化 DMA err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (err != 0) { goto err_unmap_bar0; } err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (err != 0) { goto err_unmap_bar0; } // 完成初始化 pci_set_drvdata(pdev, dev); dev_info(&pdev->dev, "PCI device initialized\n"); return 0; err_unmap_bar0: pci_iounmap(pdev, dev->bar0_addr); err_free_dev: kfree(dev); err_out: return err; } // PCI 设备移除函数 static void my_pci_remove(struct pci_dev *pdev) { struct my_device *dev = pci_get_drvdata(pdev); // 清理 DMA pci_clear_master(pdev); pci_disable_device(pdev); // 取消映射 pci_iounmap(pdev, dev->bar0_addr); // 释放设备结构体 kfree(dev); pci_set_drvdata(pdev, NULL); dev_info(&pdev->dev, "PCI device removed\n"); } // 定义 PCI 设备 ID static const struct pci_device_id my_pci_ids[] = { { PCI_DEVICE(MY_VENDOR_ID, MY_DEVICE_ID) }, { 0, } }; MODULE_DEVICE_TABLE(pci, my_pci_ids); // 定义 PCI 驱动程序结构体 static struct pci_driver my_pci_driver = { .name = "my_pci_driver", .id_table = my_pci_ids, .probe = my_pci_probe, .remove = my_pci_remove, }; // 模块初始化函数 static int __init my_init(void) { int err = 0; // 注册 PCI 驱动程序 err = pci_register_driver(&my_pci_driver); if (err != 0) { goto err_out; } return 0; err_out: return err; } // 模块退出函数 static void __exit my_exit(void) { // 注销 PCI 驱动程序 pci_unregister_driver(&my_pci_driver); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); ``` 这个示例程序实现了一个简单的 PCIe 设备驱动,包括 PCI 设备匹配、BAR0 映射、DMA 初始化和清理等操作。同时还包括模块初始化和退出函数,以及模块许可证声明等基本内容。 需要注意的是,这个示例程序只是一个简单的演示,不能直接用于生产环境。在实际开发中,需要根据具体硬件设备的情况进行修改和适配,并添加更多的功能和错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值