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
<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);
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
HISTORY
These functions first appeared in OpenBSD 1.2.