-
#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
-->
-
static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
-
size_t size,
-
enum dma_data_direction dir,
-
struct dma_attrs *attrs)
-
{
-
struct dma_map_ops *ops = get_dma_ops(dev); //获取dma_ops
-
dma_addr_t addr;
-
-
kmemcheck_mark_initialized(ptr, size);
-
BUG_ON(!valid_dma_direction(dir));
-
addr = ops->map_page(dev, virt_to_page(ptr), //调用dma_ops的map_page接口
-
(unsigned long)ptr & ~PAGE_MASK, size,
-
dir, attrs);
-
debug_dma_map_page(dev, virt_to_page(ptr),
-
(unsigned long)ptr & ~PAGE_MASK, size,
-
dir, addr, true);
-
return addr;
-
}
dma_ops的初始化
fs_initcall(pci_iommu_init); -->
-
pci_iommu_init(){
-
...
-
intel_iommu_init();//设置intel的iommu,如果存在硬件设备的话,设置dma_ops=intel_dma_ops
-
amd_iommu_init();//设置amd的iommu,如果存在硬件设备的话,设置dma_ops=amd_dma_ops
-
no_iommu_init();//当不存在iommu设备时,设置dma_ops=nommu_dma_ops
-
...
-
}
nommu_map_page最后将地址转换为总线地址,此时的总线地址==CPU域物理地址
-
static dma_addr_t nommu_map_page(struct device *dev, struct page *page,
-
unsigned long offset, size_t size,
-
enum dma_data_direction dir,
-
struct dma_attrs *attrs)
-
{
-
dma_addr_t bus = page_to_phys(page) + offset; //总线地址就等于物理地址。
-
WARN_ON(size == 0);
-
if (!check_addr("map_single", dev, bus, size))
-
return bad_dma_address;
-
flush_write_buffers();
-
return bus;
-
}
阅读(11166) | 评论(0) | 转发(0) |