侧边栏壁纸
  • 累计撰写 74 篇文章
  • 累计创建 45 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Linux下不写驱动如何访问PCI/PCIe设备的内存空间

码峰
2022-08-22 / 0 评论 / 0 点赞 / 195 阅读 / 845 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-08-30,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

Linux中,有一个新的PCI/PCIe设备需要进行测试,但又不想编写Linux内核驱动程序。事实证明,Linux可以在没有驱动驱动的情况下读取和写入PCI设备的内存空间。Cheers!
Linux为PCI设备提供了一个sysfs接口。从该接口,可以对内存空间进行mmaped,然后进行读写。不需要额外编写的内核驱动参与。

示例

我们可以使用lspci命令来获取关于特定PCI设备的信息。如下:

$ vendor="10ee" # Use your device ID
$ device="7014" # Use your vendor ID
$ lspci -d $vendor:$device -nvv
04:00.0 1180: 10ee:7014
    ...
    Region 0: Memory at f7300000 (32-bit, non-prefetchable) [size=128K]

然后我们可以查看位于/sys/bus/pci/devices/下的sysfs接口,通过lspci输出中的第一位数据给出了设备在总线上的位置,我们可以在遍历sysfs接口时使用这个位置。

$ ls -alF /sys/bus/pci/devices/0000\:04\:00.0/
total 0
drwxr-xr-x 3 root root      0 Jul  1 12:42 ./
drwxr-xr-x 8 root root      0 Jul  1 12:42 ../
-rw-r--r-- 1 root root   4096 Jul  9 12:48 broken_parity_status
-r--r--r-- 1 root root   4096 Jul  1 12:42 class
-rw-r--r-- 1 root root   4096 Jul  9 12:44 config
-r--r--r-- 1 root root   4096 Jul  1 12:42 device
...
-r--r--r-- 1 root root   4096 Jul  1 12:43 resource
-rw------- 1 root root 131072 Jul  1 12:43 resource0
...
-r--r--r-- 1 root root   4096 Jul  1 12:42 vendor

这个输出结果中,有一些有用的文件,如供应商和设备,可以确认我们打开正确的设备。同时,这些文件也有助于不用lspci命令,而以编程方式查找正确的设备。

$ cat /sys/bus/pci/devices/0000\:04\:00.0/vendor
0x10ee
$ cat /sys/bus/pci/devices/0000\:04\:00.0/device
0x7014

回顾lspci命令的输出,我们还可以看到内存资源和地址。这些在sysfs接口中表示为resource0…resourceN。这就是我们用来访问PCI内存空间的方法。
打开resource0文件(根据设备的不同,可以是0以外的数字)。

int fd = open("/sys/bus/pci/devices/0000:04:00.0/resource0", O_RDWR | O_SYNC);

然后使用lspci命令输出中的内存地址和大小来映射该文件。

void* base_address = (void*)0xf7300000;
size_t size = 128 * 1024; // 128K
void* void_memory = mmap(base_address,
                         size,
                         PROT_READ | PROT_WRITE,
                         MAP_SHARED,
                         fd,
                         0);
uint16_t* memory = (uint16_t*)void_memory;

现在,内存提供了对PCI内存空间进行读写的直接访问了。像访问本地内存一样访问:

// Read the value of the first register
uint16_t first_register = memory[0];

// Write a value to the third register
memory[2] = 0x0007;

结语

以上介绍了在Linux中不用编写内核驱动就可以访问PCI设备的内存空间的方法,但这并不是一个完美的方法。首先,我们需要是root才能访问这个内存空间。其次,不能使用设备的任何中断。但对于新设备的基本操作来说,这个方法不需要开发内核模块,可以快速做一些验证,甚至如果不需要中断的情况下,这也可以是软件的一种解决方案,需要root权限的问题也是可以解决的。

0

评论区