#include "opt_acpi.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/malloc.h>
#include <sys/msgport.h>
#include <sys/taskqueue.h>
#include <machine/clock.h>
#include <sys/msgport2.h>
#include "acpi.h"
#include "accommon.h"
#include <dev/acpica/acpivar.h>
#define _COMPONENT ACPI_OS_SERVICES
ACPI_MODULE_NAME("SCHEDULE")
MALLOC_DEFINE(M_ACPITASK, "acpitask", "ACPI deferred task");
static void acpi_task_thread(void *arg);
static void acpi_autofree_reply(lwkt_port_t port, lwkt_msg_t msg);
struct acpi_task {
struct lwkt_msg at_msg;
ACPI_OSD_EXEC_CALLBACK at_function;
void *at_context;
ACPI_EXECUTE_TYPE at_type;
};
static struct thread *acpi_task_td;
struct lwkt_port acpi_afree_rport;
int
acpi_task_thread_init(void)
{
lwkt_initport_replyonly(&acpi_afree_rport, acpi_autofree_reply);
acpi_task_td = kmalloc(sizeof(struct thread), M_DEVBUF, M_INTWAIT | M_ZERO);
lwkt_create(acpi_task_thread, NULL, NULL, acpi_task_td, TDF_NOSTART, 0,
"acpi_task");
return (0);
}
void
acpi_task_thread_schedule(void)
{
lwkt_schedule(acpi_task_td);
}
static void
acpi_task_thread(void *arg)
{
ACPI_OSD_EXEC_CALLBACK func;
struct acpi_task *at;
lwkt_gettoken(&acpi_token);
for (;;) {
at = (void *)lwkt_waitport(&curthread->td_msgport, 0);
func = at->at_function;
func(at->at_context);
lwkt_replymsg(&at->at_msg, 0);
}
lwkt_reltoken(&acpi_token);
}
ACPI_STATUS
AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
void *Context)
{
struct acpi_task *at;
switch (Type) {
case OSL_GLOBAL_LOCK_HANDLER:
case OSL_NOTIFY_HANDLER:
case OSL_GPE_HANDLER:
case OSL_DEBUGGER_EXEC_THREAD:
case OSL_EC_POLL_HANDLER:
case OSL_EC_BURST_HANDLER:
break;
default:
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
at = kmalloc(sizeof(*at), M_ACPITASK, M_INTWAIT | M_ZERO);
lwkt_initmsg(&at->at_msg, &acpi_afree_rport, 0);
at->at_function = Function;
at->at_context = Context;
at->at_type = Type;
lwkt_sendmsg(&acpi_task_td->td_msgport, &at->at_msg);
return_ACPI_STATUS (AE_OK);
}
static void
acpi_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
{
kfree(msg, M_ACPITASK);
}
UINT64
AcpiOsGetTimer (void)
{
struct timeval time;
microtime(&time);
return (((UINT64) time.tv_sec * 10000000) + ((UINT64) time.tv_usec * 10));
}
void
AcpiOsSleep(UINT64 Milliseconds)
{
int timo;
static int dummy;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
timo = Milliseconds * hz / 1000;
if (clocks_running == 0) {
while (timo > 1000000) {
DELAY(1000000);
timo -= 1000000;
}
if (timo)
DELAY(timo * 1000);
} else if (timo > 0) {
tsleep(&dummy, 0, "acpislp", timo);
} else {
DELAY(Milliseconds * 1000);
}
return_VOID;
}
void
AcpiOsStall(UINT32 Microseconds)
{
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
DELAY(Microseconds);
return_VOID;
}
ACPI_THREAD_ID
AcpiOsGetThreadId(void)
{
return ((uintptr_t)curthread);
}