#include "kernel.h" #include "log.h" #include "acpi.h" #include #include "lib/string/string.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; static uint8_t *apci_get_next_entry(uint8_t *addr,acpi_information *procdata) { //klog("Examining MADT Entry at 0x%08X",addr); if(*addr==0) { klog("Type 0: LocalAPIC (enabled=%d) (id=0x%08X)",addr[4]&1,addr[3]); // usable if(addr[4]&1) { if(procdata->processors>=SMP_MAX_PROC){ kpanic("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) { klog("Type 1: IO APIC (id=%d) (addr=0x%08X) (base=%d)",addr[2], *((uint32_t*)&addr[4]),*((uint32_t*)&addr[8])); procdata->io_apic_address=*((uint32_t*)&addr[4]); fixme("support multiple IO Apics and consider interrupt source overrides during irq config!"); } else if(*addr==2){ uint16_t flags=*((uint16_t*)&addr[8]); klog("Type 2: Interrupt Source Override (bus src=%d) (irq src=%d) (global=%d) (flags=%d)",addr[2],addr[3],*((uint32_t*)&addr[4]),flags); klog(" Active %s, %s triggered", flags&2?"low":"high", flags&8?"level":"edge"); } else if(*addr==4){ klog("Type 4: Non-maskable interrupts (proc id=%d) (flags=%d) (LINT#=%d)",addr[2],*((uint16_t*)&addr[3]),addr[5]); } else if(*addr==5){kpanic("Entry Type 5 : Local APIC Address Override. 64-bit address??");} else kpanic("MADT Entry: type:0x%X",*addr); return addr+addr[1]; } static void acpi_check_madt(uint32_t *madt,acpi_information *procdata) { acpi_madt *table=(acpi_madt *)*madt; // klog("Looking for MADT Table at %08X.",table); if(!strcmp_l("APIC",table->sig,4)) { klog("Found MADT Table at 0x%08X",table); uint8_t *end=(uint8_t *)table; end+=table->length; uint8_t *entry=(uint8_t *)table; entry+=sizeof(acpi_madt); procdata->local_apic_address=table->apic_local; klog("Local Apic Address: 0x%08X",table->apic_local); procdata->flags=table->flags; klog("Flags (Dual 8259): %d",table->flags); while(entrysig,4)) kpanic("Signature MISMATCH!"); int entries=(rsdt->length-sizeof(acpi_rsdt))/4; uint32_t *first=(uint32_t *)rsdt; first+=sizeof(acpi_rsdt)/4; klog("Entries: %d",entries); klog("Looking for MADT Table"); for(int i=0;iprocessors=0; procdata->boot=0; while(search<=(char *)0xfffff) { if(!strcmp_l("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) { klog("RSD Pointer found at 0x%08X",search); acpi_rsdp *rsdp=(acpi_rsdp *)search; acpi_read_rsdt(rsdp->ptr_rsdt,procdata); return true; } } search++; if((uint32_t)search==0xa0000)search=0xe0000; } return false; }