| 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_disestablish — PCI
interrupts
#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);
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”.
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);
...
}
These functions first appeared in OpenBSD 1.2.
| November 13, 2024 | openbsd |