xref: /haiku/src/system/boot/platform/bios_ia32/acpi.cpp (revision 0562493379cd52eb7103531f895f10bb8e77c085)
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