Merge trunk HEAD (r46369)
[reactos.git] / reactos / drivers / bus / acpi / executer / amstore.c
1
2 /******************************************************************************
3 *
4 * Module Name: amstore - AML Interpreter object store support
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
30
31 #define _COMPONENT ACPI_EXECUTER
32 MODULE_NAME ("amstore")
33
34
35 /*******************************************************************************
36 *
37 * FUNCTION: Acpi_aml_exec_store
38 *
39 * PARAMETERS: *Val_desc - Value to be stored
40 * *Dest_desc - Where to store it 0 Must be (ACPI_HANDLE)
41 * or an ACPI_OPERAND_OBJECT of type
42 * Reference; if the latter the descriptor
43 * will be either reused or deleted.
44 *
45 * RETURN: Status
46 *
47 * DESCRIPTION: Store the value described by Val_desc into the location
48 * described by Dest_desc. Called by various interpreter
49 * functions to store the result of an operation into
50 * the destination operand.
51 *
52 ******************************************************************************/
53
54 ACPI_STATUS
55 acpi_aml_exec_store (
56 ACPI_OPERAND_OBJECT *val_desc,
57 ACPI_OPERAND_OBJECT *dest_desc,
58 ACPI_WALK_STATE *walk_state)
59 {
60 ACPI_STATUS status = AE_OK;
61 ACPI_OPERAND_OBJECT *ref_desc = dest_desc;
62
63
64 /* Validate parameters */
65
66 if (!val_desc || !dest_desc) {
67 return (AE_AML_NO_OPERAND);
68 }
69
70 /* Dest_desc can be either a namespace node or an ACPI object */
71
72 if (VALID_DESCRIPTOR_TYPE (dest_desc, ACPI_DESC_TYPE_NAMED)) {
73 /*
74 * Dest is a namespace node,
75 * Storing an object into a Name "container"
76 */
77 status = acpi_aml_store_object_to_node (val_desc,
78 (ACPI_NAMESPACE_NODE *) dest_desc, walk_state);
79
80 /* All done, that's it */
81
82 return (status);
83 }
84
85
86 /* Destination object must be an object of type Reference */
87
88 if (dest_desc->common.type != INTERNAL_TYPE_REFERENCE) {
89 /* Destination is not an Reference */
90
91 return (AE_AML_OPERAND_TYPE);
92 }
93
94
95 /*
96 * Examine the Reference opcode. These cases are handled:
97 *
98 * 1) Store to Name (Change the object associated with a name)
99 * 2) Store to an indexed area of a Buffer or Package
100 * 3) Store to a Method Local or Arg
101 * 4) Store to the debug object
102 * 5) Store to a constant -- a noop
103 */
104
105 switch (ref_desc->reference.opcode) {
106
107 case AML_NAME_OP:
108
109 /* Storing an object into a Name "container" */
110
111 status = acpi_aml_store_object_to_node (val_desc, ref_desc->reference.object,
112 walk_state);
113 break;
114
115
116 case AML_INDEX_OP:
117
118 /* Storing to an Index (pointer into a packager or buffer) */
119
120 status = acpi_aml_store_object_to_index (val_desc, ref_desc, walk_state);
121 break;
122
123
124 case AML_LOCAL_OP:
125 case AML_ARG_OP:
126
127 /* Store to a method local/arg */
128
129 status = acpi_ds_store_object_to_local (ref_desc->reference.opcode,
130 ref_desc->reference.offset, val_desc, walk_state);
131 break;
132
133
134 case AML_DEBUG_OP:
135
136 /*
137 * Storing to the Debug object causes the value stored to be
138 * displayed and otherwise has no effect -- see ACPI Specification
139 *
140 * TBD: print known object types "prettier".
141 */
142
143 break;
144
145
146 case AML_ZERO_OP:
147 case AML_ONE_OP:
148 case AML_ONES_OP:
149
150 /*
151 * Storing to a constant is a no-op -- see ACPI Specification
152 * Delete the reference descriptor, however
153 */
154 break;
155
156
157 default:
158
159 /* TBD: [Restructure] use object dump routine !! */
160
161 status = AE_AML_INTERNAL;
162 break;
163
164 } /* switch (Ref_desc->Reference.Opcode) */
165
166
167 /* Always delete the reference descriptor object */
168
169 if (ref_desc) {
170 acpi_cm_remove_reference (ref_desc);
171 }
172
173 return (status);
174 }
175
176
177 /*******************************************************************************
178 *
179 * FUNCTION: Acpi_aml_store_object_to_index
180 *
181 * PARAMETERS: *Val_desc - Value to be stored
182 * *Node - Named object to receive the value
183 *
184 * RETURN: Status
185 *
186 * DESCRIPTION: Store the object to the named object.
187 *
188 ******************************************************************************/
189
190 ACPI_STATUS
191 acpi_aml_store_object_to_index (
192 ACPI_OPERAND_OBJECT *val_desc,
193 ACPI_OPERAND_OBJECT *dest_desc,
194 ACPI_WALK_STATE *walk_state)
195 {
196 ACPI_STATUS status = AE_OK;
197 ACPI_OPERAND_OBJECT *obj_desc;
198 u32 length;
199 u32 i;
200 u8 value = 0;
201
202
203 /*
204 * Destination must be a reference pointer, and
205 * must point to either a buffer or a package
206 */
207
208 switch (dest_desc->reference.target_type) {
209 case ACPI_TYPE_PACKAGE:
210 /*
211 * Storing to a package element is not simple. The source must be
212 * evaluated and converted to the type of the destination and then the
213 * source is copied into the destination - we can't just point to the
214 * source object.
215 */
216 if (dest_desc->reference.target_type == ACPI_TYPE_PACKAGE) {
217 /*
218 * The object at *(Dest_desc->Reference.Where) is the
219 * element within the package that is to be modified.
220 */
221 obj_desc = *(dest_desc->reference.where);
222 if (obj_desc) {
223 /*
224 * If the Destination element is a package, we will delete
225 * that object and construct a new one.
226 *
227 * TBD: [Investigate] Should both the src and dest be required
228 * to be packages?
229 * && (Val_desc->Common.Type == ACPI_TYPE_PACKAGE)
230 */
231 if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
232 /*
233 * Take away the reference for being part of a package and
234 * delete
235 */
236 acpi_cm_remove_reference (obj_desc);
237 acpi_cm_remove_reference (obj_desc);
238
239 obj_desc = NULL;
240 }
241 }
242
243 if (!obj_desc) {
244 /*
245 * If the Obj_desc is NULL, it means that an uninitialized package
246 * element has been used as a destination (this is OK), therefore,
247 * we must create the destination element to match the type of the
248 * source element NOTE: Val_desc can be of any type.
249 */
250 obj_desc = acpi_cm_create_internal_object (val_desc->common.type);
251 if (!obj_desc) {
252 return (AE_NO_MEMORY);
253 }
254
255 /*
256 * If the source is a package, copy the source to the new dest
257 */
258 if (ACPI_TYPE_PACKAGE == obj_desc->common.type) {
259 status = acpi_cm_copy_ipackage_to_ipackage (val_desc, obj_desc, walk_state);
260 if (ACPI_FAILURE (status)) {
261 acpi_cm_remove_reference (obj_desc);
262 return (status);
263 }
264 }
265
266 /*
267 * Install the new descriptor into the package and add a
268 * reference to the newly created descriptor for now being
269 * part of the parent package
270 */
271
272 *(dest_desc->reference.where) = obj_desc;
273 acpi_cm_add_reference (obj_desc);
274 }
275
276 if (ACPI_TYPE_PACKAGE != obj_desc->common.type) {
277 /*
278 * The destination element is not a package, so we need to
279 * convert the contents of the source (Val_desc) and copy into
280 * the destination (Obj_desc)
281 */
282 status = acpi_aml_store_object_to_object (val_desc, obj_desc,
283 walk_state);
284 if (ACPI_FAILURE (status)) {
285 /*
286 * An error occurrered when copying the internal object
287 * so delete the reference.
288 */
289 return (AE_AML_OPERAND_TYPE);
290 }
291 }
292 }
293 break;
294
295
296 case ACPI_TYPE_BUFFER_FIELD:
297 /*
298 * Storing into a buffer at a location defined by an Index.
299 *
300 * Each 8-bit element of the source object is written to the
301 * 8-bit Buffer Field of the Index destination object.
302 */
303
304 /*
305 * Set the Obj_desc to the destination object and type check.
306 */
307 obj_desc = dest_desc->reference.object;
308 if (obj_desc->common.type != ACPI_TYPE_BUFFER) {
309 return (AE_AML_OPERAND_TYPE);
310 }
311
312 /*
313 * The assignment of the individual elements will be slightly
314 * different for each source type.
315 */
316
317 switch (val_desc->common.type) {
318 /*
319 * If the type is Integer, assign bytewise
320 * This loop to assign each of the elements is somewhat
321 * backward because of the Big Endian-ness of IA-64
322 */
323 case ACPI_TYPE_INTEGER:
324 length = sizeof (ACPI_INTEGER);
325 for (i = length; i != 0; i--) {
326 value = (u8)(val_desc->integer.value >> (MUL_8 (i - 1)));
327 obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
328 }
329 break;
330
331 /*
332 * If the type is Buffer, the Length is in the structure.
333 * Just loop through the elements and assign each one in turn.
334 */
335 case ACPI_TYPE_BUFFER:
336 length = val_desc->buffer.length;
337 for (i = 0; i < length; i++) {
338 value = *(val_desc->buffer.pointer + i);
339 obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
340 }
341 break;
342
343 /*
344 * If the type is String, the Length is in the structure.
345 * Just loop through the elements and assign each one in turn.
346 */
347 case ACPI_TYPE_STRING:
348 length = val_desc->string.length;
349 for (i = 0; i < length; i++) {
350 value = *(val_desc->string.pointer + i);
351 obj_desc->buffer.pointer[dest_desc->reference.offset] = value;
352 }
353 break;
354
355 /*
356 * If source is not a valid type so return an error.
357 */
358 default:
359 status = AE_AML_OPERAND_TYPE;
360 break;
361 }
362 break;
363
364
365 default:
366 status = AE_AML_OPERAND_TYPE;
367 break;
368 }
369
370
371 return (status);
372 }
373
374
375 /*******************************************************************************
376 *
377 * FUNCTION: Acpi_aml_store_object_to_node
378 *
379 * PARAMETERS: *Source_desc - Value to be stored
380 * *Node - Named object to receive the value
381 *
382 * RETURN: Status
383 *
384 * DESCRIPTION: Store the object to the named object.
385 *
386 * The Assignment of an object to a named object is handled here
387 * The val passed in will replace the current value (if any)
388 * with the input value.
389 *
390 * When storing into an object the data is converted to the
391 * target object type then stored in the object. This means
392 * that the target object type (for an initialized target) will
393 * not be changed by a store operation.
394 *
395 * NOTE: the global lock is acquired early. This will result
396 * in the global lock being held a bit longer. Also, if the
397 * function fails during set up we may get the lock when we
398 * don't really need it. I don't think we care.
399 *
400 ******************************************************************************/
401
402 ACPI_STATUS
403 acpi_aml_store_object_to_node (
404 ACPI_OPERAND_OBJECT *source_desc,
405 ACPI_NAMESPACE_NODE *node,
406 ACPI_WALK_STATE *walk_state)
407 {
408 ACPI_STATUS status = AE_OK;
409 ACPI_OPERAND_OBJECT *target_desc;
410 OBJECT_TYPE_INTERNAL target_type = ACPI_TYPE_ANY;
411
412
413 /*
414 * Assuming the parameters were already validated
415 */
416 ACPI_ASSERT((node) && (source_desc));
417
418
419 /*
420 * Get current type of the node, and object attached to Node
421 */
422 target_type = acpi_ns_get_type (node);
423 target_desc = acpi_ns_get_attached_object (node);
424
425
426 /*
427 * Resolve the source object to an actual value
428 * (If it is a reference object)
429 */
430 status = acpi_aml_resolve_object (&source_desc, target_type, walk_state);
431 if (ACPI_FAILURE (status)) {
432 return (status);
433 }
434
435
436 /*
437 * Do the actual store operation
438 */
439 switch (target_type) {
440 case INTERNAL_TYPE_DEF_FIELD:
441
442 /* Raw data copy for target types Integer/String/Buffer */
443
444 status = acpi_aml_copy_data_to_named_field (source_desc, node);
445 break;
446
447
448 case ACPI_TYPE_INTEGER:
449 case ACPI_TYPE_STRING:
450 case ACPI_TYPE_BUFFER:
451 case INTERNAL_TYPE_BANK_FIELD:
452 case INTERNAL_TYPE_INDEX_FIELD:
453 case ACPI_TYPE_FIELD_UNIT:
454
455 /*
456 * These target types are all of type Integer/String/Buffer, and
457 * therefore support implicit conversion before the store.
458 *
459 * Copy and/or convert the source object to a new target object
460 */
461 status = acpi_aml_store_object (source_desc, target_type, &target_desc, walk_state);
462 if (ACPI_FAILURE (status)) {
463 return (status);
464 }
465
466 /*
467 * Store the new Target_desc as the new value of the Name, and set
468 * the Name's type to that of the value being stored in it.
469 * Source_desc reference count is incremented by Attach_object.
470 */
471 status = acpi_ns_attach_object (node, target_desc, target_type);
472 break;
473
474
475 default:
476
477 /* No conversions for all other types. Just attach the source object */
478
479 status = acpi_ns_attach_object (node, source_desc, source_desc->common.type);
480
481 break;
482 }
483
484
485 return (status);
486 }
487
488
489 /*******************************************************************************
490 *
491 * FUNCTION: Acpi_aml_store_object_to_object
492 *
493 * PARAMETERS: *Source_desc - Value to be stored
494 * *Dest_desc - Object to receive the value
495 *
496 * RETURN: Status
497 *
498 * DESCRIPTION: Store an object to another object.
499 *
500 * The Assignment of an object to another (not named) object
501 * is handled here.
502 * The val passed in will replace the current value (if any)
503 * with the input value.
504 *
505 * When storing into an object the data is converted to the
506 * target object type then stored in the object. This means
507 * that the target object type (for an initialized target) will
508 * not be changed by a store operation.
509 *
510 * This module allows destination types of Number, String,
511 * and Buffer.
512 *
513 ******************************************************************************/
514
515 ACPI_STATUS
516 acpi_aml_store_object_to_object (
517 ACPI_OPERAND_OBJECT *source_desc,
518 ACPI_OPERAND_OBJECT *dest_desc,
519 ACPI_WALK_STATE *walk_state)
520 {
521 ACPI_STATUS status = AE_OK;
522 OBJECT_TYPE_INTERNAL destination_type = dest_desc->common.type;
523
524
525 /*
526 * Assuming the parameters are valid!
527 */
528 ACPI_ASSERT((dest_desc) && (source_desc));
529
530
531 /*
532 * From this interface, we only support Integers/Strings/Buffers
533 */
534 switch (destination_type) {
535 case ACPI_TYPE_INTEGER:
536 case ACPI_TYPE_STRING:
537 case ACPI_TYPE_BUFFER:
538 break;
539
540 default:
541 return (AE_NOT_IMPLEMENTED);
542 }
543
544
545 /*
546 * Resolve the source object to an actual value
547 * (If it is a reference object)
548 */
549 status = acpi_aml_resolve_object (&source_desc, destination_type, walk_state);
550 if (ACPI_FAILURE (status)) {
551 return (status);
552 }
553
554
555 /*
556 * Copy and/or convert the source object to the destination object
557 */
558 status = acpi_aml_store_object (source_desc, destination_type, &dest_desc, walk_state);
559
560
561 return (status);
562 }
563