繁体   English   中英

Linux下的DMA和I/O内存区域

[英]DMA and I/O memory region under Linux

我写这篇文章是因为我对 DMA 的行为有些怀疑。 我正在阅读有关 PCI 布局以及设备驱动程序如何与卡交互的信息,我阅读了有关 DMA 的信息。 据我了解,PCI 卡没有 DMA 控制器,而不是它们请求成为总线的主控,然后它们能够获取 DMA 地址并在内存和设备之间进行传输(通过总线)。

这个 DMA 地址是 RAM 的一部分,实际上它是一个物理地址,在执行任何操作之前,您需要将其转换为驱动程序可以使用的内容,例如内核虚拟内存。 我已经用这个代码检查过:

    /* Virtual kernel address */
    kernel_buff = pci_alloc_consistent(dev, PAGE_SIZE, &dma_addr);

    pr_info("Kernel buffer - %12p , Dma_addr - %12p\n", kernel_buff, (void *)dma_addr );
    pr_info( "Kernelbuffer - dma_addr - %12p\n", kernel_buff - dma_addr);

    strcpy(kernel_buff, "Test dma\n");

    /* Test memory */

    ptest = (void *)dma_addr;
    ptest = phys_to_virt((unsigned long)ptest);

    pr_info("Ptest virtual memory(%p) containts - %s\n", ptest, (char *)ptest);

输出是:

[425971.835669] Kernel buffer - ffff8800ca70a000 , Dma_addr -     ca70a000
[425971.835671] Kernelbuffer - dma_addr - ffff880000000000
[425971.835673] Ptest virtual memory(ffff8800ca70a000) containts - Test dma

这就是我理解 DMA 是 RAM 的一部分的方式。

我的疑问是这种转移是如何进行的。 我的意思是,每次我在这个缓冲区中写入时,缓冲区包含的数据都会传输到设备? 或者只有内存位置的地址,然后设备会从这个位置读取?

这是关于DMA。

关于 I/O 内存映射:

当我们请求设备的 I/O 内存区域时,例如:

pci_resource_start

我们正在请求设备寄存器所在的内存区域? 那么通过这种方式我们可以将这个内存位置放入 RAM 中吗? 我们将写入/读取作为正常的内存位置。

最后一点是,我们使用 DMA 是因为 I/O 内存映射每个周期只允许几个字节,因为这个过程涉及 CPU,对吗? 因此,我们可以在没有 CPU 的情况下在内存位置(RAM 和设备总线)之间传输大量数据。

将数据传输到设备所涉及的步骤可总结如下:

  1. 假设您在缓冲区中有数据。
  2. 驱动程序为此缓冲区创建 DMA 映射(例如使用pci_alloc_consistent()或较新的dma_alloc_coherent() ),并返回相应的 DMA 总线地址。
  3. 该 DMA 总线地址将通知设备。 这是通过通过writel()写入设备的正确 DMA 寄存器来完成的(假设设备寄存器是内存映射的)。
  4. 设备还需要被告知正在传输的数据量等(通过使用writel()写入设备的适当寄存器)
  5. 现在向设备发出命令以通过写入其控制寄存器之一(再次可能使用writel() )来启动 DMA 事务。
  6. 数据事务完成后,设备发出中断。
  7. 在中断处理程序中,驱动程序可能会取消分配用于事务的缓冲区,也可能执行 DMA 取消映射。

你有它......数据被传输到设备!

现在来到关于 IO 内存映射的问题:

首先,当我们调用pci_resource_start() ,我们不会“请求”IO 端口。 这就是我们收集信息的方式。 关于端口。 请求是使用pci_request_regions() 具体到您的问题:

我们正在请求设备寄存器所在的内存区域?

使用它,我们请求内核访问设备寄存器所在的这个内存区域(内存映射端口)。

那么通过这种方式我们可以将这个内存位置放入 RAM 中吗?

不,我们在 RAM 中没有这个内存位置,它只是内存映射,这意味着设备与 RAM 共享相同的地址、数据和控制线,因此,用于访问 RAM 的相同指令也可以用于访问设备寄存器。

你自己已经回答了你的最后一个问题。 DMA 提供了大量有效传输的数据。 但是,在某些情况下,您需要使用内存映射来传输数据。 最好的例子已经在DMA交易过程的解释中说明了,你需要将地址和控制信息传输到设备。 这只能通过内存映射 IO 来完成。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM