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 37 38 static status_t 39 acpi_check_rsdt(acpi_rsdp *rsdp) 40 { 41 TRACE(("acpi: found rsdp at %p oem id: %.6s\n", rsdp, rsdp->oem_id)); 42 TRACE(("acpi: rsdp points to rsdt at 0x%lx\n", rsdp->rsdt_address)); 43 44 // map and validate the root system description table 45 acpi_descriptor_header *rsdt 46 = (acpi_descriptor_header *)mmu_map_physical_memory( 47 rsdp->rsdt_address, B_PAGE_SIZE, kDefaultPageFlags); 48 if (rsdt == NULL || strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) { 49 TRACE(("acpi: invalid root system description table\n")); 50 return B_ERROR; 51 } 52 53 sAcpiRsdt = rsdt; 54 return B_OK; 55 } 56 57 58 acpi_descriptor_header * 59 acpi_find_table(char *signature) 60 { 61 if (sAcpiRsdt == NULL) 62 return NULL; 63 64 // Tried to keep numEntries a static variable; kept turning up 0 on table 65 // scan 66 // TODO: This calculates numEntries for every acpi probe. 67 int32 numEntries = (sAcpiRsdt->length - sizeof(acpi_descriptor_header)) / 4; 68 if (numEntries <= 0) { 69 TRACE(("acpi: root system description table is empty\n")); 70 return NULL; 71 } 72 73 TRACE(("acpi: searching %ld entries for table '%.4s'\n", numEntries, 74 signature)); 75 76 uint32 *pointer = (uint32 *)((uint8 *)sAcpiRsdt 77 + sizeof(acpi_descriptor_header)); 78 79 for (int32 j = 0; j < numEntries; j++, pointer++) { 80 acpi_descriptor_header *header = (acpi_descriptor_header *) 81 mmu_map_physical_memory(*pointer, B_PAGE_SIZE, kDefaultPageFlags); 82 if (header == NULL || strncmp(header->signature, signature, 4) != 0) { 83 // not interesting for us 84 TRACE(("acpi: Looking for '%.4s'. Skipping '%.4s'\n", signature, 85 header->signature)); 86 continue; 87 } 88 TRACE(("acpi: Found '%.4s' @ %p\n", signature, pointer)); 89 return header; 90 } 91 92 // If we didn't find the table, return NULL. 93 return NULL; 94 } 95 96 97 void 98 acpi_init(void) 99 { 100 // Try to find the ACPI RSDP. 101 for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) { 102 acpi_rsdp *rsdp = NULL; 103 104 TRACE(("acpi_init: entry base 0x%lx, limit 0x%lx\n", 105 acpi_scan_spots[i].start, acpi_scan_spots[i].stop)); 106 107 for (char *pointer = (char *)acpi_scan_spots[i].start; 108 (uint32)pointer < acpi_scan_spots[i].stop; pointer += 16) { 109 if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) { 110 TRACE(("acpi_init: found ACPI RSDP signature at %p\n", pointer)); 111 rsdp = (acpi_rsdp *)pointer; 112 } 113 } 114 115 if (rsdp != NULL && acpi_check_rsdt(rsdp) == B_OK) 116 break; 117 } 118 } 119