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