我正在写这个,因为我对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. 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.
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来完成。
希望这可以帮助。