linux之dma api — 通用设备的动态dma映射,Linux动态DMA映射

  • Post author:
  • Post category:linux


1. 几种地址类型

虚拟地址

Linux内核使用的地址是虚拟地址,数据类型为void *。例如,kmalloc()和vmalloc()函数返回值就是虚拟地址。

物理地址

处理器真实地址总线上的地址,数据类型为phys_addr_t。

对I/O设备寄存器和内存统一编址的处理器,如ARM/PowerPC,参考手册一般会给出memory map,也就是各种I/O设备的寄存器在物理地址空间的分布。对I/O设备寄存器独立编址的处理器。如X86,访问I/O设备寄存器或内存时,向地址总线发送地址,并通过控制信号来实现对I/O设备寄存器和内存的不同寻址。这些I/O设备寄存器的地址可以在/proc/iomem中查看,必须使用ioremap()映射到虚拟地址空间才可以使用。

总线地址

从I/O设备的角度看,I/O设备使用的地址是总线地址。DMA使用地址也是总线地址,数据类型为dma_addr_t。对一些简单的系统,设备通过DMA可以直接访问物理地址,但大多数系统都有IOMMU将总线地址转换为物理地址。

2. DMA寻址能力

默认情况下Linux认为设备DMA可以进行32位寻址。必须对DMA mask进行设置,将设备的DMA寻址能力通知内核。

int dma_set_mask_and_coherent(struct device *dev, u64 mask)

该函数也可以分为如下两个函数,如果有需要,可以分别对流式映射设置DMA mask,对一致性分配设置DMA mask。

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

int dma_set_coherent_mask(struct dev