Hi,
yuq wrote:I'm writing a PCI card driver on x86 and Linux. I find the command "lspci -x" print the PCI configuration space of the card indicate the interrupt line is 10, pin is 1. But the "lspci -v" says the IRQ is 16. So it seems the interrupt line field of the PCI don't equal IRQ. According to some reference the interrupt line field is set by BIOS when BIOS POST. What Linux do to change the BIOS IRQ map?
There's 2 different "interrupt controllers". The first (oldest) is the PIC chips that date back to the original IBM XT computers. They're a bit slow, they don't support multi-CPU at all and they're limited to 15 IRQ lines. Then there's the newer IO APICs which solve all these problems. Devices are connected to both interrupt controllers, and masked in one and unmasked in the other. However, they may be connected to different IRQ lines on the different controllers, because that's the only way to get past the "15 IRQs" limit. For a simple example, a PCI ethernet controller might be connected to the PIC chip's IRQ 9 and the IO APIC's IRQ 22.
The "interrupt line" field in PCI configuration space can only hold one value. For backward compatibility reasons, it tells you which PIC chip IRQ line the device is connected to. If they can, modern OSs don't use the old PIC chips and use the newer/better IO APIC instead, so the "interrupt line" field in PCI configuration space is virtually useless. To determine which IO APIC IRQ line a device is connected to an OS has to use ACPI tables and/or Multiprocessor Specification Tables.
I don't know anything about device drivers in Linux, but (as lots of drivers would need to know which IRQ line their device is connected to) I'd expect that there's some sort of function in the kernel that device drivers use to either find out which IRQ line a device uses (e.g. "
IRQline = getPCIIRQ(bus, device, function);") or to setup an interrupt handler without needing to care which IRQ line (e.g. "
install_PCI_IRQ_handler(&myIRQhandler, bus, device, function);"). Alternatively, maybe the kernel tells the driver during startup (e.g. puts the device's details, including which PIC bus/device/function and which IRQ line into some sort of structure and calls the driver's "init" function with a pointer to the structure that contains those details).
You'd have to find and read the documentation for the Linux kernel's internals and/or the source code to figure out what you should be doing; or write your own kernel so you can decide how it should be done yourself..
Cheers,
Brendan