162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: dsfield - Dispatcher field routines 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "amlcode.h" 1362306a36Sopenharmony_ci#include "acdispat.h" 1462306a36Sopenharmony_ci#include "acinterp.h" 1562306a36Sopenharmony_ci#include "acnamesp.h" 1662306a36Sopenharmony_ci#include "acparser.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#ifdef ACPI_EXEC_APP 1962306a36Sopenharmony_ci#include "aecommon.h" 2062306a36Sopenharmony_ci#endif 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define _COMPONENT ACPI_DISPATCHER 2362306a36Sopenharmony_ciACPI_MODULE_NAME("dsfield") 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* Local prototypes */ 2662306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 2762306a36Sopenharmony_ci#include "acdisasm.h" 2862306a36Sopenharmony_cistatic acpi_status 2962306a36Sopenharmony_ciacpi_ds_create_external_region(acpi_status lookup_status, 3062306a36Sopenharmony_ci union acpi_parse_object *op, 3162306a36Sopenharmony_ci char *path, 3262306a36Sopenharmony_ci struct acpi_walk_state *walk_state, 3362306a36Sopenharmony_ci struct acpi_namespace_node **node); 3462306a36Sopenharmony_ci#endif 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic acpi_status 3762306a36Sopenharmony_ciacpi_ds_get_field_names(struct acpi_create_field_info *info, 3862306a36Sopenharmony_ci struct acpi_walk_state *walk_state, 3962306a36Sopenharmony_ci union acpi_parse_object *arg); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 4262306a36Sopenharmony_ci/******************************************************************************* 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * FUNCTION: acpi_ds_create_external_region (iASL Disassembler only) 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * PARAMETERS: lookup_status - Status from ns_lookup operation 4762306a36Sopenharmony_ci * op - Op containing the Field definition and args 4862306a36Sopenharmony_ci * path - Pathname of the region 4962306a36Sopenharmony_ci * ` walk_state - Current method state 5062306a36Sopenharmony_ci * node - Where the new region node is returned 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * RETURN: Status 5362306a36Sopenharmony_ci * 5462306a36Sopenharmony_ci * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new 5562306a36Sopenharmony_ci * region node/object. 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci ******************************************************************************/ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic acpi_status 6062306a36Sopenharmony_ciacpi_ds_create_external_region(acpi_status lookup_status, 6162306a36Sopenharmony_ci union acpi_parse_object *op, 6262306a36Sopenharmony_ci char *path, 6362306a36Sopenharmony_ci struct acpi_walk_state *walk_state, 6462306a36Sopenharmony_ci struct acpi_namespace_node **node) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci acpi_status status; 6762306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci if (lookup_status != AE_NOT_FOUND) { 7062306a36Sopenharmony_ci return (lookup_status); 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* 7462306a36Sopenharmony_ci * Table disassembly: 7562306a36Sopenharmony_ci * operation_region not found. Generate an External for it, and 7662306a36Sopenharmony_ci * insert the name into the namespace. 7762306a36Sopenharmony_ci */ 7862306a36Sopenharmony_ci acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION, 8162306a36Sopenharmony_ci ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, 8262306a36Sopenharmony_ci walk_state, node); 8362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 8462306a36Sopenharmony_ci return (status); 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci /* Must create and install a region object for the new node */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); 9062306a36Sopenharmony_ci if (!obj_desc) { 9162306a36Sopenharmony_ci return (AE_NO_MEMORY); 9262306a36Sopenharmony_ci } 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci obj_desc->region.node = *node; 9562306a36Sopenharmony_ci status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION); 9662306a36Sopenharmony_ci return (status); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci#endif 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci/******************************************************************************* 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * FUNCTION: acpi_ds_create_buffer_field 10362306a36Sopenharmony_ci * 10462306a36Sopenharmony_ci * PARAMETERS: op - Current parse op (create_XXField) 10562306a36Sopenharmony_ci * walk_state - Current state 10662306a36Sopenharmony_ci * 10762306a36Sopenharmony_ci * RETURN: Status 10862306a36Sopenharmony_ci * 10962306a36Sopenharmony_ci * DESCRIPTION: Execute the create_field operators: 11062306a36Sopenharmony_ci * create_bit_field_op, 11162306a36Sopenharmony_ci * create_byte_field_op, 11262306a36Sopenharmony_ci * create_word_field_op, 11362306a36Sopenharmony_ci * create_dword_field_op, 11462306a36Sopenharmony_ci * create_qword_field_op, 11562306a36Sopenharmony_ci * create_field_op (all of which define a field in a buffer) 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci ******************************************************************************/ 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciacpi_status 12062306a36Sopenharmony_ciacpi_ds_create_buffer_field(union acpi_parse_object *op, 12162306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci union acpi_parse_object *arg; 12462306a36Sopenharmony_ci struct acpi_namespace_node *node; 12562306a36Sopenharmony_ci acpi_status status; 12662306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 12762306a36Sopenharmony_ci union acpi_operand_object *second_desc = NULL; 12862306a36Sopenharmony_ci u32 flags; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ds_create_buffer_field); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* 13362306a36Sopenharmony_ci * Get the name_string argument (name of the new buffer_field) 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* For create_field, name is the 4th argument */ 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci arg = acpi_ps_get_arg(op, 3); 14062306a36Sopenharmony_ci } else { 14162306a36Sopenharmony_ci /* For all other create_XXXField operators, name is the 3rd argument */ 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci arg = acpi_ps_get_arg(op, 2); 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (!arg) { 14762306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_NO_OPERAND); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci if (walk_state->deferred_node) { 15162306a36Sopenharmony_ci node = walk_state->deferred_node; 15262306a36Sopenharmony_ci } else { 15362306a36Sopenharmony_ci /* Execute flag should always be set when this function is entered */ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { 15662306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Parse execute mode is not set")); 15762306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_INTERNAL); 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci /* Creating new namespace node, should not already exist */ 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 16362306a36Sopenharmony_ci ACPI_NS_ERROR_IF_FOUND; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* 16662306a36Sopenharmony_ci * Mark node temporary if we are executing a normal control 16762306a36Sopenharmony_ci * method. (Don't mark if this is a module-level code method) 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_ci if (walk_state->method_node && 17062306a36Sopenharmony_ci !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { 17162306a36Sopenharmony_ci flags |= ACPI_NS_TEMPORARY; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* Enter the name_string into the namespace */ 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci status = acpi_ns_lookup(walk_state->scope_info, 17762306a36Sopenharmony_ci arg->common.value.string, ACPI_TYPE_ANY, 17862306a36Sopenharmony_ci ACPI_IMODE_LOAD_PASS1, flags, 17962306a36Sopenharmony_ci walk_state, &node); 18062306a36Sopenharmony_ci if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) 18162306a36Sopenharmony_ci && status == AE_ALREADY_EXISTS) { 18262306a36Sopenharmony_ci status = AE_OK; 18362306a36Sopenharmony_ci } else if (ACPI_FAILURE(status)) { 18462306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 18562306a36Sopenharmony_ci arg->common.value.string, status); 18662306a36Sopenharmony_ci return_ACPI_STATUS(status); 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* 19162306a36Sopenharmony_ci * We could put the returned object (Node) on the object stack for later, 19262306a36Sopenharmony_ci * but for now, we will put it in the "op" object that the parser uses, 19362306a36Sopenharmony_ci * so we can get it again at the end of this scope. 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_ci op->common.node = node; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* 19862306a36Sopenharmony_ci * If there is no object attached to the node, this node was just created 19962306a36Sopenharmony_ci * and we need to create the field object. Otherwise, this was a lookup 20062306a36Sopenharmony_ci * of an existing node and we don't want to create the field object again. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci obj_desc = acpi_ns_get_attached_object(node); 20362306a36Sopenharmony_ci if (obj_desc) { 20462306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* 20862306a36Sopenharmony_ci * The Field definition is not fully parsed at this time. 20962306a36Sopenharmony_ci * (We must save the address of the AML for the buffer and index operands) 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* Create the buffer field object */ 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); 21562306a36Sopenharmony_ci if (!obj_desc) { 21662306a36Sopenharmony_ci status = AE_NO_MEMORY; 21762306a36Sopenharmony_ci goto cleanup; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* 22162306a36Sopenharmony_ci * Remember location in AML stream of the field unit opcode and operands 22262306a36Sopenharmony_ci * -- since the buffer and index operands must be evaluated. 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci second_desc = obj_desc->common.next_object; 22562306a36Sopenharmony_ci second_desc->extra.aml_start = op->named.data; 22662306a36Sopenharmony_ci second_desc->extra.aml_length = op->named.length; 22762306a36Sopenharmony_ci obj_desc->buffer_field.node = node; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Attach constructed field descriptors to parent node */ 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); 23262306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 23362306a36Sopenharmony_ci goto cleanup; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cicleanup: 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* Remove local reference to the object */ 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci acpi_ut_remove_reference(obj_desc); 24162306a36Sopenharmony_ci return_ACPI_STATUS(status); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci/******************************************************************************* 24562306a36Sopenharmony_ci * 24662306a36Sopenharmony_ci * FUNCTION: acpi_ds_get_field_names 24762306a36Sopenharmony_ci * 24862306a36Sopenharmony_ci * PARAMETERS: info - create_field info structure 24962306a36Sopenharmony_ci * walk_state - Current method state 25062306a36Sopenharmony_ci * arg - First parser arg for the field name list 25162306a36Sopenharmony_ci * 25262306a36Sopenharmony_ci * RETURN: Status 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * DESCRIPTION: Process all named fields in a field declaration. Names are 25562306a36Sopenharmony_ci * entered into the namespace. 25662306a36Sopenharmony_ci * 25762306a36Sopenharmony_ci ******************************************************************************/ 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic acpi_status 26062306a36Sopenharmony_ciacpi_ds_get_field_names(struct acpi_create_field_info *info, 26162306a36Sopenharmony_ci struct acpi_walk_state *walk_state, 26262306a36Sopenharmony_ci union acpi_parse_object *arg) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci acpi_status status; 26562306a36Sopenharmony_ci u64 position; 26662306a36Sopenharmony_ci union acpi_parse_object *child; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci#ifdef ACPI_EXEC_APP 26962306a36Sopenharmony_ci union acpi_operand_object *result_desc; 27062306a36Sopenharmony_ci union acpi_operand_object *obj_desc; 27162306a36Sopenharmony_ci char *name_path; 27262306a36Sopenharmony_ci#endif 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* First field starts at bit zero */ 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci info->field_bit_position = 0; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* Process all elements in the field list (of parse nodes) */ 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci while (arg) { 28362306a36Sopenharmony_ci /* 28462306a36Sopenharmony_ci * Four types of field elements are handled: 28562306a36Sopenharmony_ci * 1) name - Enters a new named field into the namespace 28662306a36Sopenharmony_ci * 2) offset - specifies a bit offset 28762306a36Sopenharmony_ci * 3) access_as - changes the access mode/attributes 28862306a36Sopenharmony_ci * 4) connection - Associate a resource template with the field 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_ci switch (arg->common.aml_opcode) { 29162306a36Sopenharmony_ci case AML_INT_RESERVEDFIELD_OP: 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci position = (u64)info->field_bit_position + 29462306a36Sopenharmony_ci (u64)arg->common.value.size; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci if (position > ACPI_UINT32_MAX) { 29762306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 29862306a36Sopenharmony_ci "Bit offset within field too large (> 0xFFFFFFFF)")); 29962306a36Sopenharmony_ci return_ACPI_STATUS(AE_SUPPORT); 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci info->field_bit_position = (u32) position; 30362306a36Sopenharmony_ci break; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci case AML_INT_ACCESSFIELD_OP: 30662306a36Sopenharmony_ci case AML_INT_EXTACCESSFIELD_OP: 30762306a36Sopenharmony_ci /* 30862306a36Sopenharmony_ci * Get new access_type, access_attribute, and access_length fields 30962306a36Sopenharmony_ci * -- to be used for all field units that follow, until the 31062306a36Sopenharmony_ci * end-of-field or another access_as keyword is encountered. 31162306a36Sopenharmony_ci * NOTE. These three bytes are encoded in the integer value 31262306a36Sopenharmony_ci * of the parseop for convenience. 31362306a36Sopenharmony_ci * 31462306a36Sopenharmony_ci * In field_flags, preserve the flag bits other than the 31562306a36Sopenharmony_ci * ACCESS_TYPE bits. 31662306a36Sopenharmony_ci */ 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci /* access_type (byte_acc, word_acc, etc.) */ 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci info->field_flags = (u8) 32162306a36Sopenharmony_ci ((info-> 32262306a36Sopenharmony_ci field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | 32362306a36Sopenharmony_ci ((u8)((u32)(arg->common.value.integer & 0x07)))); 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci /* access_attribute (attrib_quick, attrib_byte, etc.) */ 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci info->attribute = (u8) 32862306a36Sopenharmony_ci ((arg->common.value.integer >> 8) & 0xFF); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* access_length (for serial/buffer protocols) */ 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci info->access_length = (u8) 33362306a36Sopenharmony_ci ((arg->common.value.integer >> 16) & 0xFF); 33462306a36Sopenharmony_ci break; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci case AML_INT_CONNECTION_OP: 33762306a36Sopenharmony_ci /* 33862306a36Sopenharmony_ci * Clear any previous connection. New connection is used for all 33962306a36Sopenharmony_ci * fields that follow, similar to access_as 34062306a36Sopenharmony_ci */ 34162306a36Sopenharmony_ci info->resource_buffer = NULL; 34262306a36Sopenharmony_ci info->connection_node = NULL; 34362306a36Sopenharmony_ci info->pin_number_index = 0; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* 34662306a36Sopenharmony_ci * A Connection() is either an actual resource descriptor (buffer) 34762306a36Sopenharmony_ci * or a named reference to a resource template 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_ci child = arg->common.value.arg; 35062306a36Sopenharmony_ci if (child->common.aml_opcode == AML_INT_BYTELIST_OP) { 35162306a36Sopenharmony_ci info->resource_buffer = child->named.data; 35262306a36Sopenharmony_ci info->resource_length = 35362306a36Sopenharmony_ci (u16)child->named.value.integer; 35462306a36Sopenharmony_ci } else { 35562306a36Sopenharmony_ci /* Lookup the Connection() namepath, it should already exist */ 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci status = acpi_ns_lookup(walk_state->scope_info, 35862306a36Sopenharmony_ci child->common.value. 35962306a36Sopenharmony_ci name, ACPI_TYPE_ANY, 36062306a36Sopenharmony_ci ACPI_IMODE_EXECUTE, 36162306a36Sopenharmony_ci ACPI_NS_DONT_OPEN_SCOPE, 36262306a36Sopenharmony_ci walk_state, 36362306a36Sopenharmony_ci &info->connection_node); 36462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 36562306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state-> 36662306a36Sopenharmony_ci scope_info, 36762306a36Sopenharmony_ci child->common. 36862306a36Sopenharmony_ci value.name, 36962306a36Sopenharmony_ci status); 37062306a36Sopenharmony_ci return_ACPI_STATUS(status); 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci break; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci case AML_INT_NAMEDFIELD_OP: 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* Lookup the name, it should already exist */ 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci status = acpi_ns_lookup(walk_state->scope_info, 38062306a36Sopenharmony_ci (char *)&arg->named.name, 38162306a36Sopenharmony_ci info->field_type, 38262306a36Sopenharmony_ci ACPI_IMODE_EXECUTE, 38362306a36Sopenharmony_ci ACPI_NS_DONT_OPEN_SCOPE, 38462306a36Sopenharmony_ci walk_state, &info->field_node); 38562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 38662306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 38762306a36Sopenharmony_ci (char *)&arg->named.name, 38862306a36Sopenharmony_ci status); 38962306a36Sopenharmony_ci return_ACPI_STATUS(status); 39062306a36Sopenharmony_ci } else { 39162306a36Sopenharmony_ci arg->common.node = info->field_node; 39262306a36Sopenharmony_ci info->field_bit_length = arg->common.value.size; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* 39562306a36Sopenharmony_ci * If there is no object attached to the node, this node was 39662306a36Sopenharmony_ci * just created and we need to create the field object. 39762306a36Sopenharmony_ci * Otherwise, this was a lookup of an existing node and we 39862306a36Sopenharmony_ci * don't want to create the field object again. 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_ci if (!acpi_ns_get_attached_object 40162306a36Sopenharmony_ci (info->field_node)) { 40262306a36Sopenharmony_ci status = acpi_ex_prep_field_value(info); 40362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 40462306a36Sopenharmony_ci return_ACPI_STATUS(status); 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci#ifdef ACPI_EXEC_APP 40762306a36Sopenharmony_ci name_path = 40862306a36Sopenharmony_ci acpi_ns_get_external_pathname(info-> 40962306a36Sopenharmony_ci field_node); 41062306a36Sopenharmony_ci if (ACPI_SUCCESS 41162306a36Sopenharmony_ci (ae_lookup_init_file_entry 41262306a36Sopenharmony_ci (name_path, &obj_desc))) { 41362306a36Sopenharmony_ci acpi_ex_write_data_to_field 41462306a36Sopenharmony_ci (obj_desc, 41562306a36Sopenharmony_ci acpi_ns_get_attached_object 41662306a36Sopenharmony_ci (info->field_node), 41762306a36Sopenharmony_ci &result_desc); 41862306a36Sopenharmony_ci acpi_ut_remove_reference 41962306a36Sopenharmony_ci (obj_desc); 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci ACPI_FREE(name_path); 42262306a36Sopenharmony_ci#endif 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* Keep track of bit position for the next field */ 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci position = (u64)info->field_bit_position + 42962306a36Sopenharmony_ci (u64)arg->common.value.size; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci if (position > ACPI_UINT32_MAX) { 43262306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 43362306a36Sopenharmony_ci "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", 43462306a36Sopenharmony_ci ACPI_CAST_PTR(char, 43562306a36Sopenharmony_ci &info->field_node-> 43662306a36Sopenharmony_ci name))); 43762306a36Sopenharmony_ci return_ACPI_STATUS(AE_SUPPORT); 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci info->field_bit_position += info->field_bit_length; 44162306a36Sopenharmony_ci info->pin_number_index++; /* Index relative to previous Connection() */ 44262306a36Sopenharmony_ci break; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci default: 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 44762306a36Sopenharmony_ci "Invalid opcode in field list: 0x%X", 44862306a36Sopenharmony_ci arg->common.aml_opcode)); 44962306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_BAD_OPCODE); 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci arg = arg->common.next; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci/******************************************************************************* 45962306a36Sopenharmony_ci * 46062306a36Sopenharmony_ci * FUNCTION: acpi_ds_create_field 46162306a36Sopenharmony_ci * 46262306a36Sopenharmony_ci * PARAMETERS: op - Op containing the Field definition and args 46362306a36Sopenharmony_ci * region_node - Object for the containing Operation Region 46462306a36Sopenharmony_ci * ` walk_state - Current method state 46562306a36Sopenharmony_ci * 46662306a36Sopenharmony_ci * RETURN: Status 46762306a36Sopenharmony_ci * 46862306a36Sopenharmony_ci * DESCRIPTION: Create a new field in the specified operation region 46962306a36Sopenharmony_ci * 47062306a36Sopenharmony_ci ******************************************************************************/ 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ciacpi_status 47362306a36Sopenharmony_ciacpi_ds_create_field(union acpi_parse_object *op, 47462306a36Sopenharmony_ci struct acpi_namespace_node *region_node, 47562306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci acpi_status status; 47862306a36Sopenharmony_ci union acpi_parse_object *arg; 47962306a36Sopenharmony_ci struct acpi_create_field_info info; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci /* First arg is the name of the parent op_region (must already exist) */ 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci arg = op->common.value.arg; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if (!region_node) { 48862306a36Sopenharmony_ci status = 48962306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, 49062306a36Sopenharmony_ci arg->common.value.name, ACPI_TYPE_REGION, 49162306a36Sopenharmony_ci ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 49262306a36Sopenharmony_ci walk_state, ®ion_node); 49362306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 49462306a36Sopenharmony_ci status = acpi_ds_create_external_region(status, arg, 49562306a36Sopenharmony_ci arg->common.value.name, 49662306a36Sopenharmony_ci walk_state, 49762306a36Sopenharmony_ci ®ion_node); 49862306a36Sopenharmony_ci#endif 49962306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 50062306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 50162306a36Sopenharmony_ci arg->common.value.name, status); 50262306a36Sopenharmony_ci return_ACPI_STATUS(status); 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci memset(&info, 0, sizeof(struct acpi_create_field_info)); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* Second arg is the field flags */ 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci arg = arg->common.next; 51162306a36Sopenharmony_ci info.field_flags = (u8) arg->common.value.integer; 51262306a36Sopenharmony_ci info.attribute = 0; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci /* Each remaining arg is a Named Field */ 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; 51762306a36Sopenharmony_ci info.region_node = region_node; 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); 52062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 52162306a36Sopenharmony_ci return_ACPI_STATUS(status); 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci if (info.region_node->object->region.space_id == 52562306a36Sopenharmony_ci ACPI_ADR_SPACE_PLATFORM_COMM) { 52662306a36Sopenharmony_ci region_node->object->field.internal_pcc_buffer = 52762306a36Sopenharmony_ci ACPI_ALLOCATE_ZEROED(info.region_node->object->region. 52862306a36Sopenharmony_ci length); 52962306a36Sopenharmony_ci if (!region_node->object->field.internal_pcc_buffer) { 53062306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 53162306a36Sopenharmony_ci } 53262306a36Sopenharmony_ci } 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci return_ACPI_STATUS(status); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/******************************************************************************* 53862306a36Sopenharmony_ci * 53962306a36Sopenharmony_ci * FUNCTION: acpi_ds_init_field_objects 54062306a36Sopenharmony_ci * 54162306a36Sopenharmony_ci * PARAMETERS: op - Op containing the Field definition and args 54262306a36Sopenharmony_ci * ` walk_state - Current method state 54362306a36Sopenharmony_ci * 54462306a36Sopenharmony_ci * RETURN: Status 54562306a36Sopenharmony_ci * 54662306a36Sopenharmony_ci * DESCRIPTION: For each "Field Unit" name in the argument list that is 54762306a36Sopenharmony_ci * part of the field declaration, enter the name into the 54862306a36Sopenharmony_ci * namespace. 54962306a36Sopenharmony_ci * 55062306a36Sopenharmony_ci ******************************************************************************/ 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ciacpi_status 55362306a36Sopenharmony_ciacpi_ds_init_field_objects(union acpi_parse_object *op, 55462306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci acpi_status status; 55762306a36Sopenharmony_ci union acpi_parse_object *arg = NULL; 55862306a36Sopenharmony_ci struct acpi_namespace_node *node; 55962306a36Sopenharmony_ci u8 type = 0; 56062306a36Sopenharmony_ci u32 flags; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci /* Execute flag should always be set when this function is entered */ 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { 56762306a36Sopenharmony_ci if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci /* bank_field Op is deferred, just return OK */ 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Parse deferred mode is not set")); 57562306a36Sopenharmony_ci return_ACPI_STATUS(AE_AML_INTERNAL); 57662306a36Sopenharmony_ci } 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci /* 57962306a36Sopenharmony_ci * Get the field_list argument for this opcode. This is the start of the 58062306a36Sopenharmony_ci * list of field elements. 58162306a36Sopenharmony_ci */ 58262306a36Sopenharmony_ci switch (walk_state->opcode) { 58362306a36Sopenharmony_ci case AML_FIELD_OP: 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci arg = acpi_ps_get_arg(op, 2); 58662306a36Sopenharmony_ci type = ACPI_TYPE_LOCAL_REGION_FIELD; 58762306a36Sopenharmony_ci break; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci case AML_BANK_FIELD_OP: 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci arg = acpi_ps_get_arg(op, 4); 59262306a36Sopenharmony_ci type = ACPI_TYPE_LOCAL_BANK_FIELD; 59362306a36Sopenharmony_ci break; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci case AML_INDEX_FIELD_OP: 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci arg = acpi_ps_get_arg(op, 3); 59862306a36Sopenharmony_ci type = ACPI_TYPE_LOCAL_INDEX_FIELD; 59962306a36Sopenharmony_ci break; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci default: 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci return_ACPI_STATUS(AE_BAD_PARAMETER); 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* Creating new namespace node(s), should not already exist */ 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 60962306a36Sopenharmony_ci ACPI_NS_ERROR_IF_FOUND; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* 61262306a36Sopenharmony_ci * Mark node(s) temporary if we are executing a normal control 61362306a36Sopenharmony_ci * method. (Don't mark if this is a module-level code method) 61462306a36Sopenharmony_ci */ 61562306a36Sopenharmony_ci if (walk_state->method_node && 61662306a36Sopenharmony_ci !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { 61762306a36Sopenharmony_ci flags |= ACPI_NS_TEMPORARY; 61862306a36Sopenharmony_ci } 61962306a36Sopenharmony_ci#ifdef ACPI_EXEC_APP 62062306a36Sopenharmony_ci flags |= ACPI_NS_OVERRIDE_IF_FOUND; 62162306a36Sopenharmony_ci#endif 62262306a36Sopenharmony_ci /* 62362306a36Sopenharmony_ci * Walk the list of entries in the field_list 62462306a36Sopenharmony_ci * Note: field_list can be of zero length. In this case, Arg will be NULL. 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_ci while (arg) { 62762306a36Sopenharmony_ci /* 62862306a36Sopenharmony_ci * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested 62962306a36Sopenharmony_ci * in the field names in order to enter them into the namespace. 63062306a36Sopenharmony_ci */ 63162306a36Sopenharmony_ci if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { 63262306a36Sopenharmony_ci status = acpi_ns_lookup(walk_state->scope_info, 63362306a36Sopenharmony_ci (char *)&arg->named.name, type, 63462306a36Sopenharmony_ci ACPI_IMODE_LOAD_PASS1, flags, 63562306a36Sopenharmony_ci walk_state, &node); 63662306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 63762306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 63862306a36Sopenharmony_ci (char *)&arg->named.name, 63962306a36Sopenharmony_ci status); 64062306a36Sopenharmony_ci if (status != AE_ALREADY_EXISTS) { 64162306a36Sopenharmony_ci return_ACPI_STATUS(status); 64262306a36Sopenharmony_ci } 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* Name already exists, just ignore this error */ 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci arg->common.node = node; 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci /* Get the next field element in the list */ 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci arg = arg->common.next; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci/******************************************************************************* 65962306a36Sopenharmony_ci * 66062306a36Sopenharmony_ci * FUNCTION: acpi_ds_create_bank_field 66162306a36Sopenharmony_ci * 66262306a36Sopenharmony_ci * PARAMETERS: op - Op containing the Field definition and args 66362306a36Sopenharmony_ci * region_node - Object for the containing Operation Region 66462306a36Sopenharmony_ci * walk_state - Current method state 66562306a36Sopenharmony_ci * 66662306a36Sopenharmony_ci * RETURN: Status 66762306a36Sopenharmony_ci * 66862306a36Sopenharmony_ci * DESCRIPTION: Create a new bank field in the specified operation region 66962306a36Sopenharmony_ci * 67062306a36Sopenharmony_ci ******************************************************************************/ 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ciacpi_status 67362306a36Sopenharmony_ciacpi_ds_create_bank_field(union acpi_parse_object *op, 67462306a36Sopenharmony_ci struct acpi_namespace_node *region_node, 67562306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 67662306a36Sopenharmony_ci{ 67762306a36Sopenharmony_ci acpi_status status; 67862306a36Sopenharmony_ci union acpi_parse_object *arg; 67962306a36Sopenharmony_ci struct acpi_create_field_info info; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci /* First arg is the name of the parent op_region (must already exist) */ 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci arg = op->common.value.arg; 68662306a36Sopenharmony_ci if (!region_node) { 68762306a36Sopenharmony_ci status = 68862306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, 68962306a36Sopenharmony_ci arg->common.value.name, ACPI_TYPE_REGION, 69062306a36Sopenharmony_ci ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 69162306a36Sopenharmony_ci walk_state, ®ion_node); 69262306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 69362306a36Sopenharmony_ci status = acpi_ds_create_external_region(status, arg, 69462306a36Sopenharmony_ci arg->common.value.name, 69562306a36Sopenharmony_ci walk_state, 69662306a36Sopenharmony_ci ®ion_node); 69762306a36Sopenharmony_ci#endif 69862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 69962306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 70062306a36Sopenharmony_ci arg->common.value.name, status); 70162306a36Sopenharmony_ci return_ACPI_STATUS(status); 70262306a36Sopenharmony_ci } 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci /* Second arg is the Bank Register (Field) (must already exist) */ 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci arg = arg->common.next; 70862306a36Sopenharmony_ci status = 70962306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, 71062306a36Sopenharmony_ci ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 71162306a36Sopenharmony_ci ACPI_NS_SEARCH_PARENT, walk_state, 71262306a36Sopenharmony_ci &info.register_node); 71362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 71462306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 71562306a36Sopenharmony_ci arg->common.value.string, status); 71662306a36Sopenharmony_ci return_ACPI_STATUS(status); 71762306a36Sopenharmony_ci } 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* 72062306a36Sopenharmony_ci * Third arg is the bank_value 72162306a36Sopenharmony_ci * This arg is a term_arg, not a constant 72262306a36Sopenharmony_ci * It will be evaluated later, by acpi_ds_eval_bank_field_operands 72362306a36Sopenharmony_ci */ 72462306a36Sopenharmony_ci arg = arg->common.next; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* Fourth arg is the field flags */ 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci arg = arg->common.next; 72962306a36Sopenharmony_ci info.field_flags = (u8) arg->common.value.integer; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci /* Each remaining arg is a Named Field */ 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; 73462306a36Sopenharmony_ci info.region_node = region_node; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci /* 73762306a36Sopenharmony_ci * Use Info.data_register_node to store bank_field Op 73862306a36Sopenharmony_ci * It's safe because data_register_node will never be used when create 73962306a36Sopenharmony_ci * bank field \we store aml_start and aml_length in the bank_field Op for 74062306a36Sopenharmony_ci * late evaluation. Used in acpi_ex_prep_field_value(Info) 74162306a36Sopenharmony_ci * 74262306a36Sopenharmony_ci * TBD: Or, should we add a field in struct acpi_create_field_info, like 74362306a36Sopenharmony_ci * "void *ParentOp"? 74462306a36Sopenharmony_ci */ 74562306a36Sopenharmony_ci info.data_register_node = (struct acpi_namespace_node *)op; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); 74862306a36Sopenharmony_ci return_ACPI_STATUS(status); 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci/******************************************************************************* 75262306a36Sopenharmony_ci * 75362306a36Sopenharmony_ci * FUNCTION: acpi_ds_create_index_field 75462306a36Sopenharmony_ci * 75562306a36Sopenharmony_ci * PARAMETERS: op - Op containing the Field definition and args 75662306a36Sopenharmony_ci * region_node - Object for the containing Operation Region 75762306a36Sopenharmony_ci * ` walk_state - Current method state 75862306a36Sopenharmony_ci * 75962306a36Sopenharmony_ci * RETURN: Status 76062306a36Sopenharmony_ci * 76162306a36Sopenharmony_ci * DESCRIPTION: Create a new index field in the specified operation region 76262306a36Sopenharmony_ci * 76362306a36Sopenharmony_ci ******************************************************************************/ 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ciacpi_status 76662306a36Sopenharmony_ciacpi_ds_create_index_field(union acpi_parse_object *op, 76762306a36Sopenharmony_ci struct acpi_namespace_node *region_node, 76862306a36Sopenharmony_ci struct acpi_walk_state *walk_state) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci acpi_status status; 77162306a36Sopenharmony_ci union acpi_parse_object *arg; 77262306a36Sopenharmony_ci struct acpi_create_field_info info; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci /* First arg is the name of the Index register (must already exist) */ 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci arg = op->common.value.arg; 77962306a36Sopenharmony_ci status = 78062306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, 78162306a36Sopenharmony_ci ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 78262306a36Sopenharmony_ci ACPI_NS_SEARCH_PARENT, walk_state, 78362306a36Sopenharmony_ci &info.register_node); 78462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 78562306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 78662306a36Sopenharmony_ci arg->common.value.string, status); 78762306a36Sopenharmony_ci return_ACPI_STATUS(status); 78862306a36Sopenharmony_ci } 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci /* Second arg is the data register (must already exist) */ 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci arg = arg->common.next; 79362306a36Sopenharmony_ci status = 79462306a36Sopenharmony_ci acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, 79562306a36Sopenharmony_ci ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 79662306a36Sopenharmony_ci ACPI_NS_SEARCH_PARENT, walk_state, 79762306a36Sopenharmony_ci &info.data_register_node); 79862306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 79962306a36Sopenharmony_ci ACPI_ERROR_NAMESPACE(walk_state->scope_info, 80062306a36Sopenharmony_ci arg->common.value.string, status); 80162306a36Sopenharmony_ci return_ACPI_STATUS(status); 80262306a36Sopenharmony_ci } 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci /* Next arg is the field flags */ 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci arg = arg->common.next; 80762306a36Sopenharmony_ci info.field_flags = (u8) arg->common.value.integer; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci /* Each remaining arg is a Named Field */ 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; 81262306a36Sopenharmony_ci info.region_node = region_node; 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); 81562306a36Sopenharmony_ci return_ACPI_STATUS(status); 81662306a36Sopenharmony_ci} 817