OpenBSD manual page server

Manual Page Search Parameters

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

pci_intr_map, pci_intr_map_msi, pci_intr_map_msix, pci_intr_line, pci_intr_string, pci_intr_establish, pci_intr_disestablishPCI interrupts

#include <alpha/pci/pci_machdep.h>
#include <i386/pci/pci_machdep.h>
#include <powerpc/pci/pci_machdep.h>
#include <sgi/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);

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_msi(), or pci_intr_map_msix().

The () 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 () 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 () 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 (). 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 ().

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

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

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);

	...
}

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

These functions first appeared in OpenBSD 1.2.

June 17, 2020 OpenBSD-6.8