/*- * Copyright (c) 2000 Michael Smith * Copyright (c) 2000 BSDi * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * 6.3 : Scheduling services */ #include "acpi.h" #include #include #include #include /* * This is a little complicated due to the fact that we need to build and then * free a 'struct task' for each task we enqueue. * * We use the default taskqueue_swi queue, since it really doesn't matter what * else we're queued along with. */ MALLOC_DEFINE(M_ACPITASK, "acpitask", "ACPI deferred task"); static void AcpiOsExecuteQueue(void *arg, int pending); struct acpi_task { struct task at_task; OSD_EXECUTION_CALLBACK at_function; void *at_context; }; ACPI_STATUS AcpiOsQueueForExecution(UINT32 Priority, OSD_EXECUTION_CALLBACK Function, void *Context) { struct acpi_task *at; if (Function == NULL) return(AE_BAD_PARAMETER); /* XXX is it OK to block here? */ at = malloc(sizeof(*at), M_ACPITASK, M_WAITOK); bzero(at, sizeof(*at)); at->at_function = Function; at->at_context = Context; at->at_task.ta_func = AcpiOsExecuteQueue; at->at_task.ta_context = at; switch (Priority) { case OSD_PRIORITY_HIGH: at->at_task.ta_priority = 3; break; case OSD_PRIORITY_MED: at->at_task.ta_priority = 2; break; case OSD_PRIORITY_LO: at->at_task.ta_priority = 1; break; default: free(at, M_ACPITASK); return(AE_BAD_PARAMETER); } taskqueue_enqueue(taskqueue_swi, (struct task *)at); return(AE_OK); } static void AcpiOsExecuteQueue(void *arg, int pending) { struct acpi_task *at = (struct acpi_task *)arg; OSD_EXECUTION_CALLBACK Function; void *Context; Function = (OSD_EXECUTION_CALLBACK)at->at_function; Context = at->at_context; free(at, M_ACPITASK); Function(Context); } /* * We don't have any sleep granularity better than hz, so * make do with that. */ void AcpiOsSleep (UINT32 Seconds, UINT32 Milliseconds) { int timo; timo = (Seconds * hz) + Milliseconds / (1000 * hz); if (timo == 0) timo = 1; tsleep(NULL, 0, "acpislp", timo); } void AcpiOsSleepUsec (UINT32 Microseconds) { if (Microseconds > 1000) { /* long enough to be worth the overhead of sleeping */ AcpiOsSleep(0, Microseconds / 1000); } else { DELAY(Microseconds); } }