Next Previous Contents

## 7. PCI Interrupts

Each PCI device that needs an interrupt comes with a fixed PCI interrupt that can't be changed. But this PCI interrupt can be mapped (routed or redirected) to an ISA interrupt by a chip on the motherboard. Thus when PCI card generates a PCI interrupt, it becomes an ISA interrupt, even if there is no ISA bus anymore.

There are two newer developments in PCI interrupts. They are especially important for cases of more than one CPU per computer. One is the Advanced Programmable Interrupt Controller (APIC) which can provides 24 or more interrupts. See the file "IO-APIC" in the i386 directory of the kernel documentation and the ACPI-HOWTO. Don't confuse APIC with ACPI (Advanced Configuration and Power Interface) which may be used by the kernel to configure the APIC.

Another new development is Message Signalled Interrupts (MSI) where the interrupt is just a message sent to a special address over the main computer bus (no interrupt lines needed). But the device that sends such a message must first gain control of the main bus so that it can send the interrupt message. Such a message contains more info than just "I'm sending an interrupt".

The mapping (same as routing or redirecting) of interrupts to ISA interrupts is done by either a "programmable interrupt router" or by and APIC. Both can be programmed by the BIOS or Linux.

PCI interrupts may be shared, meaning that two or more PCI devices will generate the same IRQ. If feasible, it's usually better not to share. Sharing doesn't work right for: 1. very old PCI hardware (before 1995 ??) 2. defective PCI hardware which may have a factory defect (it was made that way). For example, if a PCI device on IRQ9 falsely claims that any IRQ9 was intended for it, then other devices using IRQ9 may wind up having all IRQs they issue ignored since the bad device is falsely claiming their IRQs. With no sharing, this problem is avoided.

For an example of sharing the same IRQ between two PCI devices. see PCI interrupt sharing This sharing ability is built into the hardware and all device drivers are supposed to support it. Note that you can't share the same interrupt between the PCI and ISA bus. However, such illegal sharing will work provided only one of the two conflicting devices is in use at any given time. "In use" here means that a program has "opened" the device (and hasn't "closed" it) in its C programming code, even though such a program could be temporarily sleeping, etc.

## 7.1 PCI Interrupt Linking

Here are some of the details of the PCI interrupt system. Each PCI card (and device mounted on the motherboard) has 4 possible interrupts: INTA#, INTB#, INTC#, INTD#. From now on we will call them just A, B, C, and D. Each has its own pin on the edge connector of a PCI card. Thus for a 7-slot system (for 7 cards) there could be 7 x 4 = 28 different interrupt lines for these cards. Devices built into the motherboard also have additional interrupts. But the specs permit a fewer number of interrupt lines, so some PCI buses seem to be made with only 4 or 8 interrupt lines. This is not too restrictive since interrupts may be shared. For 4 interrupt line (wires, traces, or links) LNKA, LNKB, LNKC, LNKD there is a programmable "interrupt router" chip that routes LNKA, LNKB, LNKC, LNKD to selected IRQs. This routing can be changed by the BIOS or Linux. For example, LNKA may be routed to IRQ5. Suppose we designate the B interrupt from slot 3 as interrupt 3B. Then interrupts 3B and 2A could both be permanently connected to LNKA which is routed to IRQ5. These 2 interrupts: 3B and 2A are permanently shared by hardwiring on the motherboard.

One may type "dmesg" on the command line to see how interrupt lines like LNKA are routed (or linked) to IRQs (*5 means that it's linked to IRQ 5). Look for "PCI Interrupt Link". Note that "link" is used here with two meanings: 1. the linking (routing) of PCI interrupt lines to IRQs. 2. the label of an interrupt line such as LNKB (link B). The interrupt line labels seem to be provided by the Bios ?? and they may have many different names like: LNKC, LNK2, APCF, LUBA, LIDE, etc. Question: When a large number of interrupt lines are shown disabled, do they all physically exist on the motherboard? Or do they just exist only in the ACPI BIOS software so that the BIOS can work with motherboards which have more interrupt lines?

One simple method of connecting (hard-wiring) these lines from PCI devices (such as 3B) to the interrupts LNKA, etc. would be to connect all A interrupts (INTA#) to line LNKA, all B's to LNKB, etc. This method was once used many years ago but it is not a good solution. Here's why. If a card only needs one interrupt, it's required that it use A. If it needs two interrupts, it must use both A and B, etc. Thus INTA# is used much more often than INTD#. So one winds up with an excessive number of interrupts sharing the first line (LNKA connected to all the INTA#). To overcome this problem one may connect them in a more random way so that each of the 4 interrupt lines (LNKA, LNKB, LNKC, LNKD) will share about the same number of actual PCI interrupts.

One method of doing this would be to have wire LNKA share interrupts 1A, 2B, 3C, 4D, 5A, 6B, 7C. This is done by physically connecting wire W to wires 1A, 2B, etc. Likewise wire LNKB could be connected to wires 1B, 2C, 3D, 4A, 5B, 6C, 7D, etc. Then on startup, the BIOS maps the LNKB, LNKA, LNKC, LNKD to IRQs. After that, it writes the IRQ that each device uses into a hardware configuration register in each device. From then on, any program interrogating this register can find out what IRQ the device uses. Note that just writing the IRQ in a register on a PCI card doesn't in any way set the IRQ for that device.

A practical use for this info is that, as a last resort, one may change the IRQs of a PCI card by inserting it in a different slot. In the above example, INTA# of a PCI card will be connected to wire LNKA the card is inserted into slot 1 (1A maps to LNKA but INTA# will be connected to wire LNKB it's inserted into slot 4 (4A maps to LNKB).

A card in a slot may have up to 8 devices on it but there are only 4 PCI interrupts for it (A, B, C, D). This is OK since interrupts may be shared so that each of the 8 devices (if they exist) can have an interrupt. The PCI interrupt letter of a device is often fixed and hardwired into the device. The assignment of interrupts is done by either the BIOS or Linux mapping the PCI interrupts to the ISA-like interrupts as mentioned above.

If there are only 4 lines (LNKA, LNKB, LNKC, and LNKD) as in the above example, the mapping choices that the PCI BIOS has are limited. Some motherboards may use more lines and thus have more choices. For example LNKA-LNKH (8 lines). The boot-time messages (and dmesg) may display them and how they are mapped. The BIOS knows about how they are wired.

On the PCI bus, the BIOS (or Linux) assigns IRQs (interrupts) so as to avoid conflicts with the IRQs it knows about on the ISA bus. Sometimes the CMOS BIOS menu may allow one to assign IRQs to PCI cards or to tell the BIOS what IRQs are to be reserved for ISA devices. The assignments are known as a "routing table". In MS Windows it's called "IRQ steering" but this also covers the case of dynamic IRQ routing after boot-time. The BIOS may support it's own IRQ steering.

You might think that since the PCI is using IRQs (designed for the ISA bus) it might be slow since the ISA bus was slow. Not really. The ISA Interrupt Controller Chip(s) has a direct interrupt wire going to the CPU so it can get immediate attention. While signals on the old ISA address and data buses are slow to get to the CPU, the IRQ interrupt signals get there very fast. The ACPI even has a narrow bus going directly to the CPU.

Next Previous Contents