- Make ACPI use PCH. Cuts down compile time to 9 seconds on gcc.
[reactos.git] / reactos / drivers / bus / acpi / executer / amconfig.c
1 /******************************************************************************
2 *
3 * Module Name: amconfig - Namespace reconfiguration (Load/Unload opcodes)
4 * $Revision: 1.1 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26
27 #include <acpi.h>
28
29
30 #define _COMPONENT ACPI_EXECUTER
31 MODULE_NAME ("amconfig")
32
33
34 /*****************************************************************************
35 *
36 * FUNCTION: Acpi_aml_exec_load_table
37 *
38 * PARAMETERS: Rgn_desc - Op region where the table will be obtained
39 * Ddb_handle - Where a handle to the table will be returned
40 *
41 * RETURN: Status
42 *
43 * DESCRIPTION: Load an ACPI table
44 *
45 ****************************************************************************/
46
47 static ACPI_STATUS
48 acpi_aml_exec_load_table (
49 ACPI_OPERAND_OBJECT *rgn_desc,
50 ACPI_HANDLE *ddb_handle)
51 {
52 ACPI_STATUS status;
53 ACPI_OPERAND_OBJECT *table_desc = NULL;
54 u8 *table_ptr;
55 u8 *table_data_ptr;
56 ACPI_TABLE_HEADER table_header;
57 ACPI_TABLE_DESC table_info;
58 u32 i;
59
60
61 /* TBD: [Unhandled] Object can be either a field or an opregion */
62
63
64 /* Get the table header */
65
66 table_header.length = 0;
67 for (i = 0; i < sizeof (ACPI_TABLE_HEADER); i++) {
68 status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ,
69 (ACPI_PHYSICAL_ADDRESS) i, 8,
70 (u32 *) ((u8 *) &table_header + i));
71 if (ACPI_FAILURE (status)) {
72 return (status);
73 }
74 }
75
76 /* Allocate a buffer for the entire table */
77
78 table_ptr = acpi_cm_allocate (table_header.length);
79 if (!table_ptr) {
80 return (AE_NO_MEMORY);
81 }
82
83 /* Copy the header to the buffer */
84
85 MEMCPY (table_ptr, &table_header, sizeof (ACPI_TABLE_HEADER));
86 table_data_ptr = table_ptr + sizeof (ACPI_TABLE_HEADER);
87
88
89 /* Get the table from the op region */
90
91 for (i = 0; i < table_header.length; i++) {
92 status = acpi_ev_address_space_dispatch (rgn_desc, ADDRESS_SPACE_READ,
93 (ACPI_PHYSICAL_ADDRESS)i, 8,
94 (u32 *) (table_data_ptr + i));
95 if (ACPI_FAILURE (status)) {
96 goto cleanup;
97 }
98 }
99
100
101 /* Table must be either an SSDT or a PSDT */
102
103 if ((!STRNCMP (table_header.signature,
104 acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature,
105 acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) &&
106 (!STRNCMP (table_header.signature,
107 acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature,
108 acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) {
109 status = AE_BAD_SIGNATURE;
110 goto cleanup;
111 }
112
113 /* Create an object to be the table handle */
114
115 table_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
116 if (!table_desc) {
117 status = AE_NO_MEMORY;
118 goto cleanup;
119 }
120
121
122 /* Install the new table into the local data structures */
123
124 table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr;
125 table_info.length = table_header.length;
126 table_info.allocation = ACPI_MEM_ALLOCATED;
127 table_info.base_pointer = table_ptr;
128
129 status = acpi_tb_install_table (NULL, &table_info);
130 if (ACPI_FAILURE (status)) {
131 goto cleanup;
132 }
133
134 /* Add the table to the namespace */
135
136 /* TBD: [Restructure] - change to whatever new interface is appropriate */
137 /*
138 Status = Acpi_load_namespace ();
139 if (ACPI_FAILURE (Status))
140 {
141 */
142 /* TBD: [Errors] Unload the table on failure ? */
143 /*
144 goto Cleanup;
145 }
146 */
147
148
149 /* TBD: [Investigate] we need a pointer to the table desc */
150
151 /* Init the table handle */
152
153 table_desc->reference.opcode = AML_LOAD_OP;
154 table_desc->reference.object = table_info.installed_desc;
155
156 *ddb_handle = table_desc;
157
158 return (status);
159
160
161 cleanup:
162
163 acpi_cm_free (table_desc);
164 acpi_cm_free (table_ptr);
165 return (status);
166
167 }
168
169
170 /*****************************************************************************
171 *
172 * FUNCTION: Acpi_aml_exec_unload_table
173 *
174 * PARAMETERS: Ddb_handle - Handle to a previously loaded table
175 *
176 * RETURN: Status
177 *
178 * DESCRIPTION: Unload an ACPI table
179 *
180 ****************************************************************************/
181
182 static ACPI_STATUS
183 acpi_aml_exec_unload_table (
184 ACPI_HANDLE ddb_handle)
185 {
186 ACPI_STATUS status = AE_NOT_IMPLEMENTED;
187 ACPI_OPERAND_OBJECT *table_desc = (ACPI_OPERAND_OBJECT *) ddb_handle;
188 ACPI_TABLE_DESC *table_info;
189
190
191 /* Validate the handle */
192 /* Although the handle is partially validated in Acpi_aml_exec_reconfiguration(),
193 * when it calls Acpi_aml_resolve_operands(), the handle is more completely
194 * validated here.
195 */
196
197 if ((!ddb_handle) ||
198 (!VALID_DESCRIPTOR_TYPE (ddb_handle, ACPI_DESC_TYPE_INTERNAL)) ||
199 (((ACPI_OPERAND_OBJECT *)ddb_handle)->common.type !=
200 INTERNAL_TYPE_REFERENCE)) {
201 return (AE_BAD_PARAMETER);
202 }
203
204
205 /* Get the actual table descriptor from the Ddb_handle */
206
207 table_info = (ACPI_TABLE_DESC *) table_desc->reference.object;
208
209 /*
210 * Delete the entire namespace under this table Node
211 * (Offset contains the Table_id)
212 */
213
214 status = acpi_ns_delete_namespace_by_owner (table_info->table_id);
215 if (ACPI_FAILURE (status)) {
216 return (status);
217 }
218
219 /* Delete the table itself */
220
221 acpi_tb_uninstall_table (table_info->installed_desc);
222
223 /* Delete the table descriptor (Ddb_handle) */
224
225 acpi_cm_remove_reference (table_desc);
226
227 return (status);
228 }
229
230
231 /*****************************************************************************
232 *
233 * FUNCTION: Acpi_aml_exec_reconfiguration
234 *
235 * PARAMETERS: Opcode - The opcode to be executed
236 * Walk_state - Current state of the parse tree walk
237 *
238 * RETURN: Status
239 *
240 * DESCRIPTION: Reconfiguration opcodes such as LOAD and UNLOAD
241 *
242 ****************************************************************************/
243
244 ACPI_STATUS
245 acpi_aml_exec_reconfiguration (
246 u16 opcode,
247 ACPI_WALK_STATE *walk_state)
248 {
249 ACPI_STATUS status;
250 ACPI_OPERAND_OBJECT *region_desc = NULL;
251 ACPI_HANDLE *ddb_handle;
252
253
254 /* Resolve the operands */
255
256 status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
257 /* Get the table handle, common for both opcodes */
258
259 status |= acpi_ds_obj_stack_pop_object ((ACPI_OPERAND_OBJECT **) &ddb_handle,
260 walk_state);
261
262 switch (opcode) {
263
264 case AML_LOAD_OP:
265
266 /* Get the region or field descriptor */
267
268 status |= acpi_ds_obj_stack_pop_object (&region_desc, walk_state);
269 if (ACPI_FAILURE (status)) {
270 acpi_cm_remove_reference (region_desc);
271 return (status);
272 }
273
274 status = acpi_aml_exec_load_table (region_desc, ddb_handle);
275 break;
276
277
278 case AML_UNLOAD_OP:
279
280 if (ACPI_FAILURE (status)) {
281 return (status);
282 }
283
284 status = acpi_aml_exec_unload_table (ddb_handle);
285 break;
286
287
288 default:
289
290 status = AE_AML_BAD_OPCODE;
291 break;
292 }
293
294
295 return (status);
296 }
297