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_operations
的 mmap
方法。考虑:
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
。
我正在尝试使用 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_operations
的 mmap
方法。考虑:
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
。