xtalk_intr(D3)xtalk_intr(D3)NAME
xtalk_intr_alloc - allocate a XIO Interrupt channel
xtalk_intr_connect - connect handling function
xtalk_intr_disconnect - disconnect handling function
xtalk_intr_free - release a XIO Interrupt channel
SYNOPSIS
#include <sys/XIO/xtalk.h>
xtalk_intr_t
xtalk_intr_alloc(vertex_hdl_t vhdl,
device_desc_t desc,
vertex_hdl_t owner)
int
xtalk_intr_connect(xtalk_intr_t intr,
intr_func_t func,
intr_arg_t arg,
xtalk_intr_setfunc_t setfunc,
void *setfunc_arg,
void *thread)
void
xtalk_intr_disconnect(xtalk_intr_t intr)
void
xtalk_intr_free(xtalk_intr_t intr)
Arguments
vhdl is the appropriate XIO connection point.
desc is a device descriptor, usually zero.
lines specifies one or more of the XIO Interrupt pins connected to the
card.
owner is an appropriate vertex handle to use when printing messages
about this particular interrupt, and is usually a vertex created
by the device driver.
intr is the opaque interrupt channel handle
func is a function to be used for interrupt service
arg is the parameter to pass to the function when this particular
interrupt occurs, and is commonly a pointer to a driver-private
data structure.
setfunc is a callback function that will be called by the infrastructure
to set up a new interrupt target widget number, address, or
vector. It will always be called once, to set the initial
Page 1
xtalk_intr(D3)xtalk_intr(D3)
assignment; the system may call it again, later, if the interrupt
needs to be migrated to a different target.
setfunc_arg
is an opaque value, owned by the driver, that is stored within
the interrupt structure and can be retrieved by the driver using
xtalk_intr_sfarg_get().
thread is reserved for use by the interrupt threads subsystem, and
should be NULL.
DESCRIPTION
When a device driver wishes to accept interrupt events from a device, the
system needs to assign a target CPU and allocate a vector number on that
CPU's XIO interface. The target information is then reported back to the
driver, which can set up its device to send XIO interrupt packets with
the proper data to the correct target port and address. Only then can a
service function be attached to the interrupt channel.
This three-phase handling of the XIO interrupt setup allows several
things:
o The service function can be changed (or disconnected entirely)
without losing any hardware resources and having to reallocate them
in the process.
o The interrupt can be retargeted from one processor to another, should
upper layers of software decide this is necessary.
Since the interrupt delivery mechanism carries the address of the
interrupt function, it is important to disconnect your interrupts before
unloading your driver. Your driver will not be auto-loaded when an
interrupt occurs.
The necessary sequence of calls is as follows:
o When the device is initially attached, xtalk_intr_alloc() should be
used to establish interrupt connectivity between the device and the
processor. It is common to call xtalk_intr_connect() at this time.
o xtalk_intr_connect() triggers the first callback to the setfunc so
the driver can correctly configure its hardware for the target
processor, XIO port, XIO address, and vector number.
o If the device driver is automatically unloading, it will be unloaded
shortly after the attaches are complete. Since the driver text is
going away, it is important for all interrupts to be disconnected.
xtalk_iterate() should be used to call a function with each of the
driver's connection points, which can then execute the proper
disconnect calls.
Page 2
xtalk_intr(D3)xtalk_intr(D3)
o When the device driver is reloaded, its pfxinit() entry point is
called. The device driver should again use xtalk_iterate(), this
time to call a function that will re-connect interrupts to the new
address of the service function. No special logic is needed to
prevent this at the initial load time, since xtalk_iterate() is a
no-operation when the device driver is not registered.
o When the device driver is unregistered, the act of unregistering with
the XTALK infrastructure will trigger calls to pfxdetach() which
should disconnect all interrupt service.
Alternate Scenario
Some devices may not require interrupt service when they are not open.
Leaving an interrupt allocated but not connected will keep it disabled,
possibly reducing impact on the system from devices that may interrupt
when there is no interest from the driver in actually performing any
services.
If this is true, then the scenario above may be somewhat simplified:
o If interrupts are required as part of setting up the device in
pfxattach(), then they can be connected, then disconnected before
pfxattach() returns.
o Since interrupts are not active when the device is closed,
pfxunload() and pfxdetach() do not need to worry about disconnecting
the interrupt services, and pfxinit() does not need to worry about
reconnecting them. Instead, pfxopen() would connect the interrupt on
first open, and pfxclose() would disconnect the interrupt on last
close.
EXAMPLES
Here is a simple example of how an XIO device driver might get interrupt
service started.
xiofoo_attach(vertex_hdl_t xconn_vhdl)
{
xtalk_intr_t intr;
struct xiofoo_regs *xiofoo_regs;
...
/* This driver uses both line A and line B,
* and wants to route both to the same
* service function.
*/
intr = xtalk_intr_alloc(xconn_vhdl, 0, xiofoo_vhdl);
/* Arrange for the "soft" pointer to
* be the parameter for the interrupt,
* and for the device registers themselves
Page 3
xtalk_intr(D3)xtalk_intr(D3)
* to be the parameter for the setfunc()
* call.
*/
xtalk_intr_connect(
intr,
xiofoo_intr,
(intr_arg_t)xiofoo_soft,
xiofoo_intr_setfunc,
(void *)xiofoo_regs,
(void *)0);
...
}
static void
xiofoo_intr_setfunc(xtalk_intr_t intr)
{
xwidgetnum_t targ = xtalk_intr_target_get(intr);
iopaddr_t addr = xtalk_intr_addr_get(intr);
xtalk_intr_vector_t vect = xtalk_intr_vector_get(intr);
struct xiofoo_regs *fooregs;
fooregs = (struct xiofoo_regs *)
xtalk_intr_sfarg_get(intr);
fooregs->control &= FOOREGS_INT_ENABLE;
fooregs->intr_port = targ;
fooregs->intr_addr = addr;
fooregs->intr_vect = vect;
fooregs->control |= FOOREGS_INT_ENABLE;
}
/
SEE ALSOxtalk(D3), xtalk_dma(D3), xtalk_error(D3), xtalk_get(D3), xtalk_pio(D3).
DIAGNOSTICSxtalk_intr_alloc() will return a null value if it can not allocate
memory.
xtalk_intr_connect() will return a zero for success, or a negative value
on failure. Since the channel is preallocated, the only interesting
failure is the attempt to use a null interrupt cookie value.
Page 4