PCI_INTR_MAP(9) | Kernel Developer's Manual | PCI_INTR_MAP(9)

# NAME

`pci_intr_map`, `pci_intr_map_msi`, `pci_intr_map_msix`, `pci_intr_line`, `pci_intr_string`, `pci_intr_establish`, `pci_intr_disestablish` — PCI interrupts

# SYNOPSIS

`#include <alpha/pci/pci_machdep.h>`
`#include <i386/pci/pci_machdep.h>`
`#include <machine/pci_machdep.h>`

int
`pci_intr_map`(struct pci_attach_args *paa, pci_intr_handle_t *ih);

int
`pci_intr_map_msi`(struct pci_attach_args *paa, pci_intr_handle_t *ih);

int
`pci_intr_map_msix`(struct pci_attach_args *paa, int vector, pci_intr_handle_t *ih);

int
`pci_intr_line`(pci_intr_handle_t ih);

const char *
`pci_intr_string`(pci_chipset_tag_t pc, pci_intr_handle_t ih);

void *
`pci_intr_establish`(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int (*func)(void *), void *arg, const char *name);

void
`pci_intr_disestablish`(pci_chipset_tag_t pc, void *v);

# DESCRIPTION

These functions are provided by the machine-dependent implementation for attaching handler functions to the interrupts of PCI devices.

An architect type is provided by the machine-dependent code pci_intr_handle_t, to be initialised by `pci_intr_map`(), `pci_intr_map_msi`(), or `pci_intr_map_msix`().

The `pci_intr_map`() function should be called first to establish a mapping between a PCI pin and the interrupt controller's interrupt vector. This process may include resolving the mapping through firmware-provided information.

For devices that support Message Signaled Interrupts (MSI) the `pci_intr_map_msi`() function should be called instead. This function can fail if the system does not support MSI. In that case `pci_intr_map`() should be called to fall back on classic PCI interrupts.

For devices that support Extended Message Signaled Interrupts (MSI-X) the `pci_intr_map_msix`() function can be called instead. This function can fail if the system does not support MSI-X. In that case `pci_intr_map_msi`() or `pci_intr_map`() can be called to fall back on Message Signalled Interrupts or classic PCI interrupts respectively. MSI-X can provide multiple interrupt vectors per device. For each vector, a separate call to `pci_intr_map_msix`() is made with the vector argument specifying which interrupt vector to map.

Having initialised the pci_intr_handle_t in the previous step, an interrupt handler can be established using `pci_intr_establish`(). An established interrupt handler is always called with the system interrupt priority level set equal to, or higher than, level.

A printable string representation of an initialised interrupt mapping can be generated with `pci_intr_string`().

`pci_intr_line`() provides the interrupt line extracted from the MD interrupt handle. Upon device detachment, `pci_intr_disestablish`() should be used to disassociate the handler from the interrupt.

See spl(9) for an explanation of the ipl “interrupt priority levels”.

# EXAMPLES

A typical code sequence for establishing a handler for a device interrupt in the driver might be:

    int
    xxxattach(struct device *parent, struct device *self, void *aux)
    {
    	struct xxx_softc *sc = (struct xxx_softc *)self;
    	struct pci_attach_args *pa = aux;
    	pci_intr_handle_t ih;
    	const char *intrstr;
    	bus_size_t size;

    	...

    	if (pci_intr_map_msi(pa, &ih) && pci_intr_map(pa, &ih)) {
    		printf(": can't map interrupt\n");
    		bus_space_unmap(sc->iot, sc->ioh, size);
    		return;
    	}
    	intrstr = pci_intr_string(pa->pa_pc, ih);
    	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
    	    xxx_intr, sc, sc->sc_dev.dv_xname);
    	if (!sc->sc_ih) {
    		printf(": can't establish interrupt");
    		if (intrstr)
    			printf(" at %s", intrstr);
    		printf("\n");
    		bus_space_unmap(sc->iot, sc->ioh, size);
    		return;
    	}

    	printf(": %s\n", intrstr);

    	...
    }

# SEE ALSO

cardbus(4), pci(4), pcibios(4), pci_conf_read(9), spl(9)

# HISTORY

These functions first appeared in OpenBSD 1.2.

November 13, 2024 | Debian