gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 01:04:33 30 4
gpt4 key购买 nike

我写这篇文章是因为我对 DMA 的行为有一些疑问。我正在阅读有关 PCI 布局以及设备驱动程序如何与卡交互的信息,我还阅读了有关 DMA 的信息。据我了解,PCI 卡没有 DMA Controller ,而不是它们请求成为总线的主控,然后它们能够获取 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,对吧?所以我们可以在内存位置(RAM 和设备总线)之间传输大量数据而无需 cpu。

最佳答案

将数据传输到设备所涉及的步骤可以概括如下:

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

好了。数据已传输到设备!

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

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

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

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

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

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

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

希望这对您有所帮助。

关于linux - Linux下的DMA和I/O内存区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25161555/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com