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

时间:2014-08-06 13:20:57

标签: linux memory kernel dma pci

我写这篇文章是因为我对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 个答案:

答案 0 :(得分:7)

将数据传输到设备所涉及的步骤可归纳如下: 1. Assume that you have the data in a buffer. 2. The driver creates a DMA mapping for this buffer(say using pci_alloc_coherent()), and returns the corresponding DMA bus address. 3. This DMA bus address is to be informed to the device. This is done by writing into the correct DMA registers of the device through writel()(Assuming that the device registers are memory mapped). 4. The device also needs to be informed about the amount of data that is being transferred and such (by writing to the appropriate registers of the device using writel()) 4. Now issue the command to the device to start the DMA transactions by writing to one of its control registers(again possibly using writel()). 5. Once the data transaction is completed, the device issues an interrupt. 6. In the interrupt handler, the driver may unallocate the buffer which was used for transaction and might as well perform DMA unmapping.

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

现在讨论有关IO内存映射的问题:

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

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

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

所以这样我们将这个内存位置放入RAM?

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

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

希望这有帮助。