目前正致力于PCI设备驱动程序。设备编程如下:
当DMA传输完成时,设备向MSI数据“001”二进制发送MSI中断。
现在我正在为这个pci设备编写驱动程序,对于MSI部分,我有一些问题。
在维基百科中,它说:
MSI允许器件将少量描述中断的数据写入特殊的存储器映射I / O地址,然后芯片组将相应的中断传送给处理器。
Q1:所以在我的情况下,small amount of interrupt-describing data
是从pci设备发送到PC的"001"
?
在我的驱动程序代码中,MSI irq的注册方式如下:
err = pci_enable_msi(my_pci_dev);
err = request_irq(my_pci_dev->irq, irq_handler, 0, "PCI_FPGA_CARD", NULL);
并且irq_handler
的定义如下:
static irqreturn_t irq_handler(int irq, void *dev_id)
{
printk(KERN_INFO "(irq_handler): Called\n");
return IRQ_HANDLED;
}
Q2:使用上面的3个核心函数,我们如何获得消息"001"
?
问题3:PCI设备最多支持8个MSI向量,因此要使用所有这8个向量,我应该在下面使用哪些代码,或者两者都不正确:
err = pci_enable_msi_block(my_pci_dev,8);
err = request_irq(my_pci_dev->irq, irq_handler, 0, "PCI_FPGA_CARD", NULL);
或
err = pci_enable_msi(my_pci_dev);
err = request_irq(my_pci_dev->irq, irq_handler_0, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_1, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_2, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_3, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_4, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_5, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_6, 0, "PCI_FPGA_CARD", NULL);
err = request_irq(my_pci_dev->irq, irq_handler_7, 0, "PCI_FPGA_CARD", NULL);
3个问题~~ thx求助。
答案 0 :(得分:0)
最新答案。希望它仍然有帮助。
A1:是。 MSI是从设备到CPU的已发布内存写入。 TLP以CPU分配的MSI地址为目标,有效负载为MSI DATA,在这种情况下为“ 001”。地址和数据(偏移量)的组合定义了唯一的中断向量。因此,使用不同的“数据”,您可以有多个中断和处理程序。
A2:通常不需要它。来自维基百科。
MSI的一个常见误解是它允许设备发送 数据作为中断的一部分发送给处理器。发送为的数据 内存写入事务的一部分由芯片组用于 确定在哪个处理器上触发哪个中断;那个数据是 设备无法与之通信其他信息 中断处理程序。
如果您仍然感到好奇,请检查MSI功能的MSI DATA寄存器。它可能包含“ 001”,但我尚未验证。无论如何,“ 001”应该与ISR无关。
A3:您应该注册多个处理程序。使用MSI,您有一个连续的向量,MSI-X给出了每个中断向量的地址和数据表。
对于MSI:
request_irq(my_pci_dev->irq, irq_handler_0, ...);
request_irq(my_pci_dev->irq + 1, irq_handler_1, ...);
request_irq(my_pci_dev->irq + 2, irq_handler_2, ...);
对于MSI-X:
request_irq(my_pci_dev->pMsixEntries[0].vector, irq_handler_0, ...);
request_irq(my_pci_dev->pMsixEntries[1].vector, irq_handler_1, ...);
request_irq(my_pci_dev->pMsixEntries[2].vector, irq_handler_2, ...);