你可以写一个简单的字符设备驱动程序来做到这一点。
内部驱动器(伪码):
static ssize_t device_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
{
struct page *page;
dma_addr_t DmaBusAddress;
copy_from_user(addrstr, buf, sizeof(addrstr));
uaddr = simple_strtoul(addrstr, NULL, 0);
/* Get page structure which describes your user space
memory area
*/
res = get_user_pages(...,uaddr,...&page);
/* (optional)Get the kernel virtual address for your user space page
*/
kernel_virtual_address = kmap(page);
DmaBusAddress = dma_map_page(...,page)
/*
or the function below if you use address instead of page
DmaBusAddress = dma_map_single(...kernel_virtual_address,count...);
*/
dev->dma_dir = DMA_TO_DEVICE;/* Write operation */
dev->dma_size = count;
dev->dma_addr = DmaBusAddress;
/* Assume you have already memory map your DMA controller's I/O space
with remap_pfn_range() */
writeRegister(DMA_ADDRESS,dev->dma_addr);
........................
writeRegister(START_DMA_TRANSFER,1); /* enable DMA controller */
}
上面的代码示出了如何使用通用的DMA层。从LDD3
报价“的IOMMU可以安排任何物理存储由装置访问的 地址范围内出现,它可能会导致物理 散射缓冲器看邻接装置。制作使用 IOMMU的需要使用通用DMA层; virt_to_bus达不到 任务”
和
“通用的DMA层尽最大努力确保所有架构上的东西 都能正常工作,但正如我们将看到的,正确的 行为需要遵守一小部分规则。”
“内存映射和DMA”一章可能会回答你所有的问题。
这是链接: http://free-electrons.com/doc/books/ldd3.pdf
谢谢你的详细解答。这实际上并不适合我们,因为我们希望严格保持应用程序的用户空间而不依赖于新的内核模块。 –