]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /****************************************************************************** |
2 | * | |
3 | * Module Name: dsfield - Dispatcher field routines | |
4 | * | |
5 | *****************************************************************************/ | |
6 | ||
7 | /* | |
7735ca0e | 8 | * Copyright (C) 2000 - 2017, Intel Corp. |
1da177e4 LT |
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 | ||
1da177e4 | 44 | #include <acpi/acpi.h> |
e2f7a777 LB |
45 | #include "accommon.h" |
46 | #include "amlcode.h" | |
47 | #include "acdispat.h" | |
48 | #include "acinterp.h" | |
49 | #include "acnamesp.h" | |
50 | #include "acparser.h" | |
1da177e4 | 51 | |
1da177e4 | 52 | #define _COMPONENT ACPI_DISPATCHER |
4be44fcd | 53 | ACPI_MODULE_NAME("dsfield") |
1da177e4 | 54 | |
44f6c012 | 55 | /* Local prototypes */ |
6ccd7b5a BM |
56 | #ifdef ACPI_ASL_COMPILER |
57 | #include "acdisasm.h" | |
58 | static acpi_status | |
59 | acpi_ds_create_external_region(acpi_status lookup_status, | |
60 | union acpi_parse_object *op, | |
61 | char *path, | |
62 | struct acpi_walk_state *walk_state, | |
63 | struct acpi_namespace_node **node); | |
64 | #endif | |
65 | ||
44f6c012 | 66 | static acpi_status |
4be44fcd LB |
67 | acpi_ds_get_field_names(struct acpi_create_field_info *info, |
68 | struct acpi_walk_state *walk_state, | |
69 | union acpi_parse_object *arg); | |
1da177e4 | 70 | |
6ccd7b5a BM |
71 | #ifdef ACPI_ASL_COMPILER |
72 | /******************************************************************************* | |
73 | * | |
ba494bee | 74 | * FUNCTION: acpi_ds_create_external_region (iASL Disassembler only) |
6ccd7b5a BM |
75 | * |
76 | * PARAMETERS: lookup_status - Status from ns_lookup operation | |
ba494bee BM |
77 | * op - Op containing the Field definition and args |
78 | * path - Pathname of the region | |
6ccd7b5a | 79 | * ` walk_state - Current method state |
ba494bee | 80 | * node - Where the new region node is returned |
6ccd7b5a BM |
81 | * |
82 | * RETURN: Status | |
83 | * | |
84 | * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new | |
85 | * region node/object. | |
86 | * | |
87 | ******************************************************************************/ | |
88 | ||
89 | static acpi_status | |
90 | acpi_ds_create_external_region(acpi_status lookup_status, | |
91 | union acpi_parse_object *op, | |
92 | char *path, | |
93 | struct acpi_walk_state *walk_state, | |
94 | struct acpi_namespace_node **node) | |
95 | { | |
96 | acpi_status status; | |
97 | union acpi_operand_object *obj_desc; | |
98 | ||
99 | if (lookup_status != AE_NOT_FOUND) { | |
100 | return (lookup_status); | |
101 | } | |
102 | ||
103 | /* | |
104 | * Table disassembly: | |
105 | * operation_region not found. Generate an External for it, and | |
106 | * insert the name into the namespace. | |
107 | */ | |
5af2b635 | 108 | acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0); |
1fad8738 | 109 | |
6ccd7b5a BM |
110 | status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION, |
111 | ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, | |
112 | walk_state, node); | |
113 | if (ACPI_FAILURE(status)) { | |
114 | return (status); | |
115 | } | |
116 | ||
117 | /* Must create and install a region object for the new node */ | |
118 | ||
119 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); | |
120 | if (!obj_desc) { | |
121 | return (AE_NO_MEMORY); | |
122 | } | |
123 | ||
124 | obj_desc->region.node = *node; | |
125 | status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION); | |
126 | return (status); | |
127 | } | |
128 | #endif | |
129 | ||
1da177e4 LT |
130 | /******************************************************************************* |
131 | * | |
132 | * FUNCTION: acpi_ds_create_buffer_field | |
133 | * | |
ba494bee | 134 | * PARAMETERS: op - Current parse op (create_XXField) |
1da177e4 LT |
135 | * walk_state - Current state |
136 | * | |
137 | * RETURN: Status | |
138 | * | |
139 | * DESCRIPTION: Execute the create_field operators: | |
140 | * create_bit_field_op, | |
141 | * create_byte_field_op, | |
142 | * create_word_field_op, | |
143 | * create_dword_field_op, | |
144 | * create_qword_field_op, | |
44f6c012 | 145 | * create_field_op (all of which define a field in a buffer) |
1da177e4 LT |
146 | * |
147 | ******************************************************************************/ | |
148 | ||
149 | acpi_status | |
4be44fcd LB |
150 | acpi_ds_create_buffer_field(union acpi_parse_object *op, |
151 | struct acpi_walk_state *walk_state) | |
1da177e4 | 152 | { |
4be44fcd LB |
153 | union acpi_parse_object *arg; |
154 | struct acpi_namespace_node *node; | |
155 | acpi_status status; | |
156 | union acpi_operand_object *obj_desc; | |
157 | union acpi_operand_object *second_desc = NULL; | |
158 | u32 flags; | |
1da177e4 | 159 | |
b229cf92 | 160 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); |
1da177e4 | 161 | |
cca97b81 BM |
162 | /* |
163 | * Get the name_string argument (name of the new buffer_field) | |
164 | */ | |
1da177e4 | 165 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { |
cca97b81 BM |
166 | |
167 | /* For create_field, name is the 4th argument */ | |
168 | ||
4be44fcd LB |
169 | arg = acpi_ps_get_arg(op, 3); |
170 | } else { | |
ba494bee | 171 | /* For all other create_XXXField operators, name is the 3rd argument */ |
1da177e4 | 172 | |
4be44fcd | 173 | arg = acpi_ps_get_arg(op, 2); |
1da177e4 LT |
174 | } |
175 | ||
176 | if (!arg) { | |
4be44fcd | 177 | return_ACPI_STATUS(AE_AML_NO_OPERAND); |
1da177e4 LT |
178 | } |
179 | ||
180 | if (walk_state->deferred_node) { | |
181 | node = walk_state->deferred_node; | |
182 | status = AE_OK; | |
4be44fcd | 183 | } else { |
cca97b81 BM |
184 | /* Execute flag should always be set when this function is entered */ |
185 | ||
186 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | |
376a588c | 187 | ACPI_ERROR((AE_INFO, "Parse execute mode is not set")); |
cca97b81 | 188 | return_ACPI_STATUS(AE_AML_INTERNAL); |
1da177e4 LT |
189 | } |
190 | ||
cca97b81 BM |
191 | /* Creating new namespace node, should not already exist */ |
192 | ||
193 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | |
194 | ACPI_NS_ERROR_IF_FOUND; | |
195 | ||
7f0c826a LM |
196 | /* |
197 | * Mark node temporary if we are executing a normal control | |
198 | * method. (Don't mark if this is a module-level code method) | |
199 | */ | |
200 | if (walk_state->method_node && | |
201 | !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | |
cca97b81 BM |
202 | flags |= ACPI_NS_TEMPORARY; |
203 | } | |
204 | ||
205 | /* Enter the name_string into the namespace */ | |
206 | ||
1fad8738 BM |
207 | status = acpi_ns_lookup(walk_state->scope_info, |
208 | arg->common.value.string, ACPI_TYPE_ANY, | |
209 | ACPI_IMODE_LOAD_PASS1, flags, | |
210 | walk_state, &node); | |
4be44fcd | 211 | if (ACPI_FAILURE(status)) { |
b8e4d893 | 212 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); |
4be44fcd | 213 | return_ACPI_STATUS(status); |
1da177e4 LT |
214 | } |
215 | } | |
216 | ||
9c52657a BM |
217 | /* |
218 | * We could put the returned object (Node) on the object stack for later, | |
44f6c012 | 219 | * but for now, we will put it in the "op" object that the parser uses, |
cca97b81 | 220 | * so we can get it again at the end of this scope. |
1da177e4 LT |
221 | */ |
222 | op->common.node = node; | |
223 | ||
224 | /* | |
44f6c012 | 225 | * If there is no object attached to the node, this node was just created |
cca97b81 | 226 | * and we need to create the field object. Otherwise, this was a lookup |
44f6c012 | 227 | * of an existing node and we don't want to create the field object again. |
1da177e4 | 228 | */ |
4be44fcd | 229 | obj_desc = acpi_ns_get_attached_object(node); |
1da177e4 | 230 | if (obj_desc) { |
4be44fcd | 231 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
232 | } |
233 | ||
234 | /* | |
235 | * The Field definition is not fully parsed at this time. | |
236 | * (We must save the address of the AML for the buffer and index operands) | |
237 | */ | |
238 | ||
239 | /* Create the buffer field object */ | |
240 | ||
4be44fcd | 241 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); |
1da177e4 LT |
242 | if (!obj_desc) { |
243 | status = AE_NO_MEMORY; | |
244 | goto cleanup; | |
245 | } | |
246 | ||
247 | /* | |
1fad8738 BM |
248 | * Remember location in AML stream of the field unit opcode and operands |
249 | * -- since the buffer and index operands must be evaluated. | |
1da177e4 | 250 | */ |
4be44fcd | 251 | second_desc = obj_desc->common.next_object; |
1da177e4 LT |
252 | second_desc->extra.aml_start = op->named.data; |
253 | second_desc->extra.aml_length = op->named.length; | |
254 | obj_desc->buffer_field.node = node; | |
255 | ||
256 | /* Attach constructed field descriptors to parent node */ | |
257 | ||
4be44fcd LB |
258 | status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); |
259 | if (ACPI_FAILURE(status)) { | |
1da177e4 LT |
260 | goto cleanup; |
261 | } | |
262 | ||
10622bf8 | 263 | cleanup: |
1da177e4 LT |
264 | |
265 | /* Remove local reference to the object */ | |
266 | ||
4be44fcd LB |
267 | acpi_ut_remove_reference(obj_desc); |
268 | return_ACPI_STATUS(status); | |
1da177e4 LT |
269 | } |
270 | ||
1da177e4 LT |
271 | /******************************************************************************* |
272 | * | |
273 | * FUNCTION: acpi_ds_get_field_names | |
274 | * | |
ba494bee | 275 | * PARAMETERS: info - create_field info structure |
1da177e4 | 276 | * ` walk_state - Current method state |
ba494bee | 277 | * arg - First parser arg for the field name list |
1da177e4 LT |
278 | * |
279 | * RETURN: Status | |
280 | * | |
73a3090a | 281 | * DESCRIPTION: Process all named fields in a field declaration. Names are |
1da177e4 LT |
282 | * entered into the namespace. |
283 | * | |
284 | ******************************************************************************/ | |
285 | ||
44f6c012 | 286 | static acpi_status |
4be44fcd LB |
287 | acpi_ds_get_field_names(struct acpi_create_field_info *info, |
288 | struct acpi_walk_state *walk_state, | |
289 | union acpi_parse_object *arg) | |
1da177e4 | 290 | { |
4be44fcd | 291 | acpi_status status; |
5df7e6cb | 292 | u64 position; |
9ce81784 | 293 | union acpi_parse_object *child; |
1da177e4 | 294 | |
b229cf92 | 295 | ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); |
1da177e4 LT |
296 | |
297 | /* First field starts at bit zero */ | |
298 | ||
299 | info->field_bit_position = 0; | |
300 | ||
301 | /* Process all elements in the field list (of parse nodes) */ | |
302 | ||
303 | while (arg) { | |
304 | /* | |
9ce81784 | 305 | * Four types of field elements are handled: |
ba494bee BM |
306 | * 1) name - Enters a new named field into the namespace |
307 | * 2) offset - specifies a bit offset | |
9ce81784 | 308 | * 3) access_as - changes the access mode/attributes |
ba494bee | 309 | * 4) connection - Associate a resource template with the field |
1da177e4 LT |
310 | */ |
311 | switch (arg->common.aml_opcode) { | |
312 | case AML_INT_RESERVEDFIELD_OP: | |
313 | ||
1fad8738 BM |
314 | position = (u64)info->field_bit_position + |
315 | (u64)arg->common.value.size; | |
1da177e4 LT |
316 | |
317 | if (position > ACPI_UINT32_MAX) { | |
b8e4d893 BM |
318 | ACPI_ERROR((AE_INFO, |
319 | "Bit offset within field too large (> 0xFFFFFFFF)")); | |
4be44fcd | 320 | return_ACPI_STATUS(AE_SUPPORT); |
1da177e4 LT |
321 | } |
322 | ||
323 | info->field_bit_position = (u32) position; | |
324 | break; | |
325 | ||
1da177e4 | 326 | case AML_INT_ACCESSFIELD_OP: |
9ce81784 | 327 | case AML_INT_EXTACCESSFIELD_OP: |
1da177e4 | 328 | /* |
9ce81784 BM |
329 | * Get new access_type, access_attribute, and access_length fields |
330 | * -- to be used for all field units that follow, until the | |
331 | * end-of-field or another access_as keyword is encountered. | |
332 | * NOTE. These three bytes are encoded in the integer value | |
333 | * of the parseop for convenience. | |
1da177e4 | 334 | * |
44f6c012 | 335 | * In field_flags, preserve the flag bits other than the |
9ce81784 | 336 | * ACCESS_TYPE bits. |
1da177e4 | 337 | */ |
9ce81784 BM |
338 | |
339 | /* access_type (byte_acc, word_acc, etc.) */ | |
340 | ||
44f6c012 | 341 | info->field_flags = (u8) |
4be44fcd LB |
342 | ((info-> |
343 | field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | | |
9ce81784 BM |
344 | ((u8)((u32)(arg->common.value.integer & 0x07)))); |
345 | ||
346 | /* access_attribute (attrib_quick, attrib_byte, etc.) */ | |
347 | ||
1fad8738 BM |
348 | info->attribute = (u8) |
349 | ((arg->common.value.integer >> 8) & 0xFF); | |
9ce81784 BM |
350 | |
351 | /* access_length (for serial/buffer protocols) */ | |
352 | ||
1fad8738 BM |
353 | info->access_length = (u8) |
354 | ((arg->common.value.integer >> 16) & 0xFF); | |
9ce81784 BM |
355 | break; |
356 | ||
357 | case AML_INT_CONNECTION_OP: | |
358 | /* | |
359 | * Clear any previous connection. New connection is used for all | |
360 | * fields that follow, similar to access_as | |
361 | */ | |
362 | info->resource_buffer = NULL; | |
363 | info->connection_node = NULL; | |
75ec6e55 | 364 | info->pin_number_index = 0; |
1da177e4 | 365 | |
9ce81784 BM |
366 | /* |
367 | * A Connection() is either an actual resource descriptor (buffer) | |
368 | * or a named reference to a resource template | |
369 | */ | |
370 | child = arg->common.value.arg; | |
371 | if (child->common.aml_opcode == AML_INT_BYTELIST_OP) { | |
372 | info->resource_buffer = child->named.data; | |
373 | info->resource_length = | |
374 | (u16)child->named.value.integer; | |
375 | } else { | |
376 | /* Lookup the Connection() namepath, it should already exist */ | |
377 | ||
378 | status = acpi_ns_lookup(walk_state->scope_info, | |
379 | child->common.value. | |
380 | name, ACPI_TYPE_ANY, | |
381 | ACPI_IMODE_EXECUTE, | |
382 | ACPI_NS_DONT_OPEN_SCOPE, | |
383 | walk_state, | |
384 | &info->connection_node); | |
385 | if (ACPI_FAILURE(status)) { | |
386 | ACPI_ERROR_NAMESPACE(child->common. | |
387 | value.name, | |
388 | status); | |
389 | return_ACPI_STATUS(status); | |
390 | } | |
391 | } | |
1da177e4 LT |
392 | break; |
393 | ||
1da177e4 LT |
394 | case AML_INT_NAMEDFIELD_OP: |
395 | ||
cca97b81 | 396 | /* Lookup the name, it should already exist */ |
1da177e4 | 397 | |
4be44fcd LB |
398 | status = acpi_ns_lookup(walk_state->scope_info, |
399 | (char *)&arg->named.name, | |
400 | info->field_type, | |
401 | ACPI_IMODE_EXECUTE, | |
402 | ACPI_NS_DONT_OPEN_SCOPE, | |
403 | walk_state, &info->field_node); | |
404 | if (ACPI_FAILURE(status)) { | |
b8e4d893 BM |
405 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, |
406 | status); | |
cca97b81 | 407 | return_ACPI_STATUS(status); |
4be44fcd | 408 | } else { |
1da177e4 LT |
409 | arg->common.node = info->field_node; |
410 | info->field_bit_length = arg->common.value.size; | |
411 | ||
ef805d95 | 412 | /* |
cca97b81 BM |
413 | * If there is no object attached to the node, this node was |
414 | * just created and we need to create the field object. | |
415 | * Otherwise, this was a lookup of an existing node and we | |
416 | * don't want to create the field object again. | |
ef805d95 LM |
417 | */ |
418 | if (!acpi_ns_get_attached_object | |
419 | (info->field_node)) { | |
420 | status = acpi_ex_prep_field_value(info); | |
421 | if (ACPI_FAILURE(status)) { | |
422 | return_ACPI_STATUS(status); | |
423 | } | |
1da177e4 LT |
424 | } |
425 | } | |
426 | ||
427 | /* Keep track of bit position for the next field */ | |
428 | ||
1fad8738 BM |
429 | position = (u64)info->field_bit_position + |
430 | (u64)arg->common.value.size; | |
1da177e4 LT |
431 | |
432 | if (position > ACPI_UINT32_MAX) { | |
b8e4d893 BM |
433 | ACPI_ERROR((AE_INFO, |
434 | "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", | |
435 | ACPI_CAST_PTR(char, | |
436 | &info->field_node-> | |
437 | name))); | |
4be44fcd | 438 | return_ACPI_STATUS(AE_SUPPORT); |
1da177e4 LT |
439 | } |
440 | ||
441 | info->field_bit_position += info->field_bit_length; | |
75ec6e55 | 442 | info->pin_number_index++; /* Index relative to previous Connection() */ |
1da177e4 LT |
443 | break; |
444 | ||
1da177e4 LT |
445 | default: |
446 | ||
b8e4d893 | 447 | ACPI_ERROR((AE_INFO, |
f6a22b0b | 448 | "Invalid opcode in field list: 0x%X", |
b8e4d893 | 449 | arg->common.aml_opcode)); |
4be44fcd | 450 | return_ACPI_STATUS(AE_AML_BAD_OPCODE); |
1da177e4 LT |
451 | } |
452 | ||
453 | arg = arg->common.next; | |
454 | } | |
455 | ||
4be44fcd | 456 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
457 | } |
458 | ||
1da177e4 LT |
459 | /******************************************************************************* |
460 | * | |
461 | * FUNCTION: acpi_ds_create_field | |
462 | * | |
ba494bee | 463 | * PARAMETERS: op - Op containing the Field definition and args |
1da177e4 LT |
464 | * region_node - Object for the containing Operation Region |
465 | * ` walk_state - Current method state | |
466 | * | |
467 | * RETURN: Status | |
468 | * | |
469 | * DESCRIPTION: Create a new field in the specified operation region | |
470 | * | |
471 | ******************************************************************************/ | |
472 | ||
473 | acpi_status | |
4be44fcd LB |
474 | acpi_ds_create_field(union acpi_parse_object *op, |
475 | struct acpi_namespace_node *region_node, | |
476 | struct acpi_walk_state *walk_state) | |
1da177e4 | 477 | { |
4be44fcd LB |
478 | acpi_status status; |
479 | union acpi_parse_object *arg; | |
480 | struct acpi_create_field_info info; | |
1da177e4 | 481 | |
b229cf92 | 482 | ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); |
1da177e4 LT |
483 | |
484 | /* First arg is the name of the parent op_region (must already exist) */ | |
485 | ||
486 | arg = op->common.value.arg; | |
6ccd7b5a | 487 | |
1da177e4 | 488 | if (!region_node) { |
4be44fcd LB |
489 | status = |
490 | acpi_ns_lookup(walk_state->scope_info, | |
491 | arg->common.value.name, ACPI_TYPE_REGION, | |
492 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | |
493 | walk_state, ®ion_node); | |
6ccd7b5a BM |
494 | #ifdef ACPI_ASL_COMPILER |
495 | status = acpi_ds_create_external_region(status, arg, | |
496 | arg->common.value.name, | |
497 | walk_state, | |
498 | ®ion_node); | |
499 | #endif | |
4be44fcd | 500 | if (ACPI_FAILURE(status)) { |
b8e4d893 | 501 | ACPI_ERROR_NAMESPACE(arg->common.value.name, status); |
4be44fcd | 502 | return_ACPI_STATUS(status); |
1da177e4 LT |
503 | } |
504 | } | |
505 | ||
4fa4616e | 506 | memset(&info, 0, sizeof(struct acpi_create_field_info)); |
9ce81784 | 507 | |
1da177e4 LT |
508 | /* Second arg is the field flags */ |
509 | ||
510 | arg = arg->common.next; | |
511 | info.field_flags = (u8) arg->common.value.integer; | |
512 | info.attribute = 0; | |
513 | ||
514 | /* Each remaining arg is a Named Field */ | |
515 | ||
516 | info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; | |
517 | info.region_node = region_node; | |
518 | ||
4be44fcd | 519 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); |
4be44fcd | 520 | return_ACPI_STATUS(status); |
1da177e4 LT |
521 | } |
522 | ||
1da177e4 LT |
523 | /******************************************************************************* |
524 | * | |
525 | * FUNCTION: acpi_ds_init_field_objects | |
526 | * | |
ba494bee | 527 | * PARAMETERS: op - Op containing the Field definition and args |
1da177e4 LT |
528 | * ` walk_state - Current method state |
529 | * | |
530 | * RETURN: Status | |
531 | * | |
532 | * DESCRIPTION: For each "Field Unit" name in the argument list that is | |
533 | * part of the field declaration, enter the name into the | |
534 | * namespace. | |
535 | * | |
536 | ******************************************************************************/ | |
537 | ||
538 | acpi_status | |
4be44fcd LB |
539 | acpi_ds_init_field_objects(union acpi_parse_object *op, |
540 | struct acpi_walk_state *walk_state) | |
1da177e4 | 541 | { |
4be44fcd LB |
542 | acpi_status status; |
543 | union acpi_parse_object *arg = NULL; | |
544 | struct acpi_namespace_node *node; | |
545 | u8 type = 0; | |
ef805d95 | 546 | u32 flags; |
1da177e4 | 547 | |
b229cf92 | 548 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); |
1da177e4 | 549 | |
cca97b81 BM |
550 | /* Execute flag should always be set when this function is entered */ |
551 | ||
552 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | |
553 | if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { | |
554 | ||
555 | /* bank_field Op is deferred, just return OK */ | |
556 | ||
557 | return_ACPI_STATUS(AE_OK); | |
558 | } | |
559 | ||
376a588c | 560 | ACPI_ERROR((AE_INFO, "Parse deferred mode is not set")); |
cca97b81 | 561 | return_ACPI_STATUS(AE_AML_INTERNAL); |
ef805d95 LM |
562 | } |
563 | ||
cca97b81 BM |
564 | /* |
565 | * Get the field_list argument for this opcode. This is the start of the | |
566 | * list of field elements. | |
567 | */ | |
1da177e4 LT |
568 | switch (walk_state->opcode) { |
569 | case AML_FIELD_OP: | |
1d1ea1b7 | 570 | |
4be44fcd | 571 | arg = acpi_ps_get_arg(op, 2); |
1da177e4 LT |
572 | type = ACPI_TYPE_LOCAL_REGION_FIELD; |
573 | break; | |
574 | ||
575 | case AML_BANK_FIELD_OP: | |
1d1ea1b7 | 576 | |
4be44fcd | 577 | arg = acpi_ps_get_arg(op, 4); |
1da177e4 LT |
578 | type = ACPI_TYPE_LOCAL_BANK_FIELD; |
579 | break; | |
580 | ||
581 | case AML_INDEX_FIELD_OP: | |
1d1ea1b7 | 582 | |
4be44fcd | 583 | arg = acpi_ps_get_arg(op, 3); |
1da177e4 LT |
584 | type = ACPI_TYPE_LOCAL_INDEX_FIELD; |
585 | break; | |
586 | ||
587 | default: | |
1d1ea1b7 | 588 | |
4be44fcd | 589 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
1da177e4 LT |
590 | } |
591 | ||
cca97b81 BM |
592 | /* Creating new namespace node(s), should not already exist */ |
593 | ||
594 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | |
595 | ACPI_NS_ERROR_IF_FOUND; | |
596 | ||
7f0c826a LM |
597 | /* |
598 | * Mark node(s) temporary if we are executing a normal control | |
599 | * method. (Don't mark if this is a module-level code method) | |
600 | */ | |
601 | if (walk_state->method_node && | |
602 | !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | |
cca97b81 BM |
603 | flags |= ACPI_NS_TEMPORARY; |
604 | } | |
605 | ||
1da177e4 LT |
606 | /* |
607 | * Walk the list of entries in the field_list | |
7aa7d433 | 608 | * Note: field_list can be of zero length. In this case, Arg will be NULL. |
1da177e4 LT |
609 | */ |
610 | while (arg) { | |
cca97b81 | 611 | /* |
9ce81784 BM |
612 | * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested |
613 | * in the field names in order to enter them into the namespace. | |
cca97b81 | 614 | */ |
1da177e4 | 615 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { |
4be44fcd | 616 | status = acpi_ns_lookup(walk_state->scope_info, |
cca97b81 BM |
617 | (char *)&arg->named.name, type, |
618 | ACPI_IMODE_LOAD_PASS1, flags, | |
619 | walk_state, &node); | |
4be44fcd | 620 | if (ACPI_FAILURE(status)) { |
b8e4d893 BM |
621 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, |
622 | status); | |
1da177e4 | 623 | if (status != AE_ALREADY_EXISTS) { |
4be44fcd | 624 | return_ACPI_STATUS(status); |
1da177e4 LT |
625 | } |
626 | ||
627 | /* Name already exists, just ignore this error */ | |
628 | ||
629 | status = AE_OK; | |
630 | } | |
631 | ||
632 | arg->common.node = node; | |
633 | } | |
634 | ||
cca97b81 | 635 | /* Get the next field element in the list */ |
1da177e4 LT |
636 | |
637 | arg = arg->common.next; | |
638 | } | |
639 | ||
4be44fcd | 640 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
641 | } |
642 | ||
1da177e4 LT |
643 | /******************************************************************************* |
644 | * | |
645 | * FUNCTION: acpi_ds_create_bank_field | |
646 | * | |
ba494bee | 647 | * PARAMETERS: op - Op containing the Field definition and args |
1da177e4 | 648 | * region_node - Object for the containing Operation Region |
ef805d95 | 649 | * walk_state - Current method state |
1da177e4 LT |
650 | * |
651 | * RETURN: Status | |
652 | * | |
653 | * DESCRIPTION: Create a new bank field in the specified operation region | |
654 | * | |
655 | ******************************************************************************/ | |
656 | ||
657 | acpi_status | |
4be44fcd LB |
658 | acpi_ds_create_bank_field(union acpi_parse_object *op, |
659 | struct acpi_namespace_node *region_node, | |
660 | struct acpi_walk_state *walk_state) | |
1da177e4 | 661 | { |
4be44fcd LB |
662 | acpi_status status; |
663 | union acpi_parse_object *arg; | |
664 | struct acpi_create_field_info info; | |
1da177e4 | 665 | |
b229cf92 | 666 | ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); |
1da177e4 LT |
667 | |
668 | /* First arg is the name of the parent op_region (must already exist) */ | |
669 | ||
670 | arg = op->common.value.arg; | |
671 | if (!region_node) { | |
4be44fcd LB |
672 | status = |
673 | acpi_ns_lookup(walk_state->scope_info, | |
674 | arg->common.value.name, ACPI_TYPE_REGION, | |
675 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | |
676 | walk_state, ®ion_node); | |
6ccd7b5a BM |
677 | #ifdef ACPI_ASL_COMPILER |
678 | status = acpi_ds_create_external_region(status, arg, | |
679 | arg->common.value.name, | |
680 | walk_state, | |
681 | ®ion_node); | |
682 | #endif | |
4be44fcd | 683 | if (ACPI_FAILURE(status)) { |
b8e4d893 | 684 | ACPI_ERROR_NAMESPACE(arg->common.value.name, status); |
4be44fcd | 685 | return_ACPI_STATUS(status); |
1da177e4 LT |
686 | } |
687 | } | |
688 | ||
689 | /* Second arg is the Bank Register (Field) (must already exist) */ | |
690 | ||
691 | arg = arg->common.next; | |
4be44fcd LB |
692 | status = |
693 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | |
694 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | |
695 | ACPI_NS_SEARCH_PARENT, walk_state, | |
696 | &info.register_node); | |
697 | if (ACPI_FAILURE(status)) { | |
b8e4d893 | 698 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); |
4be44fcd | 699 | return_ACPI_STATUS(status); |
1da177e4 LT |
700 | } |
701 | ||
ef805d95 LM |
702 | /* |
703 | * Third arg is the bank_value | |
704 | * This arg is a term_arg, not a constant | |
705 | * It will be evaluated later, by acpi_ds_eval_bank_field_operands | |
706 | */ | |
1da177e4 | 707 | arg = arg->common.next; |
9c52657a | 708 | |
1da177e4 LT |
709 | /* Fourth arg is the field flags */ |
710 | ||
711 | arg = arg->common.next; | |
712 | info.field_flags = (u8) arg->common.value.integer; | |
713 | ||
714 | /* Each remaining arg is a Named Field */ | |
715 | ||
716 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; | |
717 | info.region_node = region_node; | |
718 | ||
ef805d95 LM |
719 | /* |
720 | * Use Info.data_register_node to store bank_field Op | |
1fad8738 BM |
721 | * It's safe because data_register_node will never be used when create |
722 | * bank field \we store aml_start and aml_length in the bank_field Op for | |
723 | * late evaluation. Used in acpi_ex_prep_field_value(Info) | |
ef805d95 | 724 | * |
1fad8738 BM |
725 | * TBD: Or, should we add a field in struct acpi_create_field_info, like |
726 | * "void *ParentOp"? | |
ef805d95 LM |
727 | */ |
728 | info.data_register_node = (struct acpi_namespace_node *)op; | |
1da177e4 | 729 | |
ef805d95 | 730 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); |
4be44fcd | 731 | return_ACPI_STATUS(status); |
1da177e4 LT |
732 | } |
733 | ||
1da177e4 LT |
734 | /******************************************************************************* |
735 | * | |
736 | * FUNCTION: acpi_ds_create_index_field | |
737 | * | |
ba494bee | 738 | * PARAMETERS: op - Op containing the Field definition and args |
1da177e4 LT |
739 | * region_node - Object for the containing Operation Region |
740 | * ` walk_state - Current method state | |
741 | * | |
742 | * RETURN: Status | |
743 | * | |
744 | * DESCRIPTION: Create a new index field in the specified operation region | |
745 | * | |
746 | ******************************************************************************/ | |
747 | ||
748 | acpi_status | |
4be44fcd LB |
749 | acpi_ds_create_index_field(union acpi_parse_object *op, |
750 | struct acpi_namespace_node *region_node, | |
751 | struct acpi_walk_state *walk_state) | |
1da177e4 | 752 | { |
4be44fcd LB |
753 | acpi_status status; |
754 | union acpi_parse_object *arg; | |
755 | struct acpi_create_field_info info; | |
1da177e4 | 756 | |
b229cf92 | 757 | ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); |
1da177e4 LT |
758 | |
759 | /* First arg is the name of the Index register (must already exist) */ | |
760 | ||
761 | arg = op->common.value.arg; | |
4be44fcd LB |
762 | status = |
763 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | |
764 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | |
765 | ACPI_NS_SEARCH_PARENT, walk_state, | |
766 | &info.register_node); | |
767 | if (ACPI_FAILURE(status)) { | |
b8e4d893 | 768 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); |
4be44fcd | 769 | return_ACPI_STATUS(status); |
1da177e4 LT |
770 | } |
771 | ||
772 | /* Second arg is the data register (must already exist) */ | |
773 | ||
774 | arg = arg->common.next; | |
4be44fcd LB |
775 | status = |
776 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | |
777 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | |
778 | ACPI_NS_SEARCH_PARENT, walk_state, | |
779 | &info.data_register_node); | |
780 | if (ACPI_FAILURE(status)) { | |
b8e4d893 | 781 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); |
4be44fcd | 782 | return_ACPI_STATUS(status); |
1da177e4 LT |
783 | } |
784 | ||
785 | /* Next arg is the field flags */ | |
786 | ||
787 | arg = arg->common.next; | |
788 | info.field_flags = (u8) arg->common.value.integer; | |
789 | ||
790 | /* Each remaining arg is a Named Field */ | |
791 | ||
792 | info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; | |
793 | info.region_node = region_node; | |
794 | ||
4be44fcd | 795 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); |
4be44fcd | 796 | return_ACPI_STATUS(status); |
1da177e4 | 797 | } |