直接内存访问笔记

来源:互联网 发布:rfcn网络 编辑:程序博客网 时间:2024/06/14 15:26

1.两种引发数据传输的方式

1.1 软件对数据的请求

当进程调用read,驱动程序函数分配一个DMA缓冲区,让硬件将数据传输到这个缓冲区中,进程处于睡眠状态;硬件将数据写入到DMA缓冲区中,当写入完毕,产生一个中断;中断处理程序获得输入的数据,应答中断,并唤醒进程,该进程现在可以读取数据。

1.2 硬件异步的将数据传输给系统

硬件产生中断,宣告新数据的到来;中断处理程序分配一个缓冲区,并且告诉硬件向哪里传输数据;外围设备将数据写入缓冲区,完成后产生另外一个中断;处理程序分发新数据,唤醒任何相关进程,然后执行清理工作。

2.分配DMA缓冲区

2.1处理复杂的硬件

如果设备不能在32位地址上执行DMA,则应该调用下面的函数:

int dma_set_mask(struct device *dev, u64 mask);

mask显示与设备寻址能力对应的位,比如设备受限于24位寻址,则mask应该是0xffffff。如果使用指定的mask时dma能够正常工作则返回非0值;如果返回0,则对该设备部能使用DMA。因此一个受限于24位DMA操作的驱动程序初始化代码有如下形式:

if (dma_set_mask(dev, 0xffffff))

card->use_dma = 1;

else {

card->use_dma = 1;

printk(KERN_WARN, "mydev:DMA not supported\n");

}

根据DMA缓冲区期望保留的时间长短,PCI代码区分两种类型的DMA映射:

一致性DMA映射

存在于驱动程序生命周期中,一致性映射的缓冲区必须可以同时被CPU和外围设备访问。

流式DMA映射

单独的操作建立流式映射。内核开发者建议尽量使用流式映射。第一个原因是在支持映射寄存器的系统中,每个DMA映射使用总线上的一个或者多个映射寄存器,一致性映射长时间占用这些寄存器。第二个原因是一些硬件中,流式映射可以被优化,但该方法对一致性映射无效。

建立一致性DMA映射:

void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);

建立流式DMA映射:

当只有一个缓冲区要被传输的时候,使用dma_map_single函数映射:

dma_addr_t dma_map_single(struct device *dev, void *buffer, size_t size, enum dma_data_direction direction);

返回总线地址,当传输完毕之后使用dma_unmap_single删除映射。




0 0
原创粉丝点击