pciio_intr(D3)pciio_intr(D3)NAME
pciio_intr: pciio_intr_alloc, pciio_intr_connect, pciio_intr_disconnect,
pciio_intr_free - manage PCI Interrupts
SYNOPSIS
#include <sys/PCI/pciio.h>
pciio_intr_t
pciio_intr_alloc(
vertex_hdl_t vhdl,
device_desc_t desc,
pciio_intr_line_t lines,
vertex_hdl_t owner)
int
pciio_intr_connect(
pciio_intr_t intr,
intr_func_t func,
intr_arg_t arg,
void *thread)
void
pciio_intr_disconnect(pciio_intr_t intr)
void
pciio_intr_free(pciio_intr_t intr)
Arguments
arg A parameter to pass to func() when this particular interrupt
occurs, commonly a pointer to a driver-private data structure.
desc A device descriptor, usually zero.
func The function to perform interrupt service.
intr The interrupt channel handle returned by pciio_intr_alloc().
lines Specifies one or more of the PCI Interrupt pins used by the
device.
owner An appropriate vertex handle to use when printing messages about
this particular interrupt, and is usually a vertex created by the
device driver.
vhdl The PCI device connection point as passed to the driver attach()
entry point.
thread Reserved, should be NULL.
Page 1
pciio_intr(D3)pciio_intr(D3)DESCRIPTION
When a device driver wishes to accept interrupt events from a device, the
system needs to make sure that there is a path from the PCI interrupt pin
to the appropriate CPU interrupt hardware. This is split into two
separate phases, establishing the channel and connecting a service
function, so that the service function can be changed or disconnected
without losing the allocated hardware resources.
The driver is responsible for connecting an interrupt handler when the
device needs one, and for disconnecting the handler when it does not.
The interrupt delivery mechanism depends on the address of the interrupt
function. It is important to disconnect interrupts before a driver
unloads, otherwise the PCI infrastructure might call a nonexistent
function. (A driver cannot be auto-loaded when an interrupt occurs.)
The necessary sequence of calls is based on the use of the driver entry
points, as follows:
reg() Driver registers to handle a class of PCI devices, triggering
attach() calls.
attach() Driver calls pciio_intr_alloc() to established interrupt
connectivity between the device and the processor. The
designated interrupts are disabled at this point. If
interrupts can occur and are needed at this time, a call to
pciio_intr_connect() enables interrupts and directs them to
the designated handler.
unload() The driver is to be unloaded automatically or by operator
command. The driver text is going to be removed, so it is
important for all interrupts to be disconnected.
pciio_iterate() can be used to apply to each of the driver's
connection points, a function that can calls
pciio_intr_disconnect() as appropriate. It is not necessary
or desirable to call pciio_intr_free() at this time.
init() The device driver is being loaded or reloaded. It can again
use pciio_iterate(), this time to call a function that re-
connects interrupts to the new addresses of their service
functions. No special logic is needed to avoid this at the
initial load time, because pciio_iterate() is a no-operation
when the device driver is not registered.
detach() A device is being detached and will no longer be accessible.
The driver calls both pciio_intr_disconnect() and
pciio_intr_free() for this particular device.
unreg() The device driver is shutting down. It calls
pciio_driver_unregister(). This triggers a call to the
detach() entry point for every attached device.
Page 2
pciio_intr(D3)pciio_intr(D3)
Some devices do not require interrupt service when they are not open.
Leaving an interrupt allocated but not connected keeps the interrupt
disabled, possibly reducing impact on the system from handling interrupts
from devices that do not actually need service.
If this is the situation, then the scenario above may be somewhat
simplified:
attach() Allocate the interrupt to establish a connection and disable
the interrupt. Only connect the interrupt if interrupts are
required as part of device initialization; then disconnect
it.
open() If the interrupt is not yet connected, connect it.
close() No processes have the device open; disconnect the interrupt
when all pending I/O is complete or purged.
unload() The driver is not called to unload when one of its devices is
open, so no interrupts should be connected.
detach() Devices are closed before detaching, so no interrupts should
be connected.
Specifying PCI Interrupt Lines
The lines parameter is formed by or-ing together appropriate flags:
PCIIO_INTR_LINE_A
PCIIO_INTR_LINE_B
PCIIO_INTR_LINE_C
PCIIO_INTR_LINE_D
EXAMPLES
Here is how a typical PCI device driver might get interrupt service
started.
pcifoo_attach(vertex_hdl_t pconn_vhdl)
{
pciio_intr_t intr;
...
/* This device uses both INTA and INTB,
* and this driver wants both routed to
* the same interrupt service function.
*/
intr = pciio_intr_alloc(pconn_vhdl, 0,
PCIIO_INTR_LINE_A|
PCIIO_INTR_LINE_B,
pcifoo_vhdl);
pciio_intr_connect(intr,
pcifoo_intr,
(intr_arg_t)pcifoo_soft,
(void *)0);
...
Page 3
pciio_intr(D3)pciio_intr(D3)
}
SEE ALSOpciio(D3), pciio_config(D3), pciio_dma(D3), pciio_error(D3),
pciio_get(D3), pciio_pio(D3).
DIAGNOSTICSpciio_intr_alloc() returns a null value if it can not allocate memory.
pciio_intr_connect() returns a zero for success or a negative value on
failure. Since the channel is preallocated, the only interesting failure
for this function is the attempt to use a null interrupt handle value.
Page 4