minor corrections by M.Taguchi
[reactos.git] / reactos / drivers / bus / acpi / executer / amresolv.c
1
2 /******************************************************************************
3 *
4 * Module Name: amresolv - AML Interpreter object resolution
5 * $Revision: 1.1 $
6 *
7 *****************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27
28 #include "acpi.h"
29 #include "amlcode.h"
30 #include "acparser.h"
31 #include "acdispat.h"
32 #include "acinterp.h"
33 #include "acnamesp.h"
34 #include "actables.h"
35 #include "acevents.h"
36
37
38 #define _COMPONENT ACPI_EXECUTER
39 MODULE_NAME ("amresolv")
40
41
42 /*******************************************************************************
43 *
44 * FUNCTION: Acpi_aml_get_field_unit_value
45 *
46 * PARAMETERS: *Field_desc - Pointer to a Field_unit
47 * *Result_desc - Pointer to an empty descriptor
48 * which will become a Number
49 * containing the field's value.
50 *
51 * RETURN: Status
52 *
53 * DESCRIPTION: Retrieve the value from a Field_unit
54 *
55 ******************************************************************************/
56
57 ACPI_STATUS
58 acpi_aml_get_field_unit_value (
59 ACPI_OPERAND_OBJECT *field_desc,
60 ACPI_OPERAND_OBJECT *result_desc)
61 {
62 ACPI_STATUS status = AE_OK;
63 u32 mask;
64 u8 *location = NULL;
65 u8 locked = FALSE;
66
67
68 if (!field_desc) {
69 status = AE_AML_NO_OPERAND;
70 }
71
72 if (!(field_desc->common.flags & AOPOBJ_DATA_VALID)) {
73 status = acpi_ds_get_field_unit_arguments (field_desc);
74 if (ACPI_FAILURE (status)) {
75 return (status);
76 }
77 }
78
79 if (!field_desc->field_unit.container) {
80 status = AE_AML_INTERNAL;
81 }
82
83 else if (ACPI_TYPE_BUFFER != field_desc->field_unit.container->common.type) {
84 status = AE_AML_OPERAND_TYPE;
85 }
86
87 else if (!result_desc) {
88 status = AE_AML_INTERNAL;
89 }
90
91 if (ACPI_FAILURE (status)) {
92 return (status);
93 }
94
95
96 /* Get the global lock if needed */
97
98 locked = acpi_aml_acquire_global_lock (field_desc->field_unit.lock_rule);
99
100 /* Field location is (base of buffer) + (byte offset) */
101
102 location = field_desc->field_unit.container->buffer.pointer
103 + field_desc->field_unit.offset;
104
105 /*
106 * Construct Mask with as many 1 bits as the field width
107 *
108 * NOTE: Only the bottom 5 bits are valid for a shift operation, so
109 * special care must be taken for any shift greater than 31 bits.
110 *
111 * TBD: [Unhandled] Fields greater than 32-bits will not work.
112 */
113
114 if (field_desc->field_unit.length < 32) {
115 mask = ((u32) 1 << field_desc->field_unit.length) - (u32) 1;
116 }
117 else {
118 mask = ACPI_UINT32_MAX;
119 }
120
121 result_desc->integer.type = (u8) ACPI_TYPE_INTEGER;
122
123 /* Get the 32 bit value at the location */
124
125 MOVE_UNALIGNED32_TO_32 (&result_desc->integer.value, location);
126
127 /*
128 * Shift the 32-bit word containing the field, and mask off the
129 * resulting value
130 */
131
132 result_desc->integer.value =
133 (result_desc->integer.value >> field_desc->field_unit.bit_offset) & mask;
134
135 /* Release global lock if we acquired it earlier */
136
137 acpi_aml_release_global_lock (locked);
138
139 return (status);
140 }
141
142
143 /*******************************************************************************
144 *
145 * FUNCTION: Acpi_aml_resolve_to_value
146 *
147 * PARAMETERS: **Stack_ptr - Points to entry on Obj_stack, which can
148 * be either an (ACPI_OPERAND_OBJECT *)
149 * or an ACPI_HANDLE.
150 *
151 * RETURN: Status
152 *
153 * DESCRIPTION: Convert Reference objects to values
154 *
155 ******************************************************************************/
156
157 ACPI_STATUS
158 acpi_aml_resolve_to_value (
159 ACPI_OPERAND_OBJECT **stack_ptr,
160 ACPI_WALK_STATE *walk_state)
161 {
162 ACPI_STATUS status = AE_OK;
163
164
165 if (!stack_ptr || !*stack_ptr) {
166 return (AE_AML_NO_OPERAND);
167 }
168
169
170 /*
171 * The entity pointed to by the Stack_ptr can be either
172 * 1) A valid ACPI_OPERAND_OBJECT, or
173 * 2) A ACPI_NAMESPACE_NODE (Named_obj)
174 */
175
176 if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_INTERNAL)) {
177
178 status = acpi_aml_resolve_object_to_value (stack_ptr, walk_state);
179 if (ACPI_FAILURE (status)) {
180 return (status);
181 }
182 }
183
184 /*
185 * Object on the stack may have changed if Acpi_aml_resolve_object_to_value()
186 * was called (i.e., we can't use an _else_ here.)
187 */
188
189 if (VALID_DESCRIPTOR_TYPE (*stack_ptr, ACPI_DESC_TYPE_NAMED)) {
190 status = acpi_aml_resolve_node_to_value ((ACPI_NAMESPACE_NODE **) stack_ptr, walk_state);
191 }
192
193
194 return (status);
195 }
196
197
198 /*******************************************************************************
199 *
200 * FUNCTION: Acpi_aml_resolve_object_to_value
201 *
202 * PARAMETERS: Stack_ptr - Pointer to a stack location that contains a
203 * ptr to an internal object.
204 *
205 * RETURN: Status
206 *
207 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
208 * uses the associated AML opcode to determine the value.
209 *
210 ******************************************************************************/
211
212 ACPI_STATUS
213 acpi_aml_resolve_object_to_value (
214 ACPI_OPERAND_OBJECT **stack_ptr,
215 ACPI_WALK_STATE *walk_state)
216 {
217 ACPI_OPERAND_OBJECT *stack_desc;
218 ACPI_STATUS status = AE_OK;
219 ACPI_HANDLE temp_handle = NULL;
220 ACPI_OPERAND_OBJECT *obj_desc = NULL;
221 u32 index = 0;
222 u16 opcode;
223
224
225 stack_desc = *stack_ptr;
226
227 /* This is an ACPI_OPERAND_OBJECT */
228
229 switch (stack_desc->common.type) {
230
231 case INTERNAL_TYPE_REFERENCE:
232
233 opcode = stack_desc->reference.opcode;
234
235 switch (opcode) {
236
237 case AML_NAME_OP:
238
239 /*
240 * Convert indirect name ptr to a direct name ptr.
241 * Then, Acpi_aml_resolve_node_to_value can be used to get the value
242 */
243
244 temp_handle = stack_desc->reference.object;
245
246 /* Delete the Reference Object */
247
248 acpi_cm_remove_reference (stack_desc);
249
250 /* Put direct name pointer onto stack and exit */
251
252 (*stack_ptr) = temp_handle;
253 status = AE_OK;
254 break;
255
256
257 case AML_LOCAL_OP:
258 case AML_ARG_OP:
259
260 index = stack_desc->reference.offset;
261
262 /*
263 * Get the local from the method's state info
264 * Note: this increments the local's object reference count
265 */
266
267 status = acpi_ds_method_data_get_value (opcode, index,
268 walk_state, &obj_desc);
269 if (ACPI_FAILURE (status)) {
270 return (status);
271 }
272
273 /*
274 * Now we can delete the original Reference Object and
275 * replace it with the resolve value
276 */
277
278 acpi_cm_remove_reference (stack_desc);
279 *stack_ptr = obj_desc;
280
281 break;
282
283
284 /*
285 * TBD: [Restructure] These next three opcodes change the type of
286 * the object, which is actually a no-no.
287 */
288
289 case AML_ZERO_OP:
290
291 stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
292 stack_desc->integer.value = 0;
293 break;
294
295
296 case AML_ONE_OP:
297
298 stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
299 stack_desc->integer.value = 1;
300 break;
301
302
303 case AML_ONES_OP:
304
305 stack_desc->common.type = (u8) ACPI_TYPE_INTEGER;
306 stack_desc->integer.value = ACPI_INTEGER_MAX;
307
308 /* Truncate value if we are executing from a 32-bit ACPI table */
309
310 acpi_aml_truncate_for32bit_table (stack_desc, walk_state);
311 break;
312
313
314 case AML_INDEX_OP:
315
316 switch (stack_desc->reference.target_type) {
317 case ACPI_TYPE_BUFFER_FIELD:
318
319 /* Just return - leave the Reference on the stack */
320 break;
321
322
323 case ACPI_TYPE_PACKAGE:
324 obj_desc = *stack_desc->reference.where;
325 if (obj_desc) {
326 /*
327 * Valid obj descriptor, copy pointer to return value
328 * (i.e., dereference the package index)
329 * Delete the ref object, increment the returned object
330 */
331 acpi_cm_remove_reference (stack_desc);
332 acpi_cm_add_reference (obj_desc);
333 *stack_ptr = obj_desc;
334 }
335
336 else {
337 /*
338 * A NULL object descriptor means an unitialized element of
339 * the package, can't deref it
340 */
341
342 status = AE_AML_UNINITIALIZED_ELEMENT;
343 }
344 break;
345
346 default:
347 /* Invalid reference OBJ*/
348
349 status = AE_AML_INTERNAL;
350 break;
351 }
352
353 break;
354
355
356 case AML_DEBUG_OP:
357
358 /* Just leave the object as-is */
359 break;
360
361
362 default:
363
364 status = AE_AML_INTERNAL;
365
366 } /* switch (Opcode) */
367
368
369 if (ACPI_FAILURE (status)) {
370 return (status);
371 }
372
373 break; /* case INTERNAL_TYPE_REFERENCE */
374
375
376 case ACPI_TYPE_FIELD_UNIT:
377
378 obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY);
379 if (!obj_desc) {
380 /* Descriptor allocation failure */
381
382 return (AE_NO_MEMORY);
383 }
384
385 status = acpi_aml_get_field_unit_value (stack_desc, obj_desc);
386 if (ACPI_FAILURE (status)) {
387 acpi_cm_remove_reference (obj_desc);
388 obj_desc = NULL;
389 }
390
391 *stack_ptr = (void *) obj_desc;
392 break;
393
394
395 case INTERNAL_TYPE_BANK_FIELD:
396
397 obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_ANY);
398 if (!obj_desc) {
399 /* Descriptor allocation failure */
400
401 return (AE_NO_MEMORY);
402 }
403
404 status = acpi_aml_get_field_unit_value (stack_desc, obj_desc);
405 if (ACPI_FAILURE (status)) {
406 acpi_cm_remove_reference (obj_desc);
407 obj_desc = NULL;
408 }
409
410 *stack_ptr = (void *) obj_desc;
411 break;
412
413
414 /* TBD: [Future] - may need to handle Index_field, and Def_field someday */
415
416 default:
417
418 break;
419
420 } /* switch (Stack_desc->Common.Type) */
421
422
423 return (status);
424 }
425
426