Nucleus
Barry ACPI DSDT + PCI 53a772a (3 years, 3 months ago)
diff --git a/kernel/acpi/acpi.c b/kernel/acpi/acpi.c
index 2774dbe..431d471 100644
--- a/kernel/acpi/acpi.c
+++ b/kernel/acpi/acpi.c
@@ -1,5 +1,6 @@
/*
- * This file controls the ACPI.
+ * This file controls ACPI. It finds the ACPI Root System Descriptor Table then
+ * searches it for more tables, which can be initialised separately.
*/
#include <stdint.h>
@@ -18,24 +19,42 @@ struct RSDPDesc {
} __attribute__((packed));
void init_apic(struct SDTHeader *);
+void init_fadt(struct SDTHeader *);
+void init_dsdt(struct SDTHeader *);
/* Table handlers */
struct TableHandler {
char *sig;
void (*handler)(struct SDTHeader *);
} handlers[] = {
- {"APIC", init_apic},
+ { "APIC", init_apic },
+ { "FACP", init_fadt },
+ { "DSDT", init_dsdt },
};
-/* Calculate the ACPI checksum */
-static uint32_t
-checksum(struct SDTHeader *header)
+/* Match a signature to a handler */
+void
+init_table(struct SDTHeader *table)
{
- char *byte = (void *) header;
uint32_t i, check = 0;
- for (i = 0; i < header->length; i++)
+ char *byte = (void *) table;
+
+ set_page((uintptr_t) table, PAGE_ADDR((uintptr_t) table) |
+ PTE_PRESENT | PTE_WRITE);
+ flush_tlb((uintptr_t) table);
+
+ /* Checksum */
+ for (i = 0; i < table->length; i++)
check += byte[i];
- return ((check % 0x100) == 0);
+ if (check % 0x100)
+ return;
+
+ /* Match handler */
+ for (i = 0; i < sizeof(handlers) / sizeof(handlers[0]); i++) {
+ if (memcmp(table->signature, handlers[i].sig, 4))
+ continue;
+ handlers[i].handler(table);
+ }
}
/* Initialise ACPI */
@@ -65,14 +84,6 @@ init_acpi(void *ebda)
set_page((uintptr_t) rsdt, PAGE_ADDR((uintptr_t) rsdt) |
PTE_PRESENT | PTE_WRITE);
flush_tlb((uintptr_t) rsdt);
- 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]);
- }
- }
+ for (i = 0; i < (rsdt->length - sizeof(struct SDTHeader)) / 4; i++)
+ init_table(table[i]);
}
diff --git a/kernel/acpi/acpi.h b/kernel/acpi/acpi.h
index 9821960..0c39b19 100644
--- a/kernel/acpi/acpi.h
+++ b/kernel/acpi/acpi.h
@@ -14,6 +14,7 @@ struct SDTHeader {
uint32_t creatorRevision;
};
+void init_table(struct SDTHeader *table);
void init_acpi(void *ebda);
#endif
diff --git a/kernel/acpi/apic.c b/kernel/acpi/apic.c
index 423d815..4d969f5 100644
--- a/kernel/acpi/apic.c
+++ b/kernel/acpi/apic.c
@@ -122,7 +122,7 @@ apic_start_timer(void)
c++;
}
-/* Initialise SMP (RSDT method) */
+/* Initialise SMP */
void
init_apic(struct SDTHeader *header)
{
diff --git a/kernel/acpi/dsdt.c b/kernel/acpi/dsdt.c
new file mode 100644
index 0000000..23b8178
--- /dev/null
+++ b/kernel/acpi/dsdt.c
@@ -0,0 +1,16 @@
+/*
+ * This file contains the Differentated System Descriptor Table initialisation
+ * code. The DSDT describes the peripherals attached to a machine, holding
+ * information on IO ports, IRQs, memory mappings and power management.
+ */
+
+#include <nucleus/panic.h>
+#include <io.h>
+#include "acpi.h"
+
+/* Parse the DSDT for information */
+void
+init_dsdt(struct SDTHeader *header)
+{
+ return;
+}
diff --git a/kernel/acpi/fadt.c b/kernel/acpi/fadt.c
new file mode 100644
index 0000000..92ce4c1
--- /dev/null
+++ b/kernel/acpi/fadt.c
@@ -0,0 +1,40 @@
+/*
+ * This file contains the code for handling the Fixed ACPI Description Table.
+ * The FADT describes the ACPI fixed register blocks related to power
+ * management. It should also contain a pointer to the Differentiated System
+ * Description Table.
+ */
+
+#include <io.h>
+#include "acpi.h"
+
+/* Preferred Power Management Profile */
+enum PMProfile {
+ PM_UNSPECIFIED,
+ PM_DESKTOP,
+ PM_MOBILE,
+ PM_WORKSTATION,
+ PM_ENTERPRISE_SERVER,
+ PM_SOHO_SERVER,
+ PM_APPLIANCE_PC,
+ PM_PERFORMANCE_SERVER,
+};
+
+/* Structure of the FADT */
+struct FADTable {
+ uint32_t firmwareCtrl;
+ uint32_t dsdt;
+ uint8_t reserved;
+ uint8_t prefPMProfile;
+ uint16_t sciInterrupt;
+ uint32_t smiCommandPort;
+ /* Bunch more boring stuff */
+};
+
+/* Parse FADT for information */
+void
+init_fadt(struct SDTHeader *header)
+{
+ struct FADTable *fadt = (struct FADTable *) (header + 1);
+ init_table((void *) fadt->dsdt);
+}