Xilinx XDMA驱动代码分析及用法
先简单的介绍一下,赛灵思的XDMA的驱动是用于做什么的、他的主要功能就类似与网卡pcie接口的网卡驱动、用于控制主机与fpga设备进行pcie的通讯。通讯的主要方式是设备文件的读写,这里不清楚的同学可以看一下我上一篇文章。通过控制设备文件的读写,操作驱动与fpga设备进行数据传输。
1、目录结构
zacha@Superman:~/nfs/xdma-debug/dma_ip_drivers-master/XDMA/linux-kernel$ tree -C
.
├── COPYING
├── include
│ └── libxdma_api.h
├── LICENSE
├── readme.txt
├── RELEASE
├── tests
│ ├── data
│ │ ├── datafile0_4K.bin
│ │ ├── datafile1_4K.bin
│ │ ├── datafile2_4K.bin
│ │ ├── datafile_256K.bin
│ │ ├── datafile_32M.bin
│ │ ├── datafile3_4K.bin
│ │ └── datafile_8K.bin
│ ├── dma_memory_mapped_test.sh
│ ├── dma_streaming_test.sh
│ ├── load_driver.sh
│ ├── perform_hwcount.sh
│ └── run_test.sh
├── tools
│ ├── \001
│ ├── dma_from_device.c
│ ├── dma_to_device.c
│ ├── dma_utils.c
│ ├── Makefile
│ ├── performance.c
│ ├── perform_hwcount.sh
│ └── reg_rw.c
└── xdma
├── cdev_bypass.c
├── cdev_ctrl.c
├── cdev_ctrl.h
├── cdev_events.c
├── cdev_sgdma.c
├── cdev_sgdma.h
├── cdev_xvc.c
├── cdev_xvc.h
├── libxdma.c
├── libxdma.h
├── Makefile
├── version.h
├── xdma_cdev.c
├── xdma_cdev.h
├── xdma_mod.c
├── xdma_mod.h
├── xdma_thread.c
└── xdma_thread.h
5 directories, 43 files
zacha@Superman:~/nfs/xdma-debug/dma_ip_drivers-master/XDMA/linux-kernel$
Xilinx 官方的XDMA驱动的目录结构大致如上图所示,大致就是:xdma(驱动代码)、tools(测试工具)、tests(自动化测试脚本)、include(对外头文件)。
今天重点分析驱动的代码部分,也会简单的介绍一些测试文件代码的基本用法。
1.1 tests/tools
tools中的文件就是用于测试驱动mem读写、寄存器读写、等的工具。 tests中的文件 就是自动化运行脚本,分为两种测试方法,第一种是mem mapped 方式,第二种事streamming的方式,两种模式的区别在于DMA以及FPGA的传输方式不同。
1.2 xdma
xdma就是驱动部分的代码,我们先看一下驱动安装成功后,所生成的设备文件,然后对应设备文件去看驱动代码每部分的功能和控制逻辑。
2、驱动的文件与生成的设备
2.1
我们先看xdma_mod.c
这个文件, 这个文件主要的功能,这部分代码的主要功能是驱动代码的整体控制入口,我们知道,整个驱动的通讯都是基于PCI协议进行通讯的,所有的总线协议在Linux下都是需要进行总线上设备注册的,所以这个代码主要的功能,就是进行pci总线初始化和注册、然后再 在总线上注册各个字符设备。
static struct pci_driver pci_driver = {
.name = DRV_MODULE_NAME,
.id_table = pci_ids,
.probe = probe_one, /*设备总线上的字符设备注册入口*/
.remove = remove_one,
.err_handler = &xdma_err_handler,
};
static int xdma_mod_init(void)
{
int rv;
pr_info("%s", version);
if (desc_blen_max > XDMA_DESC_BLEN_MAX)
desc_blen_max = XDMA_DESC_BLEN_MAX;
pr_info("desc_blen_max: 0x%x/%u, timeout: h2c %u c2h %u sec.\n",
desc_blen_max, desc_blen_max, h2c_timeout, c2h_timeout);
rv = xdma_cdev_init();
if (rv < 0)
return rv;
return pci_register_driver