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