summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpi/uacpi.c109
-rw-r--r--sys/include/dev/acpi/tables.h37
2 files changed, 139 insertions, 7 deletions
diff --git a/sys/dev/acpi/uacpi.c b/sys/dev/acpi/uacpi.c
index b133288..ffec436 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>
@@ -58,17 +60,88 @@ typedef struct {
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 +351,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
@@ -575,5 +667,8 @@ uacpi_init(void)
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/include/dev/acpi/tables.h b/sys/include/dev/acpi/tables.h
index 5340c7f..d31cbe0 100644
--- a/sys/include/dev/acpi/tables.h
+++ b/sys/include/dev/acpi/tables.h
@@ -118,6 +118,43 @@ struct __packed acpi_gas {
uint64_t address;
};
+/*
+ * ACPI Address Space ID definitions for GAS
+ *
+ * See section 5.2.3.2 of the ACPI software programming
+ * manual.
+ *
+ * XXX: 0x0B->0x7E is reserved as well as 0x80->0xBF
+ * and 0xC0->0xFF is OEM defined. Values other than
+ * the ones specified below are either garbage or
+ * OEM specific values.
+ */
+#define ACPI_GAS_SYSMEM 0x00 /* System memory space */
+#define ACPI_GAS_SYSIO 0x01 /* System I/O space */
+#define ACPI_GAS_PCICONF 0x02 /* PCI configuration space */
+#define ACPI_GAS_EC 0x03 /* Embedded controller */
+#define ACPI_GAS_SMBUS 0x04 /* System management bus */
+#define ACPI_GAS_CMOS 0x05 /* System CMOS */
+#define ACPI_GAS_PCIBAR 0x06 /* PCI BAR target */
+#define ACPI_GAS_IPMI 0x07 /* IPMI (sensor monitoring) */
+#define ACPI_GAS_GPIO 0x08 /* General Purpose I/O */
+#define ACPI_GAS_GSBUS 0x09 /* GenericSerialBus */
+#define ACPI_GAS_PLATCOM 0x0A /* Platform Communications Channel */
+
+/*
+ * ACPI address size definitions for GAS
+ *
+ * See section 5.2.3.2 of the ACPI software programming
+ * manual.
+ *
+ * This is really retarded Intel and Microsoft, thank you.
+ */
+#define ACPI_GAS_UNDEF 0 /* Undefined (legacy reasons) */
+#define ACPI_GAS_BYTE 1 /* Byte access */
+#define ACPI_GAS_WORD 2 /* Word access */
+#define ACPI_GAS_DWORD 3 /* Dword access */
+#define ACPI_GAS_QWORD 4 /* Qword access */
+
struct __packed acpi_hpet {
struct acpi_header hdr;
uint8_t hardware_rev_id;