目前正致力于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求助。
迟到的答案。希望它仍然有帮助。
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, ...);