NAME
pci_intr_map
,
pci_intr_map_msi
,
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_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
()
or
pci_intr_map_msi
().
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.
Having initialised the
pci_intr_handle_t in the previous step, an interrupt
handler can be established using
pci_intr_establish
()
or converted into printable form using
pci_intr_string
().
A handler established using pci_intr_establish
() is
always called with the system interrupt priority level set equal to, or
higher than, level.
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.