summaryrefslogtreecommitdiff
path: root/sys/dev/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r--sys/dev/acpi/uacpi.c137
-rw-r--r--sys/dev/acpi/uacpi/event.c1
-rw-r--r--sys/dev/acpi/uacpi/resources.c1
-rw-r--r--sys/dev/acpi/uacpi/tables.c1
-rw-r--r--sys/dev/acpi/uacpi/utilities.c1
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, &reg->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