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 TRACE(("acpi: Looking for '%.4s'. Skipping '%.4s'\n", 93 signature, header != NULL ? header->signature : "null")); 94 95 if (header != NULL) 96 mmu_free(header, sizeof(acpi_descriptor_header)); 97 98 continue; 99 } 100 101 TRACE(("acpi: Found '%.4s' @ %p\n", signature, pointer)); 102 return header; 103 } 104 105 // If we didn't find the table, return NULL. 106 return NULL; 107 } 108 109 110 void 111 acpi_init() 112 { 113 // Try to find the ACPI RSDP. 114 for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) { 115 acpi_rsdp* rsdp = NULL; 116 117 TRACE(("acpi_init: entry base 0x%lx, limit 0x%lx\n", 118 acpi_scan_spots[i].start, acpi_scan_spots[i].stop)); 119 120 for (char* pointer = (char*)acpi_scan_spots[i].start; 121 (uint32)pointer < acpi_scan_spots[i].stop; pointer += 16) { 122 if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) { 123 TRACE(("acpi_init: found ACPI RSDP signature at %p\n", 124 pointer)); 125 rsdp = (acpi_rsdp*)pointer; 126 } 127 } 128 129 if (rsdp != NULL && acpi_check_rsdt(rsdp) == B_OK) 130 break; 131 } 132 } 133