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