Linux + MSI

Started working with my device driver + PCIe interface task again, and yesterday I wrote my ioctl() handler. It was an easy task, and now I’m trying on interrupt handling.

MSI (Message Signaled Interrupt) is a new way of PCI interruption, that issues an interrupt by a write request to a device specific address in memory address space, instead to assert INTA#.

There’s “MSI capability register” in the PCI configuration space, beginning at 0x48 in my case. To find the register, (i) check the pointer at 0x34. (ii) 0x34 has a pointer (0x40) to next register. (iii) 0x40 has a capability ID(01), but this isn’t for MSI. 0x41 has a pointer to next, 0x48. (iii) 0x48 is the capability ID for MSI (0x05), but 0x4a and 0x4b must be “0x81 0x01” if MSI is enabled…

02:00.0 RAM memory: Xilinx Corporation Device 0007
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: ee 10 07 00 07 00 10 00 00 00 00 05 10 00 00 00
10: 04 00 20 e3 00 00 00 00 04 10 20 e3 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 ee 10 07 00
30: 00 00 f0 ff 40 00 00 00 00 00 00 00 0b 01 00 00
40: 01 48 03 08 00 00 00 00 05 60 80 01 00 00 00 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: 10 00 01 00 ea 8f 2c 01 10 29 00 00 41 f4 03 00
70: 40 00 41 10 00 00 00 00 00 00 00 00 00 00 00 00

So I added a pci_enable_msi() call in my driver initialization routine, and I’ve got it! The address and message to fire an interrupt are 0x00000000fee0f00c (at 0x4c-0x53) and 0x41b1 (at 0x54).

02:00.0 RAM memory: Xilinx Corporation Device 0007
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: ee 10 07 00 07 04 10 00 00 00 00 05 10 00 00 00
10: 04 00 20 e3 00 00 00 00 04 10 20 e3 00 00 00 00
20: 00 00 00 00 00 00 00 00 00 00 00 00 ee 10 07 00
30: 00 00 f0 ff 40 00 00 00 00 00 00 00 0b 01 00 00
40: 01 48 03 08 00 00 00 00 05 60 81 01 0c f0 e0 fe
50: 00 00 00 00 b1 41 00 00 01 00 00 00 00 00 00 00
60: 10 00 01 00 ea 8f 2c 01 10 29 00 00 41 f4 03 00
70: 40 00 41 10 00 00 00 00 00 00 00 00 00 00 00 00

Additionally, the link status register is located at 0x70 (in the PCIe function block: cap ID 0x10 at 0x60), and “0x0040” means that the PCIe interface is operating at x4 mode (0x**1* for x1, 0x**8* for x8).

FYI: The Virtex-5 PCIe configuration space map is available in Xilinx UG341.

コメントを残す