NAME
pci_msi
, pci_msix
,
pci_msi_count
,
pci_msi_alloc
,
pci_msi_alloc_exact
,
pci_msix_count
,
pci_msix_alloc
,
pci_msix_alloc_exact
,
pci_msix_alloc_map
,
pci_intx_alloc
,
pci_intr_alloc
,
pci_intr_release
,
pci_intr_type
—
PCI MSI{,-X} manipulation
functions
SYNOPSIS
int
pci_msi_count
(pci_chipset_tag_t
pc, pcitag_t
tag);
int
pci_msi_alloc
(const
struct pci_attach_args *pa,
pci_intr_handle_t **ihps,
int *count);
int
pci_msi_alloc_exact
(const
struct pci_attach_args *pa,
pci_intr_handle_t **ihps,
int count);
int
pci_msix_count
(pci_chipset_tag_t
pc, pcitag_t
tag);
int
pci_msix_alloc
(const
struct pci_attach_args *pa,
pci_intr_handle_t **ihps,
int *count);
int
pci_msix_alloc_exact
(const
struct pci_attach_args *pa,
pci_intr_handle_t **ihps,
int count);
int
pci_msix_alloc_map
(const
struct pci_attach_args *pa,
pci_intr_handle_t **ihps,
u_int *table_indexes,
int count);
int
pci_intx_alloc
(const
struct pci_attach_args *pa,
pci_intr_handle_t
**ihp);
int
pci_intr_alloc
(const
struct pci_attach_args *pa,
pci_intr_handle_t **ihp,
int *counts,
pci_intr_type_t
max_type);
void
pci_intr_release
(pci_chipset_tag_t
pc, pci_intr_handle_t
*pih, int
count);
pci_intr_type_t
pci_intr_type
(pci_chipset_tag_t
pc, pci_intr_handle_t
ih);
DESCRIPTION
Thepci_msi
functions exist to allow device drivers to
use MSI/MSI-X. When the system uses MSI/MSI-X, it must define the
__HAVE_PCI_MSI_MSIX
build option.
Each driver has an
attach
()
function which has a bus-specific attach_args
structure. Each driver for a PCI device is passed a pointer to an object of
type struct pci_attach_args which contains, among
other things, information about the location of the device in the PCI bus
topology sufficient to allow interrupts from the device to be handled.
pci_msi_count
()
returns the max number of the device's MSI. If the device can not use MSI,
pci_msi_count
() returns zero.
pci_msix_count
()
works in the same manner for MSI-X.
If a driver wishes to establish an MSI handler
for the device, it should pass the struct pci_attach_args
* and count
pci_msi_alloc
()
or
pci_msi_alloc_exact
()
functions, which return zero on success, and nonzero on failure. When the
functions are successful, they return the pointer to the allocated handle
array in pihs whose size is
count or less. The difference between
pci_msi_alloc
() and
pci_msi_alloc_exact
() is whether
count can be decremented or not.
pci_msi_alloc
() can decrement
count, and which is similar to
FreeBSD's
pci_alloc_msi
().
In contrast, pci_msi_alloc_exact
() can not decrement
count.
If the driver wishes to refer to the MSI
source in an attach or error message, it should use the value returned by
pci_intr_string
()
the same as INTx. The buffer passed to
pci_intr_string
() should be at least
PCI_INTRSTR_LEN
bytes long.
Subsequently, when the driver is prepared
to receive MSIs, it should call
pci_intr_establish
()
the same as INTx to actually establish the handler; when the device
interrupts, intrhand will be called with a single
argument intrarg, and will run at the interrupt
priority level ipl.
The return value of
pci_intr_establish
()
may be saved and passed to
pci_intr_disestablish
()
to disable the interrupt handler the same as INTx when the driver is no
longer interested in MSIs from the device. After that, the driver should
also call pci_intr_release
() to free resources about
MSI as well as INTx and MSI-X. If pih is NULL,
pci_intr_release
() does nothing.
If a driver wishes to establish an MSI-X
handler for the device, it is almost the same as MSI. The only differences
is
pci_msix_alloc_map
().
This function can assign separate handlers for each MSI-X table entry. I.e.,
if the driver wants to assign the handlers in the following way:
msix_handler0 => MSI-X table index: 4 msix_handler1 => MSI-X table index: 5 msix_handler2 => MSI-X table index: 0
table_indexes[0] = 4; table_indexes[1] = 5; table_indexes[2] = 0;
If the driver wants to fall back to INTx, the
driver should use
pci_intx_alloc
()
and
pci_intr_release
()
instead of
pci_intr_map
()
to resolve contradiction of the interrupt handler ownership. I.e.,
pci_intr_map
() does not have the ownership (the
function just calculates value), in contrast,
pci_msi_alloc
() and
pci_msix_alloc
()
have (the functions allocate memory for interrupt handlers).
pci_intr_alloc
()
is wrapper function which select and automatically fallback allocation
functions according to the argument counts. The
elements of counts array means each required interrupt
count for INTx, MSI, and MSI-X. The index count of
counts must be
PCI_INTR_TYPE_SIZE
. max_type
must be PCI_INTR_TYPE_MSIX
,
PCI_INTR_TYPE_MSI
, or
PCI_INTR_TYPE_INTX
. The parameter does not mean
array index counts of counts. The parameter means the
interrupt type which pci_intr_alloc
() tries to
allocate first. I.e., if the driver wants to allocate interrupts in the
following way:
5 MSI-X 1 MSI (if MSI-X allocation failed) INTx (if MSI allocation failed either)
pci_intr_alloc
() in the following
way:
int counts[PCI_INTR_TYPE_SIZE]; counts[PCI_INTR_TYPE_MSIX] = 5; counts[PCI_INTR_TYPE_MSI] = 1; counts[PCI_INTR_TYPE_INTX] = 1; error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSIX);
hardware max number MSI-X 1 MSI (if MSI-X allocation failed)
pci_intr_alloc
() in the following way:
int counts[PCI_INTR_TYPE_SIZE]; counts[PCI_INTR_TYPE_MSIX] = -1; /* -1 means max */ counts[PCI_INTR_TYPE_MSI] = 1; counts[PCI_INTR_TYPE_INTX] = 0; /* 0 means not use */ error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSIX);
3 MSI INTx (if MSI allocation failed)
pci_intr_alloc
() in the following way:
int counts[PCI_INTR_TYPE_SIZE]; counts[PCI_INTR_TYPE_MSIX] = 0; /* 0 means not use */ counts[PCI_INTR_TYPE_MSI] = 3; counts[PCI_INTR_TYPE_INTX] = 1; error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSI);
1 MSI-X 1 MSI INTx (if MSI/MSI-X allocation failed)
pci_intr_alloc
() in the following way:
error = pci_intr_alloc(pa, ihps, NULL, 0);
pci_intr_alloc
() returns zero on any allocation
function success, and non-zero on all allocation function failures. On
success, counts is overwritten by a really allocated
count. I.e., if 5 MSI-X is allocated, counts is
counts[PCI_INTR_TYPE_MSIX] == 5 counts[PCI_INTR_TYPE_MSI] == 0 counts[PCI_INTR_TYPE_INTX] == 0
pci_intr_type
()
returns the interrupt type of ih. The return value is
PCI_INTR_TYPE_MSIX
for MSI-X,
PCI_INTR_TYPE_MSI
for MSI, and
PCI_INTR_TYPE_INTX
for others.
SEE ALSO
HISTORY
pci_msi
support first appeared in
NetBSD 8.0. Support is present on
i386,
amd64
and
aarch64
architectures.
AUTHORS
The pci_msi
interfaces were designed and
implemented by Kengo Nakahara
<knakahara@NetBSD.org>.