diff options
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r-- | sys/dev/acpi/uacpi.c | 137 | ||||
-rw-r--r-- | sys/dev/acpi/uacpi/event.c | 1 | ||||
-rw-r--r-- | sys/dev/acpi/uacpi/resources.c | 1 | ||||
-rw-r--r-- | sys/dev/acpi/uacpi/tables.c | 1 | ||||
-rw-r--r-- | sys/dev/acpi/uacpi/utilities.c | 1 |
5 files changed, 122 insertions, 19 deletions
diff --git a/sys/dev/acpi/uacpi.c b/sys/dev/acpi/uacpi.c index 03d0ecf..6c2bf50 100644 --- a/sys/dev/acpi/uacpi.c +++ b/sys/dev/acpi/uacpi.c @@ -32,6 +32,8 @@ #include <sys/param.h> #include <sys/syslog.h> #include <sys/panic.h> +#include <sys/proc.h> +#include <sys/queue.h> #include <dev/timer.h> #include <uacpi/kernel_api.h> #include <uacpi/platform/arch_helpers.h> @@ -41,10 +43,10 @@ #include <machine/cdefs.h> #include <machine/pio.h> #include <machine/cpu.h> +#include <machine/intr.h> #if defined(__x86_64__) #include <machine/idt.h> #include <machine/ioapic.h> -#include <machine/intr.h> #endif /* __x86_64__ */ #include <dev/acpi/uacpi.h> #include <dev/acpi/acpi.h> @@ -53,22 +55,96 @@ #include <vm/vm.h> #include <string.h> +#define pr_trace(fmt, ...) kprintf("acpi: " fmt, ##__VA_ARGS__) +#define pr_error(...) pr_trace(__VA_ARGS__) + typedef struct { uacpi_io_addr base; uacpi_size length; } io_range_t; +struct uacpi_work { + uacpi_work_handler hand; + uacpi_handle ctx; + TAILQ_ENTRY(uacpi_work) link; +}; + +uacpi_status +uacpi_kernel_schedule_work(uacpi_work_type type, uacpi_work_handler h, uacpi_handle ctx); + +extern struct proc g_proc0; + +static struct proc *event_td; +static TAILQ_HEAD(, uacpi_work) acpi_gpe_eventq; +static TAILQ_HEAD(, uacpi_work) acpi_notify_eventq; + /* - * TODO: Schedule a system shutdown + * Dispatch ACPI general purpose events from + * hardware. */ -static uacpi_interrupt_ret -power_button_handler(uacpi_handle ctx) +static void +uacpi_gpe_dispatch(void) +{ + struct uacpi_work *work; + + work = TAILQ_FIRST(&acpi_gpe_eventq); + if (work == NULL) { + return; + } + + work->hand(work->ctx); + TAILQ_REMOVE(&acpi_gpe_eventq, work, link); + dynfree(work); +} + +/* + * Dispatch ACPI general notify events. + */ +static void +uacpi_notify_dispatch(void) +{ + struct uacpi_work *work; + + work = TAILQ_FIRST(&acpi_notify_eventq); + if (work == NULL) { + return; + } + + work->hand(work->ctx); + TAILQ_REMOVE(&acpi_gpe_eventq, work, link); + dynfree(work); +} + +static void +uacpi_event_td(void) +{ + for (;;) { + uacpi_gpe_dispatch(); + uacpi_notify_dispatch(); + sched_yield(); + } +} + +static void +shutdown(uacpi_handle ctx) { - md_intoff(); kprintf("power button pressed\n"); kprintf("halting machine...\n"); cpu_halt_all(); - return UACPI_INTERRUPT_HANDLED; +} + +static uacpi_interrupt_ret +power_button_handler(uacpi_handle ctx) +{ + md_intoff(); + uacpi_kernel_schedule_work(UACPI_WORK_GPE_EXECUTION, shutdown, NULL); + md_inton(); + + for (;;) { + md_hlt(); + } + + __builtin_unreachable(); } void * @@ -278,9 +354,28 @@ uacpi_kernel_uninstall_interrupt_handler([[maybe_unused]] uacpi_interrupt_handle } uacpi_status -uacpi_kernel_schedule_work(uacpi_work_type, uacpi_work_handler, uacpi_handle ctx) +uacpi_kernel_schedule_work(uacpi_work_type type, uacpi_work_handler h, uacpi_handle ctx) { - return UACPI_STATUS_UNIMPLEMENTED; + struct uacpi_work *work; + + work = dynalloc(sizeof(*work)); + if (work == NULL) { + return UACPI_STATUS_OUT_OF_MEMORY; + } + + work->hand = h; + work->ctx = ctx; + + switch (type) { + case UACPI_WORK_GPE_EXECUTION: + TAILQ_INSERT_TAIL(&acpi_gpe_eventq, work, link); + break; + case UACPI_WORK_NOTIFICATION: + TAILQ_INSERT_TAIL(&acpi_notify_eventq, work, link); + break; + } + + return 0; } uacpi_status @@ -513,9 +608,18 @@ uacpi_u64 uacpi_kernel_get_nanoseconds_since_boot(void) { static uacpi_u64 time = 0; + static struct timer tmr = {0}; + tmrr_status_t tmr_error; + + if (time == 0) { + tmr_error = req_timer(TIMER_GP, &tmr); + if (tmr_error != TMRR_SUCCESS) { + time += 1000000; + return time; + } + } - /* TODO */ - time += 1000000; + time = tmr.get_time_nsec(); return time; } @@ -532,25 +636,25 @@ uacpi_init(void) ret = uacpi_initialize(0); if (uacpi_unlikely_error(ret)) { - kprintf("uacpi init error: %s\n", uacpi_status_to_string(ret)); + pr_error("uacpi init error: %s\n", uacpi_status_to_string(ret)); return -1; } ret = uacpi_namespace_load(); if (uacpi_unlikely_error(ret)) { - kprintf("uacpi namespace load error: %s\n", uacpi_status_to_string(ret)); + pr_error("uacpi namespace load error: %s\n", uacpi_status_to_string(ret)); return -1; } ret = uacpi_namespace_initialize(); if (uacpi_unlikely_error(ret)) { - kprintf("uacpi namespace init error: %s\n", uacpi_status_to_string(ret)); + pr_error("uacpi namespace init error: %s\n", uacpi_status_to_string(ret)); return -1; } ret = uacpi_finalize_gpe_initialization(); if (uacpi_unlikely_error(ret)) { - kprintf("uacpi GPE init error: %s\n", uacpi_status_to_string(ret)); + pr_error("uacpi GPE init error: %s\n", uacpi_status_to_string(ret)); return -1; } @@ -560,11 +664,14 @@ uacpi_init(void) ); if (uacpi_unlikely_error(ret)) { - kprintf("failed to install power button event: %s\n", + pr_error("failed to install power button event: %s\n", uacpi_status_to_string(ret) ); return -1; } + TAILQ_INIT(&acpi_gpe_eventq); + TAILQ_INIT(&acpi_notify_eventq); + spawn(&g_proc0, uacpi_event_td, NULL, 0, &event_td); return 0; } diff --git a/sys/dev/acpi/uacpi/event.c b/sys/dev/acpi/uacpi/event.c index 0c58372..62412ac 100644 --- a/sys/dev/acpi/uacpi/event.c +++ b/sys/dev/acpi/uacpi/event.c @@ -1054,7 +1054,6 @@ static uacpi_status create_gpe_block( */ reg->base_idx = base_idx + (i * EVENTS_PER_GPE_REGISTER); - tmp_gas.address = address + i; ret = uacpi_map_gas_noalloc(&tmp_gas, ®->status); if (uacpi_unlikely_error(ret)) diff --git a/sys/dev/acpi/uacpi/resources.c b/sys/dev/acpi/uacpi/resources.c index a9bcb82..f1a25ec 100644 --- a/sys/dev/acpi/uacpi/resources.c +++ b/sys/dev/acpi/uacpi/resources.c @@ -602,7 +602,6 @@ static uacpi_size aml_size_for_serial_connection( #define ARG1(value) .f2.arg1 = (value) #define ARG2(value) .f3.arg2 = (value) - static const struct uacpi_resource_convert_instruction convert_irq_to_native[] = { OP(PACKED_ARRAY_16, AML_F(irq, irq_mask), NATIVE_F(irq, irqs), ARG2(NATIVE_O(irq, num_irqs))), diff --git a/sys/dev/acpi/uacpi/tables.c b/sys/dev/acpi/uacpi/tables.c index df7d7b9..3314fd1 100644 --- a/sys/dev/acpi/uacpi/tables.c +++ b/sys/dev/acpi/uacpi/tables.c @@ -1211,7 +1211,6 @@ static void gas_init_system_io( gas->access_size = 0; } - struct register_description { uacpi_size offset, xoffset; uacpi_size length_offset; diff --git a/sys/dev/acpi/uacpi/utilities.c b/sys/dev/acpi/uacpi/utilities.c index c7ca20a..059c574 100644 --- a/sys/dev/acpi/uacpi/utilities.c +++ b/sys/dev/acpi/uacpi/utilities.c @@ -963,7 +963,6 @@ static uacpi_iteration_decision find_one_device( return ctx->cb(ctx->user, node, depth); } - uacpi_status uacpi_find_devices_at( uacpi_namespace_node *parent, const uacpi_char *const *hids, uacpi_iteration_callback cb, void *user |