summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/os/sunddi.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/os/sunddi.c')
-rw-r--r--usr/src/uts/common/os/sunddi.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/usr/src/uts/common/os/sunddi.c b/usr/src/uts/common/os/sunddi.c
index 662f69986f..e919e8b846 100644
--- a/usr/src/uts/common/os/sunddi.c
+++ b/usr/src/uts/common/os/sunddi.c
@@ -60,6 +60,7 @@
#include <sys/conf.h>
#include <sys/ddi_impldefs.h> /* include implementation structure defs */
#include <sys/ndi_impldefs.h> /* include prototypes */
+#include <sys/ddi_timer.h>
#include <sys/hwconf.h>
#include <sys/pathname.h>
#include <sys/modctl.h>
@@ -5302,6 +5303,125 @@ ddi_run_callback(uintptr_t *listid)
softcall(real_callback_run, listid);
}
+/*
+ * ddi_periodic_t
+ * ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval,
+ * int level)
+ *
+ * INTERFACE LEVEL
+ * Solaris DDI specific (Solaris DDI)
+ *
+ * PARAMETERS
+ * func: the callback function
+ *
+ * The callback function will be invoked. The function is invoked
+ * in kernel context if the argument level passed is the zero.
+ * Otherwise it's invoked in interrupt context at the specified
+ * level.
+ *
+ * arg: the argument passed to the callback function
+ *
+ * interval: interval time
+ *
+ * level : callback interrupt level
+ *
+ * If the value is the zero, the callback function is invoked
+ * in kernel context. If the value is more than the zero, but
+ * less than or equal to ten, the callback function is invoked in
+ * interrupt context at the specified interrupt level, which may
+ * be used for real time applications.
+ *
+ * This value must be in range of 0-10, which can be a numeric
+ * number or a pre-defined macro (DDI_IPL_0, ... , DDI_IPL_10).
+ *
+ * DESCRIPTION
+ * ddi_periodic_add(9F) schedules the specified function to be
+ * periodically invoked in the interval time.
+ *
+ * As well as timeout(9F), the exact time interval over which the function
+ * takes effect cannot be guaranteed, but the value given is a close
+ * approximation.
+ *
+ * Drivers waiting on behalf of processes with real-time constraints must
+ * pass non-zero value with the level argument to ddi_periodic_add(9F).
+ *
+ * RETURN VALUES
+ * ddi_periodic_add(9F) returns a non-zero opaque value (ddi_periodic_t),
+ * which must be used for ddi_periodic_delete(9F) to specify the request.
+ *
+ * CONTEXT
+ * ddi_periodic_add(9F) can be called in user or kernel context, but
+ * it cannot be called in interrupt context, which is different from
+ * timeout(9F).
+ */
+ddi_periodic_t
+ddi_periodic_add(void (*func)(void *), void *arg, hrtime_t interval, int level)
+{
+ /*
+ * Sanity check of the argument level.
+ */
+ if (level < DDI_IPL_0 || level > DDI_IPL_10)
+ cmn_err(CE_PANIC,
+ "ddi_periodic_add: invalid interrupt level (%d).", level);
+
+ /*
+ * Sanity check of the context. ddi_periodic_add() cannot be
+ * called in either interrupt context or high interrupt context.
+ */
+ if (servicing_interrupt())
+ cmn_err(CE_PANIC,
+ "ddi_periodic_add: called in (high) interrupt context.");
+
+ return ((ddi_periodic_t)i_timeout(func, arg, interval, level));
+}
+
+/*
+ * void
+ * ddi_periodic_delete(ddi_periodic_t req)
+ *
+ * INTERFACE LEVEL
+ * Solaris DDI specific (Solaris DDI)
+ *
+ * PARAMETERS
+ * req: ddi_periodic_t opaque value ddi_periodic_add(9F) returned
+ * previously.
+ *
+ * DESCRIPTION
+ * ddi_periodic_delete(9F) cancels the ddi_periodic_add(9F) request
+ * previously requested.
+ *
+ * ddi_periodic_delete(9F) will not return until the pending request
+ * is canceled or executed.
+ *
+ * As well as untimeout(9F), calling ddi_periodic_delete(9F) for a
+ * timeout which is either running on another CPU, or has already
+ * completed causes no problems. However, unlike untimeout(9F), there is
+ * no restrictions on the lock which might be held across the call to
+ * ddi_periodic_delete(9F).
+ *
+ * Drivers should be structured with the understanding that the arrival of
+ * both an interrupt and a timeout for that interrupt can occasionally
+ * occur, in either order.
+ *
+ * CONTEXT
+ * ddi_periodic_delete(9F) can be called in user or kernel context, but
+ * it cannot be called in interrupt context, which is different from
+ * untimeout(9F).
+ */
+void
+ddi_periodic_delete(ddi_periodic_t req)
+{
+ /*
+ * Sanity check of the context. ddi_periodic_delete() cannot be
+ * called in either interrupt context or high interrupt context.
+ */
+ if (servicing_interrupt())
+ cmn_err(CE_PANIC,
+ "ddi_periodic_delete: called in (high) interrupt context.");
+
+ i_untimeout((timeout_t)req);
+}
+
dev_info_t *
nodevinfo(dev_t dev, int otyp)
{