Kernel Functions for Drivers ddiintraddsoftint(9F)
NAME
ddiintraddsoftint, ddiintrremovesoftint,
ddiintrtriggersoftint, ddiintrgetsoftintpri,
ddiintrsetsoftintpri - software interrupt handling rou-
tines
SYNOPSIS
#include
#include
#include
#include
int ddiintraddsoftint(devinfot *dip,
ddisoftinthandlet *h, int softpri,
ddiintrhandlert handler, void *arg1);
int ddiintrtriggersoftint(ddisoftinthandlet h,
void *arg2);
int ddiintrremovesoftint(ddisoftinthandlet h);
int ddiintrgetsoftintpri(ddisoftinthandlet h,
uint *softprip);
int ddiintrsetsoftintpri(ddisoftinthandlet h,
uint softpri);
INTERFACE LEVEL
Solaris DI specific (Solaris DI).
PARAMETERS
ddiintraddsoftint()
dip Pointer to a devinfo structure
h Pointer to the DI soft interrupt handle
softpri Priority to associate with a soft interrupt
handler Pointer to soft interrupt handler
SunOS 5.11 Last change: 16 Oct 2005 1
Kernel Functions for Drivers ddiintraddsoftint(9F)
arg1 Argument for the soft interrupt handler
ddiintrtriggersoftint()
h DI soft interrupt handle
arg2 Additional argument for the soft interrupt handler
ddiintrremovesoftint()
h DI soft interrupt handle
ddiintrgetsoftintpri()
h DI soft interrupt handle
softprip Soft interrupt priority of the handle
ddiintrsetsoftintpri()
h DI soft interrupt handle
softprip Soft interrupt priority of the handle
DESCRIPTION
The ddiintraddsoftint() function adds the soft interrupt
handler given by the handler argument arg1. The handler runs
at the soft interrupt priority given by the softpri argu-
ment.
The value returned in the location pointed at by h is the
soft interrupt handle. This value is used in later calls to
ddiintrremovesoftint(), ddiintrtriggersoftint() and
ddiintrsetsoftintpri().
The software priority argument softpri is a relative prior-
ity value within the range of DINTRSOFTPRIMIN and
DINTRSOFTPRIMAX. If the driver does not know what
SunOS 5.11 Last change: 16 Oct 2005 2
Kernel Functions for Drivers ddiintraddsoftint(9F)
priority to use, the default softpri value of
DINTRSOFTPRIDEFAULT could be specified. The default
value is the lowest possible soft interrupt priority value.
The softpri argument contains the value needed to initial-
ize the lock associated with a soft interrupt. See
mutexinit(9F) and rwinit(9F). The handler cannot be trig-
gered until the lock is initiatized.
The ddiintrremovesoftint() function removes the handler
for the soft interrupt identified by the interrupt handle h
argument. Once removed, the soft interrupt can no longer be
triggered, although any trigger calls in progress can still
be delivered to the handler.
Drivers must remove any soft interrupt handlers before
allowing the system to unload the driver. Otherwise, kernel
resource leaks might occur.
The ddiintrtriggersoftint() function triggers the soft
interrupt specified by the interrupt handler h argument. A
driver may optionally specify an additional argument arg2
that is passed to the soft interrupt handler. Subsequent
ddiintrtriggersoftint() events, along with arg2, will be
dropped until the one pending is serviced and returns the
error code DIEPENDING.
The routine handler, with the arg1 and arg2 arguments, is
called upon the receipt of a software interrupt. These were
registered through a prior call to ddiintraddsoftint().
Software interrupt handlers must not assume that they have
work to do when they run. Like hardware interrupt handlers,
they may run because a soft interrupt has occurred for some
other reason. For example, another driver may have triggered
a soft interrupt at the same level. Before triggering the
soft interrupt, the driver must indicate to the soft inter-
rupt handler that it has work to do. This is usually done by
setting a flag in the state structure. The routine handler
checks this flag, reached through arg1 and arg2, to deter-
mine if it should claim the interrupt and do its work.
The interrupt handler must return DINTRCLAIMED if the
interrupt was claimed and DINTRUNCLAIMED otherwise.
SunOS 5.11 Last change: 16 Oct 2005 3
Kernel Functions for Drivers ddiintraddsoftint(9F)
The ddiintrgetsoftintpri() function retrieves the soft
interrupt priority, a small integer value, associated with
the soft interrupt handle. The handle is defined by the h
argument, and the priority returned is in the value of the
integer pointed to by the softprip argument.
RETURN VALUES
The ddiintraddsoftint(), ddiintrremovesoftint(),
ddiintrtriggersoftint(), ddiintrgetsoftintpri(),
ddiintrsetsoftintpri() functions return:
DISUCES On success.
DIEAGAIN On encountering internal error regarding
currently unavailable resources.
DIEINVAL On encountering invalid input parameters.
DIFAILURE On any implementation specific failure.
DIEPENDING On encountering a previously triggered sof-
tint event that is pending.
CONTEXT
The ddiintraddsoftint(), ddiintrremovesoftint(),
ddiintrtriggersoftint(), ddiintrgetsoftintpri(),
ddiintrsetsoftintpri() functions can be called from
either user or kernel non-interrupt context.
EXAMPLES
Example 1 Device using high-level interrupts
In the following example, the device uses high-level inter-
rupts. High-level interrupts are those that interrupt at the
level of the scheduler and above. High-level interrupts must
be handled without using system services that manipulate
thread or process states, because these interrupts are not
blocked by the scheduler. In addition, high-level interrupt
handlers must take care to do a minimum of work because they
are not preemptable. See ddiintrgethilevelpri(9F).
In the example, the high-level interrupt routine minimally
services the device, and enqueues the data for later pro-
cessing by the soft interrupt handler. If the soft interrupt
SunOS 5.11 Last change: 16 Oct 2005 4
Kernel Functions for Drivers ddiintraddsoftint(9F)
handler is not currently running, the high-level interrupt
routine triggers a soft interrupt so the soft interrupt
handler can process the data. Once running, the soft inter-
rupt handler processes all the enqueued data before return-
ing.
The state structure contains two mutexes. The high-level
mutex is used to protect data shared between the high-level
interrupt handler and the soft interrupt handler. The low-
level mutex is used to protect the rest of the driver from
the soft interrupt handler.
struct xxstate {
...
ddiintrhandlet inthdl;
int highpri;
kmutext highmutex;
ddisoftinthandlet softhdl;
int lowsoftpri;
kmutext lowmutex;
int softintrunning;
...
};
struct xxstate *xsp;
static uintt xxsoftinthandler(void *, void *);
static uintt xxhighintr(void *, void *);
...
Example 2 Sample attach() routine
The following code fragment would usually appear in the
driver's attach(9E) routine. ddiintraddhandler(9F) is
used to add the high-level interrupt handler and
ddiintraddsoftint() is used to add the low-level inter-
rupt routine.
static uintt
xxattach(devinfot *dip, ddiattachcmdt cmd)
{
int types;
int *actual;
int nintrs;
struct xxstate *xsp;
...
SunOS 5.11 Last change: 16 Oct 2005 5
Kernel Functions for Drivers ddiintraddsoftint(9F)
(void) ddiintrgetsupportedtypes(dip, &types);
(void) ddiintrgetnintrs(dip< DINTRTYPEFIXED, *nintrs);
(void) ddiintralloc(dip, &xsp->inthdl, DINTRTYPEFIXED,
1, nintrs, *actual, 0);
/* initialize high-level mutex */
(void) ddiintrgetpri(xsp->inthdl, &>highpri);
mutexinit(&xsp->highmutex, NUL, MUTEXDRIVER,
DINTRPRI(xsp->highpri));
/* Ensure that this is a hi-level interrupt */
if (ddiintrgethilevelpri(h) != DISUCES) {
/* cleanup */
return (DIFAILURE); /* fail attach */
}
/* add high-level routine - xxhighintr() */
if (ddiintraddhandler(xsp->inthdl, xxhighintr,
arg1, NUL) != DISUCES) {
/* cleanup */
return (DIFAILURE); /* fail attach */
}
/* Enable high-level routine - xxhighintr() */
if (ddiintrenable(xsp->inthdl) != DISUCES) {
/* cleanup */
return (DIFAILURE); /* fail attach */
}
/* Enable soft interrupts */
xsp->lowsoftpri = DINTRSOFTPRIMIN;
if (ddiintraddsoftint(dip, &xsp>softhdl,
xsp->lowsoftpri, xxsoftinthandler, arg1) != DISUCES) {
/* clean up */
return (DIFAILURE); /* fail attach */
}
/* initialize low-level mutex */
mutexinit(&xsp->lowmutex, NUL, MUTEXDRIVER,
DINTRPRI(xsp->lowsoftpri));
...
}
Example 3 High-level interrupt routine
The next code fragment represents the high-level interrupt
routine. The high-level interrupt routine minimally services
the device and enqueues the data for later processing by the
soft interrupt routine. If the soft interrupt routine is not
SunOS 5.11 Last change: 16 Oct 2005 6
Kernel Functions for Drivers ddiintraddsoftint(9F)
already running, ddiintrtriggersoftint() is called to
start the routine. The soft interrupt routine will run until
there is no more data on the queue.
static uintt
xxhighintr(void *arg1, void *arg2)
{
struct xxstate *xsp = (struct xxstate *)arg1;
int needsoftint;
...
mutexenter(&xsp->highmutex);
/*
* Verify this device generated the interrupt
* and disable the device interrupt.
* Enqueue data for xxsoftinthandler() processing.
*/
/* is xxsoftinthandler() already running ? */
needsoftint = (xsp->softintrunning) ? 0 : 1;
mutexexit(&xsp->highmutex);
/* read-only access to xsp->id, no mutex needed */
if (xsp->softhdl && needsoftint)
ddiintrtriggersoftint(xsp->softhdl, arg2);
...
return (DINTRCLAIMED);
}
static uintt
xxsoftinthandler(void *arg1, void *arg2)
{
struct xxstate *xsp = (struct xxstate *)arg1;
...
mutexenter(&xsp->lowmutex);
mutexenter(&xsp->highmutex);
/* verify there is work to do */
if (work queue empty xsp->softintrunning ) {
mutexexit(&xsp->highmutex);
mutexexit(&xsp->lowmutex);
return (DINTRUNCLAIMED);
}
xsp->softintrunning = 1;
while ( data on queue ) {
ASERT(mutexowned(&xsp->highmutex));
/* de-queue data */
mutexexit(&xsp->highmutex);
SunOS 5.11 Last change: 16 Oct 2005 7
Kernel Functions for Drivers ddiintraddsoftint(9F)
/* Process data on queue */
mutexenter(&xsp->highmutex);
}
xsp->softintrunning = 0;
mutexexit(&xsp->highmutex);
mutexexit(&xsp->lowmutex);
return (DINTRCLAIMED);
}
ATRIBUTES
See attributes(5) for descriptions of the following attri-
butes:
ATRIBUTE TYPE ATRIBUTE VALUE
Interface Stability Evolving
SEE ALSO
attributes(5), attach(9E), ddiintralloc(9F),
ddiintrfree(9F), ddiintrgethilevelpri(9F),
mutexinit(9F), rwinit(9F), rwlock(9F)
Writing Device Drivers
NOTES
Consumers of these interfaces should verify that the return
value is not equal to DISUCES. Incomplete checking for
failure codes could result in inconsistent behavior among
platforms.
The ddiintraddsoftint() may not be used to add the same
software interrupt handler more than once. This is true even
if a different value is used for arg1 in each of the calls
to ddiintraddsoftint(). Instead, the argument passed to
the interrupt handler should indicate what service(s) the
interrupt handler should perform. For example, the argument
could be a pointer to the soft state structure of the device
that could contain a whichservice field that the handler
examines. The driver must set this field to the appropriate
value before calling ddiintrtriggersoftint().
SunOS 5.11 Last change: 16 Oct 2005 8
Kernel Functions for Drivers ddiintraddsoftint(9F)
Every time a modifiable valid second argument, arg2, is pro-
vided when ddiintrtriggersoftint() is invoked, the DI
framework saves arg2 internally and passes it to the inter-
rupt handler handler.
A call to ddiintrsetsoftintpri() could fail if a previ-
ously scheduled soft interrupt trigger is still pending.
SunOS 5.11 Last change: 16 Oct 2005 9
|