2 .\" Copyright (c) 2005, Sun Microsystems, Inc. All Rights Reserved.
3 .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
4 .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
5 .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
6 .TH DDI_INTR_ADD_SOFTINT 9F "Oct 16, 2005"
8 ddi_intr_add_softint, ddi_intr_remove_softint, ddi_intr_trigger_softint,
9 ddi_intr_get_softint_pri, ddi_intr_set_softint_pri \- software interrupt
14 #include <sys/types.h>
17 #include <sys/sunddi.h>
21 \fBint\fR \fBddi_intr_add_softint\fR(\fBdev_info_t *\fR\fIdip\fR,
22 \fBddi_softint_handle_t *\fR\fIh\fR, \fBint\fR \fIsoft_pri\fR,
23 \fBddi_intr_handler_t\fR \fIhandler\fR, \fBvoid *\fR\fIarg1\fR);
28 \fBint\fR \fBddi_intr_trigger_softint\fR(\fBddi_softint_handle_t\fR \fIh\fR,
29 \fBvoid *\fR\fIarg2\fR);
34 \fBint\fR \fBddi_intr_remove_softint\fR(\fBddi_softint_handle_t\fR \fIh\fR);
39 \fBint\fR \fBddi_intr_get_softint_pri\fR(\fBddi_softint_handle_t\fR \fIh\fR,
40 \fBuint *\fR\fIsoft_prip\fR);
45 \fBint\fR \fBddi_intr_set_softint_pri\fR(\fBddi_softint_handle_t\fR \fIh\fR,
46 \fBuint\fR \fIsoft_pri\fR);
52 Solaris DDI specific (Solaris DDI).
56 \fBddi_intr_add_softint()\fR
63 Pointer to a \fBdev_info\fR structure
72 Pointer to the DDI soft interrupt handle
81 Priority to associate with a soft interrupt
90 Pointer to soft interrupt handler
99 Argument for the soft interrupt handler
104 \fBddi_intr_trigger_softint()\fR
111 DDI soft interrupt handle
120 Additional argument for the soft interrupt handler
125 \fBddi_intr_remove_softint()\fR
132 DDI soft interrupt handle
137 \fBddi_intr_get_softint_pri()\fR
144 DDI soft interrupt handle
150 \fB\fIsoft_prip\fR\fR
153 Soft interrupt priority of the handle
158 \fBddi_intr_set_softint_pri()\fR
165 DDI soft interrupt handle
171 \fB\fIsoft_prip\fR\fR
174 Soft interrupt priority of the handle
180 The \fBddi_intr_add_softint()\fR function adds the soft interrupt handler given
181 by the \fIhandler\fR argument \fIarg1\fR. The \fIhandler\fR runs at the soft
182 interrupt priority given by the \fIsoft_pri\fR argument.
185 The value returned in the location pointed at by \fIh\fR is the soft interrupt
186 handle. This value is used in later calls to \fBddi_intr_remove_softint()\fR,
187 \fBddi_intr_trigger_softint()\fR and \fBddi_intr_set_softint_pri()\fR.
190 The software priority argument \fIsoft_pri\fR is a relative priority value
191 within the range of \fBDDI_INTR_SOFTPRI_MIN\fR and \fBDDI_INTR_SOFTPRI_MAX\fR.
192 If the driver does not know what priority to use, the default \fIsoft_pri\fR
193 value of \fBDDI_INTR_SOFTPRI_DEFAULT\fR could be specified. The default value
194 is the lowest possible soft interrupt priority value.
197 The \fIsoft_pri\fR argument contains the value needed to initialize the lock
198 associated with a soft interrupt. See \fBmutex_init\fR(9F) and
199 \fBrw_init\fR(9F). The handler cannot be triggered until the lock is
203 The \fBddi_intr_remove_softint()\fR function removes the handler for the soft
204 interrupt identified by the interrupt handle \fIh\fR argument. Once removed,
205 the soft interrupt can no longer be triggered, although any trigger calls in
206 progress can still be delivered to the handler.
209 Drivers must remove any soft interrupt handlers before allowing the system to
210 unload the driver. Otherwise, kernel resource leaks might occur.
213 The \fBddi_intr_trigger_softint()\fR function triggers the soft interrupt
214 specified by the interrupt handler \fIh\fR argument. A driver may optionally
215 specify an additional argument \fIarg2\fR that is passed to the soft interrupt
216 handler. Subsequent \fBddi_intr_trigger_softint()\fR events, along with
217 \fIarg2\fR, will be dropped until the one pending is serviced and returns the
218 error code \fBDDI_EPENDING\fR.
221 The routine \fIhandler\fR, with the \fIarg1\fR and \fIarg2\fR arguments, is
222 called upon the receipt of a software interrupt. These were registered through
223 a prior call to \fBddi_intr_add_softint()\fR. Software interrupt handlers must
224 not assume that they have work to do when they run. Like hardware interrupt
225 handlers, they may run because a soft interrupt has occurred for some other
226 reason. For example, another driver may have triggered a soft interrupt at the
227 same level. Before triggering the soft interrupt, the driver must indicate to
228 the soft interrupt handler that it has work to do. This is usually done by
229 setting a flag in the state structure. The routine \fIhandler\fR checks this
230 flag, reached through \fIarg1\fR and \fIarg2\fR, to determine if it should
231 claim the interrupt and do its work.
234 The interrupt handler must return \fBDDI_INTR_CLAIMED\fR if the interrupt was
235 claimed and \fBDDI_INTR_UNCLAIMED\fR otherwise.
238 The \fBddi_intr_get_softint_pri()\fR function retrieves the soft interrupt
239 priority, a small integer value, associated with the soft interrupt handle. The
240 handle is defined by the \fIh\fR argument, and the priority returned is in the
241 value of the integer pointed to by the \fIsoft_prip\fR argument.
245 The \fBddi_intr_add_softint()\fR, \fBddi_intr_remove_softint()\fR,
246 \fBddi_intr_trigger_softint()\fR, \fBddi_intr_get_softint_pri()\fR,
247 \fBddi_intr_set_softint_pri()\fR functions return:
251 \fB\fBDDI_SUCCESS\fR\fR
260 \fB\fBDDI_EAGAIN\fR\fR
263 On encountering internal error regarding currently unavailable resources.
269 \fB\fBDDI_EINVAL\fR\fR
272 On encountering invalid input parameters.
278 \fB\fBDDI_FAILURE\fR\fR
281 On any implementation specific failure.
287 \fB\fBDDI_EPENDING\fR\fR
290 On encountering a previously triggered softint event that is pending.
296 The \fBddi_intr_add_softint()\fR, \fBddi_intr_remove_softint()\fR,
297 \fBddi_intr_trigger_softint()\fR, \fBddi_intr_get_softint_pri()\fR,
298 \fBddi_intr_set_softint_pri()\fR functions can be called from either user or
299 kernel non-interrupt context.
302 \fBExample 1 \fRDevice using high-level interrupts
305 In the following example, the device uses high-level interrupts. High-level
306 interrupts are those that interrupt at the level of the scheduler and above.
307 High-level interrupts must be handled without using system services that
308 manipulate thread or process states, because these interrupts are not blocked
309 by the scheduler. In addition, high-level interrupt handlers must take care to
310 do a minimum of work because they are not preemptable. See
311 \fBddi_intr_get_hilevel_pri\fR(9F).
315 In the example, the high-level interrupt routine minimally services the device,
316 and enqueues the data for later processing by the soft interrupt handler. If
317 the soft interrupt handler is not currently running, the high-level interrupt
318 routine triggers a soft interrupt so the soft interrupt handler can process the
319 data. Once running, the soft interrupt handler processes all the enqueued data
324 The state structure contains two mutexes. The high-level mutex is used to
325 protect data shared between the high-level interrupt handler and the soft
326 interrupt handler. The low-level mutex is used to protect the rest of the
327 driver from the soft interrupt handler.
334 ddi_intr_handle_t int_hdl;
337 ddi_softint_handle_t soft_hdl;
345 static uint_t xxsoftint_handler(void *, void *);
346 static uint_t xxhighintr(void *, void *);
352 \fBExample 2 \fRSample \fBattach()\fR routine
355 The following code fragment would usually appear in the driver's
356 \fBattach\fR(9E) routine. \fBddi_intr_add_handler\fR(9F) is used to add the
357 high-level interrupt handler and \fBddi_intr_add_softint()\fR is used to add
358 the low-level interrupt routine.
364 xxattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
372 (void) ddi_intr_get_supported_types(dip, &types);
373 (void) ddi_intr_get_nintrs(dip< DDI_INTR_TYPE_FIXED, *nintrs);
374 (void) ddi_intr_alloc(dip, &xsp->int_hdl, DDI_INTR_TYPE_FIXED,
375 1, nintrs, *actual, 0);
377 /* initialize high-level mutex */
378 (void) ddi_intr_get_pri(xsp->int_hdl, &>high_pri);
379 mutex_init(&xsp->high_mutex, NULL, MUTEX_DRIVER,
380 DDI_INTR_PRI(xsp->high_pri));
382 /* Ensure that this is a hi-level interrupt */
383 if (ddi_intr_get_hilevel_pri(h) != DDI_SUCCESS) {
385 return (DDI_FAILURE); /* fail attach */
388 /* add high-level routine - xxhighintr() */
389 if (ddi_intr_add_handler(xsp->int_hdl, xxhighintr,
390 arg1, NULL) != DDI_SUCCESS) {
392 return (DDI_FAILURE); /* fail attach */
395 /* Enable high-level routine - xxhighintr() */
396 if (ddi_intr_enable(xsp->int_hdl) != DDI_SUCCESS) {
398 return (DDI_FAILURE); /* fail attach */
401 /* Enable soft interrupts */
402 xsp->low_soft_pri = DDI_INTR_SOFTPRI_MIN;
403 if (ddi_intr_add_softint(dip, &xsp>soft_hdl,
404 xsp->low_soft_pri, xxsoftint_handler, arg1) != DDI_SUCCESS) {
406 return (DDI_FAILURE); /* fail attach */
409 /* initialize low-level mutex */
410 mutex_init(&xsp->low_mutex, NULL, MUTEX_DRIVER,
411 DDI_INTR_PRI(xsp->low_soft_pri));
419 \fBExample 3 \fRHigh-level interrupt routine
422 The next code fragment represents the high-level interrupt routine. The
423 high-level interrupt routine minimally services the device and enqueues the
424 data for later processing by the soft interrupt routine. If the soft interrupt
425 routine is not already running, \fBddi_intr_trigger_softint()\fR is called to
426 start the routine. The soft interrupt routine will run until there is no more
433 xxhighintr(void *arg1, void *arg2)
435 struct xxstate *xsp = (struct xxstate *)arg1;
438 mutex_enter(&xsp->high_mutex);
440 * Verify this device generated the interrupt
441 * and disable the device interrupt.
442 * Enqueue data for xxsoftint_handler() processing.
445 /* is xxsoftint_handler() already running ? */
446 need_softint = (xsp->softint_running) ? 0 : 1;
447 mutex_exit(&xsp->high_mutex);
449 /* read-only access to xsp->id, no mutex needed */
450 if (xsp->soft_hdl && need_softint)
451 ddi_intr_trigger_softint(xsp->soft_hdl, arg2);
453 return (DDI_INTR_CLAIMED);
458 xxsoftint_handler(void *arg1, void *arg2)
460 struct xxstate *xsp = (struct xxstate *)arg1;
462 mutex_enter(&xsp->low_mutex);
463 mutex_enter(&xsp->high_mutex);
465 /* verify there is work to do */
466 if (work queue empty || xsp->softint_running ) {
467 mutex_exit(&xsp->high_mutex);
468 mutex_exit(&xsp->low_mutex);
469 return (DDI_INTR_UNCLAIMED);
472 xsp->softint_running = 1;
474 while ( data on queue ) {
475 ASSERT(mutex_owned(&xsp->high_mutex));
477 mutex_exit(&xsp->high_mutex);
479 /* Process data on queue */
480 mutex_enter(&xsp->high_mutex);
483 xsp->softint_running = 0;
484 mutex_exit(&xsp->high_mutex);
485 mutex_exit(&xsp->low_mutex);
486 return (DDI_INTR_CLAIMED);
494 See \fBattributes\fR(5) for descriptions of the following attributes:
502 ATTRIBUTE TYPE ATTRIBUTE VALUE
504 Interface Stability Evolving
510 \fBattributes\fR(5), \fBattach\fR(9E), \fBddi_intr_alloc\fR(9F),
511 \fBddi_intr_free\fR(9F), \fBddi_intr_get_hilevel_pri\fR(9F),
512 \fBmutex_init\fR(9F), \fBrw_init\fR(9F), \fBrwlock\fR(9F)
515 \fIWriting Device Drivers\fR
519 Consumers of these interfaces should verify that the return value is not equal
520 to \fBDDI_SUCCESS\fR. Incomplete checking for failure codes could result in
521 inconsistent behavior among platforms.
524 The \fBddi_intr_add_softint()\fR may not be used to add the same software
525 interrupt handler more than once. This is true even if a different value is
526 used for \fIarg1\fR in each of the calls to \fBddi_intr_add_softint()\fR.
527 Instead, the argument passed to the interrupt handler should indicate what
528 service(s) the interrupt handler should perform. For example, the argument
529 could be a pointer to the soft state structure of the device that could contain
530 a \fBwhich_service\fR field that the handler examines. The driver must set this
531 field to the appropriate value before calling \fBddi_intr_trigger_softint()\fR.
534 Every time a modifiable valid second argument, \fIarg2\fR, is provided when
535 \fBddi_intr_trigger_softint()\fR is invoked, the DDI framework saves \fIarg2\fR
536 internally and passes it to the interrupt handler \fIhandler\fR.
539 A call to \fBddi_intr_set_softint_pri()\fR could fail if a previously scheduled
540 soft interrupt trigger is still pending.