OsdSchedule.c revision 67760
1220496Smarkm/*-
21802Sphk * Copyright (c) 2000 Michael Smith
3220496Smarkm * Copyright (c) 2000 BSDi
4220496Smarkm * All rights reserved.
5220496Smarkm *
6220496Smarkm * Redistribution and use in source and binary forms, with or without
7220496Smarkm * modification, are permitted provided that the following conditions
8220496Smarkm * are met:
9220496Smarkm * 1. Redistributions of source code must retain the above copyright
10220496Smarkm *    notice, this list of conditions and the following disclaimer.
11220496Smarkm * 2. Redistributions in binary form must reproduce the above copyright
12220496Smarkm *    notice, this list of conditions and the following disclaimer in the
13220496Smarkm *    documentation and/or other materials provided with the distribution.
1484211Sdillon *
1584211Sdillon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1684211Sdillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17220496Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181802Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19220496Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20220496Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21220496Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221802Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23220496Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24220496Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251802Sphk * SUCH DAMAGE.
2628688Sjoerg *
271802Sphk *	$FreeBSD: head/sys/dev/acpica/Osd/OsdSchedule.c 67760 2000-10-28 06:56:15Z msmith $
281802Sphk */
291802Sphk
301802Sphk/*
311802Sphk * 6.3 : Scheduling services
321802Sphk */
331802Sphk
341802Sphk#include "acpi.h"
351802Sphk
361802Sphk#include <sys/kernel.h>
371802Sphk#include <sys/malloc.h>
381802Sphk#include <sys/taskqueue.h>
391802Sphk#include <machine/clock.h>
401802Sphk
411802Sphk/*
42220496Smarkm * This is a little complicated due to the fact that we need to build and then
43220496Smarkm * free a 'struct task' for each task we enqueue.
44220496Smarkm *
451802Sphk * We use the default taskqueue_swi queue, since it really doesn't matter what
46220496Smarkm * else we're queued along with.
471802Sphk */
48220496Smarkm
49220496SmarkmMALLOC_DEFINE(M_ACPITASK, "acpitask", "ACPI deferred task");
501802Sphk
511802Sphkstatic void	AcpiOsExecuteQueue(void *arg, int pending);
52220496Smarkm
53220496Smarkmstruct acpi_task {
54220496Smarkm    struct task			at_task;
551802Sphk    OSD_EXECUTION_CALLBACK	at_function;
56220496Smarkm    void			*at_context;
571802Sphk};
58220496Smarkm
59220496SmarkmACPI_STATUS
60220496SmarkmAcpiOsQueueForExecution(UINT32 Priority, OSD_EXECUTION_CALLBACK Function, void *Context)
61220496Smarkm{
62220496Smarkm    struct acpi_task	*at;
63220496Smarkm
64220496Smarkm    if (Function == NULL)
65220496Smarkm	return(AE_BAD_PARAMETER);
66220496Smarkm
67220496Smarkm    /* XXX is it OK to block here? */
68220496Smarkm    at = malloc(sizeof(*at), M_ACPITASK, M_WAITOK);
691802Sphk    bzero(at, sizeof(*at));
70
71    at->at_function = Function;
72    at->at_context = Context;
73    at->at_task.ta_func = AcpiOsExecuteQueue;
74    at->at_task.ta_context = at;
75    switch (Priority) {
76    case OSD_PRIORITY_HIGH:
77	at->at_task.ta_priority = 3;
78	break;
79    case OSD_PRIORITY_MED:
80	at->at_task.ta_priority = 2;
81	break;
82    case OSD_PRIORITY_LO:
83	at->at_task.ta_priority = 1;
84	break;
85    default:
86	free(at, M_ACPITASK);
87	return(AE_BAD_PARAMETER);
88    }
89
90    taskqueue_enqueue(taskqueue_swi, (struct task *)at);
91    return(AE_OK);
92}
93
94static void
95AcpiOsExecuteQueue(void *arg, int pending)
96{
97    struct acpi_task		*at = (struct acpi_task *)arg;
98    OSD_EXECUTION_CALLBACK	Function;
99    void			*Context;
100
101    Function = (OSD_EXECUTION_CALLBACK)at->at_function;
102    Context = at->at_context;
103
104    free(at, M_ACPITASK);
105
106    Function(Context);
107}
108
109/*
110 * We don't have any sleep granularity better than hz, so
111 * make do with that.
112 */
113void
114AcpiOsSleep (UINT32 Seconds, UINT32 Milliseconds)
115{
116    int		timo;
117
118    timo = (Seconds * hz) + Milliseconds / (1000 * hz);
119    if (timo == 0)
120	timo = 1;
121    tsleep(NULL, 0, "acpislp", timo);
122}
123
124void
125AcpiOsSleepUsec (UINT32 Microseconds)
126{
127    if (Microseconds > 1000) {	/* long enough to be worth the overhead of sleeping */
128	AcpiOsSleep(0, Microseconds / 1000);
129    } else {
130	DELAY(Microseconds);
131    }
132}
133