Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / acpi / dispatcher / dsfield.c
1 /******************************************************************************
2  *
3  * Module Name: dsfield - Dispatcher field routines
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, R. Byron Moore
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44
45 #include <acpi/acpi.h>
46 #include <acpi/amlcode.h>
47 #include <acpi/acdispat.h>
48 #include <acpi/acinterp.h>
49 #include <acpi/acnamesp.h>
50 #include <acpi/acparser.h>
51
52
53 #define _COMPONENT          ACPI_DISPATCHER
54          ACPI_MODULE_NAME    ("dsfield")
55
56
57 /*******************************************************************************
58  *
59  * FUNCTION:    acpi_ds_create_buffer_field
60  *
61  * PARAMETERS:  Opcode              - The opcode to be executed
62  *              Operands            - List of operands for the opcode
63  *              walk_state          - Current state
64  *
65  * RETURN:      Status
66  *
67  * DESCRIPTION: Execute the create_field operators:
68  *              create_bit_field_op,
69  *              create_byte_field_op,
70  *              create_word_field_op,
71  *              create_dword_field_op,
72  *              create_qword_field_op,
73  *              create_field_op     (all of which define fields in buffers)
74  *
75  ******************************************************************************/
76
77 acpi_status
78 acpi_ds_create_buffer_field (
79         union acpi_parse_object         *op,
80         struct acpi_walk_state          *walk_state)
81 {
82         union acpi_parse_object         *arg;
83         struct acpi_namespace_node      *node;
84         acpi_status                     status;
85         union acpi_operand_object       *obj_desc;
86         union acpi_operand_object       *second_desc = NULL;
87         u32                             flags;
88
89
90         ACPI_FUNCTION_TRACE ("ds_create_buffer_field");
91
92
93         /* Get the name_string argument */
94
95         if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
96                 arg = acpi_ps_get_arg (op, 3);
97         }
98         else {
99                 /* Create Bit/Byte/Word/Dword field */
100
101                 arg = acpi_ps_get_arg (op, 2);
102         }
103
104         if (!arg) {
105                 return_ACPI_STATUS (AE_AML_NO_OPERAND);
106         }
107
108         if (walk_state->deferred_node) {
109                 node = walk_state->deferred_node;
110                 status = AE_OK;
111         }
112         else {
113                 /*
114                  * During the load phase, we want to enter the name of the field into
115                  * the namespace.  During the execute phase (when we evaluate the size
116                  * operand), we want to lookup the name
117                  */
118                 if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
119                         flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
120                 }
121                 else {
122                         flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND;
123                 }
124
125                 /*
126                  * Enter the name_string into the namespace
127                  */
128                 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
129                                  ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
130                                  flags, walk_state, &(node));
131                 if (ACPI_FAILURE (status)) {
132                         ACPI_REPORT_NSERROR (arg->common.value.string, status);
133                         return_ACPI_STATUS (status);
134                 }
135         }
136
137         /* We could put the returned object (Node) on the object stack for later, but
138          * for now, we will put it in the "op" object that the parser uses, so we
139          * can get it again at the end of this scope
140          */
141         op->common.node = node;
142
143         /*
144          * If there is no object attached to the node, this node was just created and
145          * we need to create the field object.  Otherwise, this was a lookup of an
146          * existing node and we don't want to create the field object again.
147          */
148         obj_desc = acpi_ns_get_attached_object (node);
149         if (obj_desc) {
150                 return_ACPI_STATUS (AE_OK);
151         }
152
153         /*
154          * The Field definition is not fully parsed at this time.
155          * (We must save the address of the AML for the buffer and index operands)
156          */
157
158         /* Create the buffer field object */
159
160         obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD);
161         if (!obj_desc) {
162                 status = AE_NO_MEMORY;
163                 goto cleanup;
164         }
165
166         /*
167          * Remember location in AML stream of the field unit
168          * opcode and operands -- since the buffer and index
169          * operands must be evaluated.
170          */
171         second_desc                 = obj_desc->common.next_object;
172         second_desc->extra.aml_start = op->named.data;
173         second_desc->extra.aml_length = op->named.length;
174         obj_desc->buffer_field.node = node;
175
176         /* Attach constructed field descriptors to parent node */
177
178         status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
179         if (ACPI_FAILURE (status)) {
180                 goto cleanup;
181         }
182
183
184 cleanup:
185
186         /* Remove local reference to the object */
187
188         acpi_ut_remove_reference (obj_desc);
189         return_ACPI_STATUS (status);
190 }
191
192
193 /*******************************************************************************
194  *
195  * FUNCTION:    acpi_ds_get_field_names
196  *
197  * PARAMETERS:  Info            - create_field info structure
198  *  `           walk_state      - Current method state
199  *              Arg             - First parser arg for the field name list
200  *
201  * RETURN:      Status
202  *
203  * DESCRIPTION: Process all named fields in a field declaration.  Names are
204  *              entered into the namespace.
205  *
206  ******************************************************************************/
207
208 acpi_status
209 acpi_ds_get_field_names (
210         struct acpi_create_field_info   *info,
211         struct acpi_walk_state          *walk_state,
212         union acpi_parse_object         *arg)
213 {
214         acpi_status                     status;
215         acpi_integer                    position;
216
217
218         ACPI_FUNCTION_TRACE_PTR ("ds_get_field_names", info);
219
220
221         /* First field starts at bit zero */
222
223         info->field_bit_position = 0;
224
225         /* Process all elements in the field list (of parse nodes) */
226
227         while (arg) {
228                 /*
229                  * Three types of field elements are handled:
230                  * 1) Offset - specifies a bit offset
231                  * 2) access_as - changes the access mode
232                  * 3) Name - Enters a new named field into the namespace
233                  */
234                 switch (arg->common.aml_opcode) {
235                 case AML_INT_RESERVEDFIELD_OP:
236
237                         position = (acpi_integer) info->field_bit_position
238                                          + (acpi_integer) arg->common.value.size;
239
240                         if (position > ACPI_UINT32_MAX) {
241                                 ACPI_REPORT_ERROR (("Bit offset within field too large (> 0xFFFFFFFF)\n"));
242                                 return_ACPI_STATUS (AE_SUPPORT);
243                         }
244
245                         info->field_bit_position = (u32) position;
246                         break;
247
248
249                 case AML_INT_ACCESSFIELD_OP:
250
251                         /*
252                          * Get a new access_type and access_attribute -- to be used for all
253                          * field units that follow, until field end or another access_as keyword.
254                          *
255                          * In field_flags, preserve the flag bits other than the ACCESS_TYPE bits
256                          */
257                         info->field_flags = (u8) ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
258                                           ((u8) ((u32) arg->common.value.integer >> 8)));
259
260                         info->attribute = (u8) (arg->common.value.integer);
261                         break;
262
263
264                 case AML_INT_NAMEDFIELD_OP:
265
266                         /* Lookup the name */
267
268                         status = acpi_ns_lookup (walk_state->scope_info,
269                                           (char *) &arg->named.name,
270                                           info->field_type, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE,
271                                           walk_state, &info->field_node);
272                         if (ACPI_FAILURE (status)) {
273                                 ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
274                                 if (status != AE_ALREADY_EXISTS) {
275                                         return_ACPI_STATUS (status);
276                                 }
277
278                                 /* Already exists, ignore error */
279                         }
280                         else {
281                                 arg->common.node = info->field_node;
282                                 info->field_bit_length = arg->common.value.size;
283
284                                 /* Create and initialize an object for the new Field Node */
285
286                                 status = acpi_ex_prep_field_value (info);
287                                 if (ACPI_FAILURE (status)) {
288                                         return_ACPI_STATUS (status);
289                                 }
290                         }
291
292                         /* Keep track of bit position for the next field */
293
294                         position = (acpi_integer) info->field_bit_position
295                                          + (acpi_integer) arg->common.value.size;
296
297                         if (position > ACPI_UINT32_MAX) {
298                                 ACPI_REPORT_ERROR (("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n",
299                                                 (char *) &info->field_node->name));
300                                 return_ACPI_STATUS (AE_SUPPORT);
301                         }
302
303                         info->field_bit_position += info->field_bit_length;
304                         break;
305
306
307                 default:
308
309                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n",
310                                 arg->common.aml_opcode));
311                         return_ACPI_STATUS (AE_AML_BAD_OPCODE);
312                 }
313
314                 arg = arg->common.next;
315         }
316
317         return_ACPI_STATUS (AE_OK);
318 }
319
320
321 /*******************************************************************************
322  *
323  * FUNCTION:    acpi_ds_create_field
324  *
325  * PARAMETERS:  Op              - Op containing the Field definition and args
326  *              region_node     - Object for the containing Operation Region
327  *  `           walk_state      - Current method state
328  *
329  * RETURN:      Status
330  *
331  * DESCRIPTION: Create a new field in the specified operation region
332  *
333  ******************************************************************************/
334
335 acpi_status
336 acpi_ds_create_field (
337         union acpi_parse_object         *op,
338         struct acpi_namespace_node      *region_node,
339         struct acpi_walk_state          *walk_state)
340 {
341         acpi_status                     status;
342         union acpi_parse_object         *arg;
343         struct acpi_create_field_info   info;
344
345
346         ACPI_FUNCTION_TRACE_PTR ("ds_create_field", op);
347
348
349         /* First arg is the name of the parent op_region (must already exist) */
350
351         arg = op->common.value.arg;
352         if (!region_node) {
353                 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
354                                   ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
355                                   ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
356                 if (ACPI_FAILURE (status)) {
357                         ACPI_REPORT_NSERROR (arg->common.value.name, status);
358                         return_ACPI_STATUS (status);
359                 }
360         }
361
362         /* Second arg is the field flags */
363
364         arg = arg->common.next;
365         info.field_flags = (u8) arg->common.value.integer;
366         info.attribute = 0;
367
368         /* Each remaining arg is a Named Field */
369
370         info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
371         info.region_node = region_node;
372
373         status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
374
375         return_ACPI_STATUS (status);
376 }
377
378
379 /*******************************************************************************
380  *
381  * FUNCTION:    acpi_ds_init_field_objects
382  *
383  * PARAMETERS:  Op              - Op containing the Field definition and args
384  *  `           walk_state      - Current method state
385  *
386  * RETURN:      Status
387  *
388  * DESCRIPTION: For each "Field Unit" name in the argument list that is
389  *              part of the field declaration, enter the name into the
390  *              namespace.
391  *
392  ******************************************************************************/
393
394 acpi_status
395 acpi_ds_init_field_objects (
396         union acpi_parse_object         *op,
397         struct acpi_walk_state          *walk_state)
398 {
399         acpi_status                     status;
400         union acpi_parse_object         *arg = NULL;
401         struct acpi_namespace_node      *node;
402         u8                              type = 0;
403
404
405         ACPI_FUNCTION_TRACE_PTR ("ds_init_field_objects", op);
406
407
408         switch (walk_state->opcode) {
409         case AML_FIELD_OP:
410                 arg = acpi_ps_get_arg (op, 2);
411                 type = ACPI_TYPE_LOCAL_REGION_FIELD;
412                 break;
413
414         case AML_BANK_FIELD_OP:
415                 arg = acpi_ps_get_arg (op, 4);
416                 type = ACPI_TYPE_LOCAL_BANK_FIELD;
417                 break;
418
419         case AML_INDEX_FIELD_OP:
420                 arg = acpi_ps_get_arg (op, 3);
421                 type = ACPI_TYPE_LOCAL_INDEX_FIELD;
422                 break;
423
424         default:
425                 return_ACPI_STATUS (AE_BAD_PARAMETER);
426         }
427
428         /*
429          * Walk the list of entries in the field_list
430          */
431         while (arg) {
432                 /* Ignore OFFSET and ACCESSAS terms here */
433
434                 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
435                         status = acpi_ns_lookup (walk_state->scope_info,
436                                           (char *) &arg->named.name,
437                                           type, ACPI_IMODE_LOAD_PASS1,
438                                           ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
439                                           walk_state, &node);
440                         if (ACPI_FAILURE (status)) {
441                                 ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
442                                 if (status != AE_ALREADY_EXISTS) {
443                                         return_ACPI_STATUS (status);
444                                 }
445
446                                 /* Name already exists, just ignore this error */
447
448                                 status = AE_OK;
449                         }
450
451                         arg->common.node = node;
452                 }
453
454                 /* Move to next field in the list */
455
456                 arg = arg->common.next;
457         }
458
459         return_ACPI_STATUS (AE_OK);
460 }
461
462
463 /*******************************************************************************
464  *
465  * FUNCTION:    acpi_ds_create_bank_field
466  *
467  * PARAMETERS:  Op              - Op containing the Field definition and args
468  *              region_node     - Object for the containing Operation Region
469  *  `           walk_state      - Current method state
470  *
471  * RETURN:      Status
472  *
473  * DESCRIPTION: Create a new bank field in the specified operation region
474  *
475  ******************************************************************************/
476
477 acpi_status
478 acpi_ds_create_bank_field (
479         union acpi_parse_object         *op,
480         struct acpi_namespace_node      *region_node,
481         struct acpi_walk_state          *walk_state)
482 {
483         acpi_status                     status;
484         union acpi_parse_object         *arg;
485         struct acpi_create_field_info   info;
486
487
488         ACPI_FUNCTION_TRACE_PTR ("ds_create_bank_field", op);
489
490
491         /* First arg is the name of the parent op_region (must already exist) */
492
493         arg = op->common.value.arg;
494         if (!region_node) {
495                 status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
496                                   ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
497                                   ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
498                 if (ACPI_FAILURE (status)) {
499                         ACPI_REPORT_NSERROR (arg->common.value.name, status);
500                         return_ACPI_STATUS (status);
501                 }
502         }
503
504         /* Second arg is the Bank Register (Field) (must already exist) */
505
506         arg = arg->common.next;
507         status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
508                           ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
509                           ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
510         if (ACPI_FAILURE (status)) {
511                 ACPI_REPORT_NSERROR (arg->common.value.string, status);
512                 return_ACPI_STATUS (status);
513         }
514
515         /* Third arg is the bank_value */
516
517         arg = arg->common.next;
518         info.bank_value = (u32) arg->common.value.integer;
519
520         /* Fourth arg is the field flags */
521
522         arg = arg->common.next;
523         info.field_flags = (u8) arg->common.value.integer;
524
525         /* Each remaining arg is a Named Field */
526
527         info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
528         info.region_node = region_node;
529
530         status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
531
532         return_ACPI_STATUS (status);
533 }
534
535
536 /*******************************************************************************
537  *
538  * FUNCTION:    acpi_ds_create_index_field
539  *
540  * PARAMETERS:  Op              - Op containing the Field definition and args
541  *              region_node     - Object for the containing Operation Region
542  *  `           walk_state      - Current method state
543  *
544  * RETURN:      Status
545  *
546  * DESCRIPTION: Create a new index field in the specified operation region
547  *
548  ******************************************************************************/
549
550 acpi_status
551 acpi_ds_create_index_field (
552         union acpi_parse_object         *op,
553         struct acpi_namespace_node      *region_node,
554         struct acpi_walk_state          *walk_state)
555 {
556         acpi_status                     status;
557         union acpi_parse_object         *arg;
558         struct acpi_create_field_info   info;
559
560
561         ACPI_FUNCTION_TRACE_PTR ("ds_create_index_field", op);
562
563
564         /* First arg is the name of the Index register (must already exist) */
565
566         arg = op->common.value.arg;
567         status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
568                           ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
569                           ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
570         if (ACPI_FAILURE (status)) {
571                 ACPI_REPORT_NSERROR (arg->common.value.string, status);
572                 return_ACPI_STATUS (status);
573         }
574
575         /* Second arg is the data register (must already exist) */
576
577         arg = arg->common.next;
578         status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
579                           ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
580                           ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node);
581         if (ACPI_FAILURE (status)) {
582                 ACPI_REPORT_NSERROR (arg->common.value.string, status);
583                 return_ACPI_STATUS (status);
584         }
585
586         /* Next arg is the field flags */
587
588         arg = arg->common.next;
589         info.field_flags = (u8) arg->common.value.integer;
590
591         /* Each remaining arg is a Named Field */
592
593         info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
594         info.region_node = region_node;
595
596         status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
597
598         return_ACPI_STATUS (status);
599 }
600
601