BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / 232d0f9e7dd31316a9b91cbdfec0174afce40c7e / kernel / acpi / acpi.c

// Related

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]);
+		}
+	}
+}