DMA 传输形式内核到用户 space

DMA transfer form kernel to user space

我正在尝试使用 DMA 引擎在 Xilinx 中实现 DMA。 FPGA 人员给了我一个支持 DMA 的 AXI DMA IP-Core,所以我需要编写一个驱动程序,它将数据从内核传输到用户 space 缓冲区。 Here 您可以找到驱动程序和应用程序的示例,其工作方式如下:

1) process opens /dev/device_file that represents the driver
2) it maps kernel coherent memory, allocated via dma_alloc_coherent
3) fills buffer with some data
4) calls ioctl() to start dma transfer

它工作正常,但我有这样的问题 - 我可以将用户 space 缓冲区传输到内核 space(通过从 file_operations 结构读取函数),准备它(转移PAGE_SIZE 或其他)并执行 dma 操作?我不明白如何使用户 space 内存在 DMA 操作中可用。

您可能想要实现 struct file_operationsmmap 方法。考虑:

static int
sample_drv_mem_mmap(struct file *filep, struct vm_area_struct *vma)
{
    /*
     * Set your "dev" pointer here (the one you used
     * for dma_alloc_coherent() invocation)
     */
    struct device   *dev;

    /*
     * Set DMA address here (the one you obtained with
     * dma_alloc_coherent() via its third argument)
     */
    dma_addr_t  dma_addr;

    /* Set your DMA buffer size here */
    size_t      dma_size;

    /* Physical page frame number to be derived from "dma_addr" */
    unsigned long   pfn;

    /* Check the buffer size requested by the user */
    if (vma->vm_end - vma->vm_start > dma_size)
        return -EINVAL;

    /*
     * For the sake of simplicity, do not let the user specify an offset;
     * you may want to take care of that in later versions of your code
     */
    if (vma->vm_pgoff != 0)
        return -EINVAL;

    pfn = PHYS_PFN(dma_to_phys(dev, dma_addr));

    return remap_pfn_range(vma, vma->vm_start, pfn,
                   vma->vm_end - vma->vm_start,
                   vma->vm_page_prot);
}

/* ... */

static const struct file_operations sample_drv_fops = {
    /* ... */

    .mmap =     sample_drv_mem_mmap,

    /* ... */
};

长话短说,我们的想法是将您拥有的 DMA(总线)地址转换为内核物理地址,然后使用 remap_pfn_range() 进行内核和用户空间之间的实际映射。

在用户应用程序中,应该调用 mmap() 来请求映射( 而不是 read / write 方法)有关更多信息,请请参考您系统上的 man 2 mmap