1 /* 2 * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved. 3 * Copyright 2007, Michael Lotz, mmlr@mlotz.ch 4 * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. 5 * Distributed under the terms of the MIT License. 6 * 7 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 8 * Distributed under the terms of the NewOS License. 9 */ 10 11 12 #include "acpi.h" 13 #include "mmu.h" 14 15 #include <string.h> 16 17 #include <KernelExport.h> 18 19 #include <arch/x86/arch_acpi.h> 20 21 22 //#define TRACE_ACPI 23 #ifdef TRACE_ACPI 24 # define TRACE(x) dprintf x 25 #else 26 # define TRACE(x) ; 27 #endif 28 29 static struct scan_spots_struct acpi_scan_spots[] = { 30 { 0x0, 0x400, 0x400 - 0x0 }, 31 { 0xe0000, 0x100000, 0x100000 - 0xe0000 }, 32 { 0, 0, 0 } 33 }; 34 35 static acpi_descriptor_header* sAcpiRsdt; // System Description Table 36 static int32 sNumEntries = -1; 37 38 39 static status_t 40 acpi_check_rsdt(acpi_rsdp* rsdp) 41 { 42 TRACE(("acpi: found rsdp at %p oem id: %.6s\n", rsdp, rsdp->oem_id)); 43 TRACE(("acpi: rsdp points to rsdt at 0x%lx\n", rsdp->rsdt_address)); 44 45 // map and validate the root system description table 46 acpi_descriptor_header* rsdt 47 = (acpi_descriptor_header*)mmu_map_physical_memory( 48 rsdp->rsdt_address, sizeof(acpi_descriptor_header), 49 kDefaultPageFlags); 50 if (rsdt == NULL 51 || strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) { 52 if (rsdt != NULL) 53 mmu_free(rsdt, sizeof(acpi_descriptor_header)); 54 TRACE(("acpi: invalid root system description table\n")); 55 return B_ERROR; 56 } 57 58 sAcpiRsdt = rsdt; 59 return B_OK; 60 } 61 62 63 acpi_descriptor_header* 64 acpi_find_table(const char* signature) 65 { 66 if (sAcpiRsdt == NULL) 67 return NULL; 68 69 if (sNumEntries == -1) { 70 sNumEntries = (sAcpiRsdt->length 71 - sizeof(acpi_descriptor_header)) / 4; 72 } 73 74 if (sNumEntries <= 0) { 75 TRACE(("acpi: root system description table is empty\n")); 76 return NULL; 77 } 78 79 TRACE(("acpi: searching %ld entries for table '%.4s'\n", sNumEntries, 80 signature)); 81 82 uint32* pointer = (uint32*)((uint8*)sAcpiRsdt 83 + sizeof(acpi_descriptor_header)); 84 85 for (int32 j = 0; j < sNumEntries; j++, pointer++) { 86 acpi_descriptor_header* header = (acpi_descriptor_header*) 87 mmu_map_physical_memory(*pointer, 88 sizeof(acpi_descriptor_header), kDefaultPageFlags); 89 if (header == NULL 90 || strncmp(header->signature, signature, 4) != 0) { 91 // not interesting for us 92 if (header != NULL) 93 mmu_free(header, sizeof(acpi_descriptor_header)); 94 TRACE(("acpi: Looking for '%.4s'. Skipping '%.4s'\n", 95 signature, header->signature)); 96 continue; 97 } 98 TRACE(("acpi: Found '%.4s' @ %p\n", signature, pointer)); 99 return header; 100 } 101 102 // If we didn't find the table, return NULL. 103 return NULL; 104 } 105 106 107 void 108 acpi_init() 109 { 110 // Try to find the ACPI RSDP. 111 for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) { 112 acpi_rsdp* rsdp = NULL; 113 114 TRACE(("acpi_init: entry base 0x%lx, limit 0x%lx\n", 115 acpi_scan_spots[i].start, acpi_scan_spots[i].stop)); 116 117 for (char* pointer = (char*)acpi_scan_spots[i].start; 118 (uint32)pointer < acpi_scan_spots[i].stop; pointer += 16) { 119 if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) { 120 TRACE(("acpi_init: found ACPI RSDP signature at %p\n", 121 pointer)); 122 rsdp = (acpi_rsdp*)pointer; 123 } 124 } 125 126 if (rsdp != NULL && acpi_check_rsdt(rsdp) == B_OK) 127 break; 128 } 129 } 130