Nucleus
Barry ACPI + APIC 232d0f9 (3 years, 3 months ago)
diff --git a/kernel/acpi/acpi.c b/kernel/acpi/acpi.c
new file mode 100644
index 0000000..c30fde8
--- /dev/null
+++ b/kernel/acpi/acpi.c
@@ -0,0 +1,74 @@
+/*
+ * This file controls the ACPI
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <nucleus/panic.h>
+#include "acpi.h"
+
+/* Root System Descriptor Pointer */
+struct RSDPDesc {
+ char signature[8];
+ uint8_t checksum;
+ char oem[6];
+ uint8_t revision;
+ uint32_t rsdt;
+} __attribute__((packed));
+
+void init_apic(struct SDTHeader *);
+
+/* Table handlers */
+struct TableHandler {
+ char *sig;
+ void (*handler)(struct SDTHeader *);
+} handlers[] = {
+ {"APIC", init_apic},
+};
+
+/* Calculate the ACPI checksum */
+static uint32_t
+checksum(struct SDTHeader *header)
+{
+ char *byte = (void *) header;
+ uint32_t i, check = 0;
+ for (i = 0; i < header->length; i++)
+ check += byte[i];
+ return ((check % 0x100) == 0);
+}
+
+/* Initialise ACPI */
+void
+init_acpi(void *ebda)
+{
+ /* Search for Root System Descriptor Table */
+ char *sig;
+ for (sig = ebda; sig < (char *) 0x100000; sig++) {
+ if (!memcmp(sig, "RSD PTR ", 8))
+ break;
+ }
+ if (sig == (char *) 0x100000)
+ return;
+
+ /* RSDT checksum */
+ uint32_t i, check = 0;
+ for (i = 0; i < sizeof(struct RSDPDesc); i++)
+ check += sig[i];
+ if (check % 0x100)
+ return;
+
+ /* Iterate tables */
+ uint32_t j;
+ struct SDTHeader *rsdt = (void *) ((struct RSDPDesc *) sig)->rsdt;
+ struct SDTHeader **table = (void *) (rsdt + 1);
+ for (i = 0; i < (rsdt->length - sizeof(struct SDTHeader)) / 4; i++) {
+ if (!checksum(table[i]))
+ continue;
+ /* Try to match to a handler */
+ for (j = 0; j < sizeof(handlers)/sizeof(handlers[0]); j++) {
+ if (memcmp(table[i]->signature, handlers[j].sig, 4))
+ continue;
+ handlers[j].handler(table[i]);
+ }
+ }
+}