summaryrefslogtreecommitdiff
path: root/kernel/acpi.c
diff options
context:
space:
mode:
authorMichal Idziorek <m.i@gmx.at>2014-09-03 00:15:51 +0200
committerMichal Idziorek <m.i@gmx.at>2014-09-03 00:15:51 +0200
commitaad04a2208fbde8db2c1a81d6057c1ac4edb390e (patch)
tree87f3b47c5f85d6c7c5921e799571b42906d0eb0a /kernel/acpi.c
parent1a3a3a20773a5664c653a8aebcd10d288962285b (diff)
ACPI support !
Diffstat (limited to 'kernel/acpi.c')
-rw-r--r--kernel/acpi.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/kernel/acpi.c b/kernel/acpi.c
new file mode 100644
index 0000000..da16be8
--- /dev/null
+++ b/kernel/acpi.c
@@ -0,0 +1,166 @@
+// Advanced Configuration and Power Interface
+// http://wiki.xomb.org/index.php?title=ACPI_Tables
+
+#define FOOLOS_MODULE_NAME "acpi"
+
+#include "lib/logger/log.h"
+#include "lib/int/stdint.h"
+#include "lib/bool/bool.h"
+#include "smp.h"
+
+
+typedef struct acpi_rsdt_struct
+{
+ char sig[4];
+ uint32_t length;
+ uint8_t revision;
+ uint8_t checksum;
+ char oemid[6];
+ char oemtabid[8];
+ uint32_t oemrevision;
+ uint32_t vendor;
+ uint32_t rev;
+}acpi_rsdt;
+
+typedef struct aspi_rsdp_struct
+{
+ char sig[8]; //signature
+ uint8_t checksum;
+ char oem[6];
+ uint8_t revision;
+
+ uint32_t ptr_rsdt;
+ uint32_t length;
+
+ uint64_t ptr_xsdt; //same info but with 64bit pointers (preferred)
+ uint8_t checksum_ext;
+ uint8_t reserved[3];
+
+}acpi_rsdp;
+
+typedef struct
+{
+ char sig[4];
+ uint32_t length;
+ uint8_t rev;
+ uint8_t checksum;
+ char oemid[6];
+ char oemtableid[8];
+ char oemrev[4];
+ char creatorid[4];
+ char creatorrev[4];
+ uint32_t apic_local;
+ uint32_t flags;
+
+}acpi_madt;
+
+uint8_t *apci_get_next_entry(uint8_t *addr,smp_processors *procdata)
+{
+
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"Examining MADT Entry at 0x%08X",addr);
+
+ if(*addr==0)
+ {
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: LocalAPIC");
+ // usable
+ if(addr[4]&1)
+ {
+ if(procdata->processors>=SMP_MAX_PROC)
+ panic(FOOLOS_MODULE_NAME,"we do not support that many processors. recompile with higher SMP_MAX_PROC.");
+
+ procdata->local_apic_id[procdata->processors]=addr[3];
+ procdata->processors++;
+ }
+
+ }
+ else if(*addr==1)
+ {
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: IO APIC");
+ }
+ else if(*addr==2)log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: Interrupt Source Override");
+ else log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"MADT Entry: type:0x%X",*addr);
+
+ return addr+addr[1];
+}
+
+
+void acpi_check_madt(uint32_t *madt,smp_processors *procdata)
+{
+ acpi_madt *table=*madt;
+
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_DEBUG,"Looking for MADT Table at %08X.",table);
+ if(strcmp("APIC",table->sig,4))
+ {
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Found MADT Table at 0x%08X",table);
+ uint8_t *end=table;
+ end+=table->length;
+
+ uint8_t *entry=table;
+ entry+=sizeof(acpi_madt);
+
+ procdata->local_apic_address=table->apic_local;
+
+ while(entry<end)
+ {
+ entry=apci_get_next_entry(entry,procdata);
+ }
+
+
+ }
+}
+
+void acpi_read_rsdt(acpi_rsdt *rsdt,smp_processors *procdata)
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Reading RSDT Table at 0x%08X",rsdt);
+
+ if(!strcmp("RSDT",rsdt->sig,4))
+ panic(FOOLOS_MODULE_NAME,"Signature MISMATCH!");
+
+ int entries=(rsdt->length-sizeof(acpi_rsdt))/4;
+ uint32_t *first=rsdt;
+ first+=sizeof(acpi_rsdt)/4;
+
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Entries: %d",entries);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Looking for MADT Table");
+ for(int i=0;i<entries;i++)
+ {
+
+ acpi_check_madt(first,procdata);
+ first++;
+ }
+
+}
+
+// search for the RSDB table in
+// 0x7ffff - 0x9ffff (max)
+// 0xe0000 - 0xfffff
+
+bool acpi_find(smp_processors *procdata)
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Looking for RSDP Table");
+ char *search=0x7ffff; //will be 16 bit aligned;
+
+ while(search<=0xfffff)
+ {
+ if(strcmp("RSD PTR ",search,8)) // notice trailing space in "RSD PTR "
+ {
+ uint8_t checksum=0;
+ for(int i=0;i<20;i++)
+ checksum+=search[i];
+
+ if(checksum==0)
+ {
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"RSDP Table found at 0x%08X",search);
+ acpi_rsdp *rsdp=search;
+ acpi_read_rsdt(rsdp->ptr_rsdt,procdata);
+ return true;
+ }
+ }
+
+ search++;
+
+ if(search==0xa0000)search=0xe0000;
+
+ }
+ return false;
+}