import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / acpi / dispatcher / dsfield.c
1 /******************************************************************************
2  *
3  * Module Name: dsfield - Dispatcher field routines
4  *              $Revision: 1.1.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 #include "amlcode.h"
29 #include "acdispat.h"
30 #include "acinterp.h"
31 #include "acnamesp.h"
32 #include "acparser.h"
33
34
35 #define _COMPONENT          ACPI_DISPATCHER
36          MODULE_NAME         ("dsfield")
37
38
39 /*******************************************************************************
40  *
41  * FUNCTION:    Acpi_ds_create_buffer_field
42  *
43  * PARAMETERS:  Opcode              - The opcode to be executed
44  *              Operands            - List of operands for the opcode
45  *              Walk_state          - Current state
46  *
47  * RETURN:      Status
48  *
49  * DESCRIPTION: Execute the Create_field operators:
50  *              Create_bit_field_op,
51  *              Create_byte_field_op,
52  *              Create_word_field_op,
53  *              Create_dWord_field_op,
54  *              Create_qWord_field_op,
55  *              Create_field_op     (all of which define fields in buffers)
56  *
57  ******************************************************************************/
58
59 acpi_status
60 acpi_ds_create_buffer_field (
61         acpi_parse_object       *op,
62         acpi_walk_state         *walk_state)
63 {
64         acpi_parse_object       *arg;
65         acpi_namespace_node     *node;
66         acpi_status             status;
67         acpi_operand_object     *obj_desc;
68
69
70         FUNCTION_TRACE ("Ds_create_buffer_field");
71
72
73         /* Get the Name_string argument */
74
75         if (op->opcode == AML_CREATE_FIELD_OP) {
76                 arg = acpi_ps_get_arg (op, 3);
77         }
78         else {
79                 /* Create Bit/Byte/Word/Dword field */
80
81                 arg = acpi_ps_get_arg (op, 2);
82         }
83
84         if (!arg) {
85                 return_ACPI_STATUS (AE_AML_NO_OPERAND);
86         }
87
88         /*
89          * Enter the Name_string into the namespace
90          */
91         status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
92                          INTERNAL_TYPE_DEF_ANY, IMODE_LOAD_PASS1,
93                          NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
94                          walk_state, &(node));
95         if (ACPI_FAILURE (status)) {
96                 return_ACPI_STATUS (status);
97         }
98
99         /* We could put the returned object (Node) on the object stack for later, but
100          * for now, we will put it in the "op" object that the parser uses, so we
101          * can get it again at the end of this scope
102          */
103         op->node = node;
104
105         /*
106          * If there is no object attached to the node, this node was just created and
107          * we need to create the field object.  Otherwise, this was a lookup of an
108          * existing node and we don't want to create the field object again.
109          */
110         if (node->object) {
111                 return_ACPI_STATUS (AE_OK);
112         }
113
114         /*
115          * The Field definition is not fully parsed at this time.
116          * (We must save the address of the AML for the buffer and index operands)
117          */
118
119         /* Create the buffer field object */
120
121         obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD);
122         if (!obj_desc) {
123                 status = AE_NO_MEMORY;
124                 goto cleanup;
125         }
126
127         /*
128          * Allocate a method object for this field unit
129          */
130         obj_desc->buffer_field.extra = acpi_ut_create_internal_object (
131                            INTERNAL_TYPE_EXTRA);
132         if (!obj_desc->buffer_field.extra) {
133                 status = AE_NO_MEMORY;
134                 goto cleanup;
135         }
136
137         /*
138          * Remember location in AML stream of the field unit
139          * opcode and operands -- since the buffer and index
140          * operands must be evaluated.
141          */
142         obj_desc->buffer_field.extra->extra.aml_start = ((acpi_parse2_object *) op)->data;
143         obj_desc->buffer_field.extra->extra.aml_length = ((acpi_parse2_object *) op)->length;
144         obj_desc->buffer_field.node = node;
145
146         /* Attach constructed field descriptor to parent node */
147
148         status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
149
150
151 cleanup:
152
153         /* Remove local reference to the object */
154
155         acpi_ut_remove_reference (obj_desc);
156         return_ACPI_STATUS (status);
157 }
158
159
160 /*******************************************************************************
161  *
162  * FUNCTION:    Acpi_ds_get_field_names
163  *
164  * PARAMETERS:  Info            - Create_field info structure
165  *  `           Walk_state      - Current method state
166  *              Arg             - First parser arg for the field name list
167  *
168  * RETURN:      Status
169  *
170  * DESCRIPTION: Process all named fields in a field declaration.  Names are
171  *              entered into the namespace.
172  *
173  ******************************************************************************/
174
175 acpi_status
176 acpi_ds_get_field_names (
177         ACPI_CREATE_FIELD_INFO  *info,
178         acpi_walk_state         *walk_state,
179         acpi_parse_object       *arg)
180 {
181         acpi_status             status;
182
183
184         PROC_NAME("acpi_ds_get_field_names"); 
185
186
187         /* First field starts at bit zero */
188
189         info->field_bit_position = 0;
190
191         /* Process all elements in the field list (of parse nodes) */
192
193         while (arg) {
194                 /*
195                  * Three types of field elements are handled:
196                  * 1) Offset - specifies a bit offset
197                  * 2) Access_as - changes the access mode
198                  * 3) Name - Enters a new named field into the namespace
199                  */
200                 switch (arg->opcode) {
201                 case AML_INT_RESERVEDFIELD_OP:
202
203                         info->field_bit_position += arg->value.size;
204                         break;
205
206
207                 case AML_INT_ACCESSFIELD_OP:
208
209                         /*
210                          * Get a new Access_type and Access_attribute for all
211                          * entries (until end or another Access_as keyword)
212                          */
213                         info->field_flags = (u8) ((info->field_flags & FIELD_ACCESS_TYPE_MASK) ||
214                                           ((u8) (arg->value.integer >> 8)));
215                         break;
216
217
218                 case AML_INT_NAMEDFIELD_OP:
219
220                         /* Enter a new field name into the namespace */
221
222                         status = acpi_ns_lookup (walk_state->scope_info,
223                                           (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name,
224                                           info->field_type, IMODE_LOAD_PASS1,
225                                           NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
226                                           NULL, &info->field_node);
227                         if (ACPI_FAILURE (status)) {
228                                 return_ACPI_STATUS (status);
229                         }
230
231                         /* Create and initialize an object for the new Field Node */
232
233                         info->field_bit_length = arg->value.size;
234
235                         status = acpi_ex_prep_field_value (info);
236                         if (ACPI_FAILURE (status)) {
237                                 return_ACPI_STATUS (status);
238                         }
239
240                         /* Keep track of bit position for the next field */
241
242                         info->field_bit_position += info->field_bit_length;
243                         break;
244
245
246                 default:
247
248                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n",
249                                 arg->opcode));
250                         return_ACPI_STATUS (AE_AML_ERROR);
251                         break;
252                 }
253
254                 arg = arg->next;
255         }
256
257         return_ACPI_STATUS (AE_OK);
258 }
259
260
261 /*******************************************************************************
262  *
263  * FUNCTION:    Acpi_ds_create_field
264  *
265  * PARAMETERS:  Op              - Op containing the Field definition and args
266  *              Region_node     - Object for the containing Operation Region
267  *  `           Walk_state      - Current method state
268  *
269  * RETURN:      Status
270  *
271  * DESCRIPTION: Create a new field in the specified operation region
272  *
273  ******************************************************************************/
274
275 acpi_status
276 acpi_ds_create_field (
277         acpi_parse_object       *op,
278         acpi_namespace_node     *region_node,
279         acpi_walk_state         *walk_state)
280 {
281         acpi_status             status = AE_AML_ERROR;
282         acpi_parse_object       *arg;
283         ACPI_CREATE_FIELD_INFO  info;
284
285
286         FUNCTION_TRACE_PTR ("Ds_create_field", op);
287
288
289         /* First arg is the name of the parent Op_region (must already exist) */
290
291         arg = op->value.arg;
292         if (!region_node) {
293                 status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
294                                   ACPI_TYPE_REGION, IMODE_EXECUTE,
295                                   NS_SEARCH_PARENT, walk_state, &region_node);
296                 if (ACPI_FAILURE (status)) {
297                         return_ACPI_STATUS (status);
298                 }
299         }
300
301         /* Second arg is the field flags */
302
303         arg = arg->next;
304         info.field_flags = arg->value.integer8;
305
306         /* Each remaining arg is a Named Field */
307
308         info.field_type = INTERNAL_TYPE_REGION_FIELD;
309         info.region_node = region_node;
310
311         status = acpi_ds_get_field_names (&info, walk_state, arg->next);
312
313         return_ACPI_STATUS (status);
314 }
315
316
317 /*******************************************************************************
318  *
319  * FUNCTION:    Acpi_ds_create_bank_field
320  *
321  * PARAMETERS:  Op              - Op containing the Field definition and args
322  *              Region_node     - Object for the containing Operation Region
323  *  `           Walk_state      - Current method state
324  *
325  * RETURN:      Status
326  *
327  * DESCRIPTION: Create a new bank field in the specified operation region
328  *
329  ******************************************************************************/
330
331 acpi_status
332 acpi_ds_create_bank_field (
333         acpi_parse_object       *op,
334         acpi_namespace_node     *region_node,
335         acpi_walk_state         *walk_state)
336 {
337         acpi_status             status = AE_AML_ERROR;
338         acpi_parse_object       *arg;
339         ACPI_CREATE_FIELD_INFO  info;
340
341
342         FUNCTION_TRACE_PTR ("Ds_create_bank_field", op);
343
344
345         /* First arg is the name of the parent Op_region (must already exist) */
346
347         arg = op->value.arg;
348         if (!region_node) {
349                 status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
350                                   ACPI_TYPE_REGION, IMODE_EXECUTE,
351                                   NS_SEARCH_PARENT, walk_state, &region_node);
352                 if (ACPI_FAILURE (status)) {
353                         return_ACPI_STATUS (status);
354                 }
355         }
356
357         /* Second arg is the Bank Register (must already exist) */
358
359         arg = arg->next;
360         status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
361                           INTERNAL_TYPE_BANK_FIELD_DEFN, IMODE_EXECUTE,
362                           NS_SEARCH_PARENT, walk_state, &info.register_node);
363         if (ACPI_FAILURE (status)) {
364                 return_ACPI_STATUS (status);
365         }
366
367         /* Third arg is the Bank_value */
368
369         arg = arg->next;
370         info.bank_value = arg->value.integer32;
371
372         /* Fourth arg is the field flags */
373
374         arg = arg->next;
375         info.field_flags = arg->value.integer8;
376
377         /* Each remaining arg is a Named Field */
378
379         info.field_type = INTERNAL_TYPE_BANK_FIELD;
380         info.region_node = region_node;
381
382         status = acpi_ds_get_field_names (&info, walk_state, arg->next);
383
384         return_ACPI_STATUS (status);
385 }
386
387
388 /*******************************************************************************
389  *
390  * FUNCTION:    Acpi_ds_create_index_field
391  *
392  * PARAMETERS:  Op              - Op containing the Field definition and args
393  *              Region_node     - Object for the containing Operation Region
394  *  `           Walk_state      - Current method state
395  *
396  * RETURN:      Status
397  *
398  * DESCRIPTION: Create a new index field in the specified operation region
399  *
400  ******************************************************************************/
401
402 acpi_status
403 acpi_ds_create_index_field (
404         acpi_parse_object       *op,
405         acpi_namespace_node     *region_node,
406         acpi_walk_state         *walk_state)
407 {
408         acpi_status             status;
409         acpi_parse_object       *arg;
410         ACPI_CREATE_FIELD_INFO  info;
411
412
413         FUNCTION_TRACE_PTR ("Ds_create_index_field", op);
414
415
416         /* First arg is the name of the Index register (must already exist) */
417
418         arg = op->value.arg;
419         status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
420                           ACPI_TYPE_ANY, IMODE_EXECUTE,
421                           NS_SEARCH_PARENT, walk_state, &info.register_node);
422         if (ACPI_FAILURE (status)) {
423                 return_ACPI_STATUS (status);
424         }
425
426         /* Second arg is the data register (must already exist) */
427
428         arg = arg->next;
429         status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
430                           INTERNAL_TYPE_INDEX_FIELD_DEFN, IMODE_EXECUTE,
431                           NS_SEARCH_PARENT, walk_state, &info.data_register_node);
432         if (ACPI_FAILURE (status)) {
433                 return_ACPI_STATUS (status);
434         }
435
436         /* Next arg is the field flags */
437
438         arg = arg->next;
439         info.field_flags = arg->value.integer8;
440
441
442         /* Each remaining arg is a Named Field */
443
444         info.field_type = INTERNAL_TYPE_INDEX_FIELD;
445         info.region_node = region_node;
446
447         status = acpi_ds_get_field_names (&info, walk_state, arg->next);
448
449         return_ACPI_STATUS (status);
450 }
451
452