| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /****************************************************************************** | 
|  | 2 | * | 
|  | 3 | * Module Name: dsfield - Dispatcher field routines | 
|  | 4 | * | 
|  | 5 | *****************************************************************************/ | 
|  | 6 |  | 
|  | 7 | /* | 
| Len Brown | 75a44ce | 2008-04-23 23:00:13 -0400 | [diff] [blame] | 8 | * Copyright (C) 2000 - 2008, Intel Corp. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 | #include <acpi/acpi.h> | 
| Len Brown | e2f7a77 | 2009-01-09 00:30:03 -0500 | [diff] [blame] | 45 | #include "accommon.h" | 
|  | 46 | #include "amlcode.h" | 
|  | 47 | #include "acdispat.h" | 
|  | 48 | #include "acinterp.h" | 
|  | 49 | #include "acnamesp.h" | 
|  | 50 | #include "acparser.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 51 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 52 | #define _COMPONENT          ACPI_DISPATCHER | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 53 | ACPI_MODULE_NAME("dsfield") | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 55 | /* Local prototypes */ | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 56 | static acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 57 | acpi_ds_get_field_names(struct acpi_create_field_info *info, | 
|  | 58 | struct acpi_walk_state *walk_state, | 
|  | 59 | union acpi_parse_object *arg); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 60 |  | 
|  | 61 | /******************************************************************************* | 
|  | 62 | * | 
|  | 63 | * FUNCTION:    acpi_ds_create_buffer_field | 
|  | 64 | * | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 65 | * PARAMETERS:  Op                  - Current parse op (create_xXField) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 66 | *              walk_state          - Current state | 
|  | 67 | * | 
|  | 68 | * RETURN:      Status | 
|  | 69 | * | 
|  | 70 | * DESCRIPTION: Execute the create_field operators: | 
|  | 71 | *              create_bit_field_op, | 
|  | 72 | *              create_byte_field_op, | 
|  | 73 | *              create_word_field_op, | 
|  | 74 | *              create_dword_field_op, | 
|  | 75 | *              create_qword_field_op, | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 76 | *              create_field_op     (all of which define a field in a buffer) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 77 | * | 
|  | 78 | ******************************************************************************/ | 
|  | 79 |  | 
|  | 80 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 81 | acpi_ds_create_buffer_field(union acpi_parse_object *op, | 
|  | 82 | struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 83 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 84 | union acpi_parse_object *arg; | 
|  | 85 | struct acpi_namespace_node *node; | 
|  | 86 | acpi_status status; | 
|  | 87 | union acpi_operand_object *obj_desc; | 
|  | 88 | union acpi_operand_object *second_desc = NULL; | 
|  | 89 | u32 flags; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 90 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 91 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 92 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 93 | /* | 
|  | 94 | * Get the name_string argument (name of the new buffer_field) | 
|  | 95 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 97 |  | 
|  | 98 | /* For create_field, name is the 4th argument */ | 
|  | 99 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 100 | arg = acpi_ps_get_arg(op, 3); | 
|  | 101 | } else { | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 102 | /* For all other create_xXXField operators, name is the 3rd argument */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 103 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 104 | arg = acpi_ps_get_arg(op, 2); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 | } | 
|  | 106 |  | 
|  | 107 | if (!arg) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 108 | return_ACPI_STATUS(AE_AML_NO_OPERAND); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 | } | 
|  | 110 |  | 
|  | 111 | if (walk_state->deferred_node) { | 
|  | 112 | node = walk_state->deferred_node; | 
|  | 113 | status = AE_OK; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 114 | } else { | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 115 | /* Execute flag should always be set when this function is entered */ | 
|  | 116 |  | 
|  | 117 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | 
|  | 118 | return_ACPI_STATUS(AE_AML_INTERNAL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 119 | } | 
|  | 120 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 121 | /* Creating new namespace node, should not already exist */ | 
|  | 122 |  | 
|  | 123 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | 
|  | 124 | ACPI_NS_ERROR_IF_FOUND; | 
|  | 125 |  | 
|  | 126 | /* Mark node temporary if we are executing a method */ | 
|  | 127 |  | 
|  | 128 | if (walk_state->method_node) { | 
|  | 129 | flags |= ACPI_NS_TEMPORARY; | 
|  | 130 | } | 
|  | 131 |  | 
|  | 132 | /* Enter the name_string into the namespace */ | 
|  | 133 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 134 | status = | 
|  | 135 | acpi_ns_lookup(walk_state->scope_info, | 
|  | 136 | arg->common.value.string, ACPI_TYPE_ANY, | 
|  | 137 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 138 | &node); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 139 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 140 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 141 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 142 | } | 
|  | 143 | } | 
|  | 144 |  | 
| Bob Moore | 9c52657 | 2007-02-02 19:48:18 +0300 | [diff] [blame] | 145 | /* | 
|  | 146 | * We could put the returned object (Node) on the object stack for later, | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 147 | * but for now, we will put it in the "op" object that the parser uses, | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 148 | * so we can get it again at the end of this scope. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 149 | */ | 
|  | 150 | op->common.node = node; | 
|  | 151 |  | 
|  | 152 | /* | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 153 | * If there is no object attached to the node, this node was just created | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 154 | * and we need to create the field object. Otherwise, this was a lookup | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 155 | * of an existing node and we don't want to create the field object again. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 156 | */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 157 | obj_desc = acpi_ns_get_attached_object(node); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 158 | if (obj_desc) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 159 | return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 | } | 
|  | 161 |  | 
|  | 162 | /* | 
|  | 163 | * The Field definition is not fully parsed at this time. | 
|  | 164 | * (We must save the address of the AML for the buffer and index operands) | 
|  | 165 | */ | 
|  | 166 |  | 
|  | 167 | /* Create the buffer field object */ | 
|  | 168 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 169 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 170 | if (!obj_desc) { | 
|  | 171 | status = AE_NO_MEMORY; | 
|  | 172 | goto cleanup; | 
|  | 173 | } | 
|  | 174 |  | 
|  | 175 | /* | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 176 | * Remember location in AML stream of the field unit opcode and operands -- | 
|  | 177 | * since the buffer and index operands must be evaluated. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 178 | */ | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 179 | second_desc = obj_desc->common.next_object; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 180 | second_desc->extra.aml_start = op->named.data; | 
|  | 181 | second_desc->extra.aml_length = op->named.length; | 
|  | 182 | obj_desc->buffer_field.node = node; | 
|  | 183 |  | 
|  | 184 | /* Attach constructed field descriptors to parent node */ | 
|  | 185 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 186 | status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); | 
|  | 187 | if (ACPI_FAILURE(status)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 188 | goto cleanup; | 
|  | 189 | } | 
|  | 190 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 191 | cleanup: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 192 |  | 
|  | 193 | /* Remove local reference to the object */ | 
|  | 194 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 195 | acpi_ut_remove_reference(obj_desc); | 
|  | 196 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 197 | } | 
|  | 198 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 199 | /******************************************************************************* | 
|  | 200 | * | 
|  | 201 | * FUNCTION:    acpi_ds_get_field_names | 
|  | 202 | * | 
|  | 203 | * PARAMETERS:  Info            - create_field info structure | 
|  | 204 | *  `           walk_state      - Current method state | 
|  | 205 | *              Arg             - First parser arg for the field name list | 
|  | 206 | * | 
|  | 207 | * RETURN:      Status | 
|  | 208 | * | 
|  | 209 | * DESCRIPTION: Process all named fields in a field declaration.  Names are | 
|  | 210 | *              entered into the namespace. | 
|  | 211 | * | 
|  | 212 | ******************************************************************************/ | 
|  | 213 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 214 | static acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 215 | acpi_ds_get_field_names(struct acpi_create_field_info *info, | 
|  | 216 | struct acpi_walk_state *walk_state, | 
|  | 217 | union acpi_parse_object *arg) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 218 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 219 | acpi_status status; | 
|  | 220 | acpi_integer position; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 221 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 222 | ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 223 |  | 
|  | 224 | /* First field starts at bit zero */ | 
|  | 225 |  | 
|  | 226 | info->field_bit_position = 0; | 
|  | 227 |  | 
|  | 228 | /* Process all elements in the field list (of parse nodes) */ | 
|  | 229 |  | 
|  | 230 | while (arg) { | 
|  | 231 | /* | 
|  | 232 | * Three types of field elements are handled: | 
|  | 233 | * 1) Offset - specifies a bit offset | 
|  | 234 | * 2) access_as - changes the access mode | 
|  | 235 | * 3) Name - Enters a new named field into the namespace | 
|  | 236 | */ | 
|  | 237 | switch (arg->common.aml_opcode) { | 
|  | 238 | case AML_INT_RESERVEDFIELD_OP: | 
|  | 239 |  | 
|  | 240 | position = (acpi_integer) info->field_bit_position | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 241 | + (acpi_integer) arg->common.value.size; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 242 |  | 
|  | 243 | if (position > ACPI_UINT32_MAX) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 244 | ACPI_ERROR((AE_INFO, | 
|  | 245 | "Bit offset within field too large (> 0xFFFFFFFF)")); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 246 | return_ACPI_STATUS(AE_SUPPORT); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 247 | } | 
|  | 248 |  | 
|  | 249 | info->field_bit_position = (u32) position; | 
|  | 250 | break; | 
|  | 251 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 252 | case AML_INT_ACCESSFIELD_OP: | 
|  | 253 |  | 
|  | 254 | /* | 
|  | 255 | * Get a new access_type and access_attribute -- to be used for all | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 256 | * field units that follow, until field end or another access_as | 
|  | 257 | * keyword. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 258 | * | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 259 | * In field_flags, preserve the flag bits other than the | 
|  | 260 | * ACCESS_TYPE bits | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 261 | */ | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 262 | info->field_flags = (u8) | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 263 | ((info-> | 
|  | 264 | field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | | 
|  | 265 | ((u8) ((u32) arg->common.value.integer >> 8))); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 266 |  | 
|  | 267 | info->attribute = (u8) (arg->common.value.integer); | 
|  | 268 | break; | 
|  | 269 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 270 | case AML_INT_NAMEDFIELD_OP: | 
|  | 271 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 272 | /* Lookup the name, it should already exist */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 273 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 274 | status = acpi_ns_lookup(walk_state->scope_info, | 
|  | 275 | (char *)&arg->named.name, | 
|  | 276 | info->field_type, | 
|  | 277 | ACPI_IMODE_EXECUTE, | 
|  | 278 | ACPI_NS_DONT_OPEN_SCOPE, | 
|  | 279 | walk_state, &info->field_node); | 
|  | 280 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 281 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 
|  | 282 | status); | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 283 | return_ACPI_STATUS(status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 284 | } else { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 285 | arg->common.node = info->field_node; | 
|  | 286 | info->field_bit_length = arg->common.value.size; | 
|  | 287 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 288 | /* | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 289 | * If there is no object attached to the node, this node was | 
|  | 290 | * just created and we need to create the field object. | 
|  | 291 | * Otherwise, this was a lookup of an existing node and we | 
|  | 292 | * don't want to create the field object again. | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 293 | */ | 
|  | 294 | if (!acpi_ns_get_attached_object | 
|  | 295 | (info->field_node)) { | 
|  | 296 | status = acpi_ex_prep_field_value(info); | 
|  | 297 | if (ACPI_FAILURE(status)) { | 
|  | 298 | return_ACPI_STATUS(status); | 
|  | 299 | } | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 300 | } | 
|  | 301 | } | 
|  | 302 |  | 
|  | 303 | /* Keep track of bit position for the next field */ | 
|  | 304 |  | 
|  | 305 | position = (acpi_integer) info->field_bit_position | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 306 | + (acpi_integer) arg->common.value.size; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 307 |  | 
|  | 308 | if (position > ACPI_UINT32_MAX) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 309 | ACPI_ERROR((AE_INFO, | 
|  | 310 | "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", | 
|  | 311 | ACPI_CAST_PTR(char, | 
|  | 312 | &info->field_node-> | 
|  | 313 | name))); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 314 | return_ACPI_STATUS(AE_SUPPORT); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 315 | } | 
|  | 316 |  | 
|  | 317 | info->field_bit_position += info->field_bit_length; | 
|  | 318 | break; | 
|  | 319 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 320 | default: | 
|  | 321 |  | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 322 | ACPI_ERROR((AE_INFO, | 
|  | 323 | "Invalid opcode in field list: %X", | 
|  | 324 | arg->common.aml_opcode)); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 325 | return_ACPI_STATUS(AE_AML_BAD_OPCODE); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 326 | } | 
|  | 327 |  | 
|  | 328 | arg = arg->common.next; | 
|  | 329 | } | 
|  | 330 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 331 | return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 332 | } | 
|  | 333 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 334 | /******************************************************************************* | 
|  | 335 | * | 
|  | 336 | * FUNCTION:    acpi_ds_create_field | 
|  | 337 | * | 
|  | 338 | * PARAMETERS:  Op              - Op containing the Field definition and args | 
|  | 339 | *              region_node     - Object for the containing Operation Region | 
|  | 340 | *  `           walk_state      - Current method state | 
|  | 341 | * | 
|  | 342 | * RETURN:      Status | 
|  | 343 | * | 
|  | 344 | * DESCRIPTION: Create a new field in the specified operation region | 
|  | 345 | * | 
|  | 346 | ******************************************************************************/ | 
|  | 347 |  | 
|  | 348 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 349 | acpi_ds_create_field(union acpi_parse_object *op, | 
|  | 350 | struct acpi_namespace_node *region_node, | 
|  | 351 | struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 352 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 353 | acpi_status status; | 
|  | 354 | union acpi_parse_object *arg; | 
|  | 355 | struct acpi_create_field_info info; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 356 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 357 | ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 358 |  | 
|  | 359 | /* First arg is the name of the parent op_region (must already exist) */ | 
|  | 360 |  | 
|  | 361 | arg = op->common.value.arg; | 
|  | 362 | if (!region_node) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 363 | status = | 
|  | 364 | acpi_ns_lookup(walk_state->scope_info, | 
|  | 365 | arg->common.value.name, ACPI_TYPE_REGION, | 
|  | 366 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | 
|  | 367 | walk_state, ®ion_node); | 
|  | 368 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 369 | ACPI_ERROR_NAMESPACE(arg->common.value.name, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 370 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 371 | } | 
|  | 372 | } | 
|  | 373 |  | 
|  | 374 | /* Second arg is the field flags */ | 
|  | 375 |  | 
|  | 376 | arg = arg->common.next; | 
|  | 377 | info.field_flags = (u8) arg->common.value.integer; | 
|  | 378 | info.attribute = 0; | 
|  | 379 |  | 
|  | 380 | /* Each remaining arg is a Named Field */ | 
|  | 381 |  | 
|  | 382 | info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; | 
|  | 383 | info.region_node = region_node; | 
|  | 384 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 385 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 386 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 387 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 388 | } | 
|  | 389 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 390 | /******************************************************************************* | 
|  | 391 | * | 
|  | 392 | * FUNCTION:    acpi_ds_init_field_objects | 
|  | 393 | * | 
|  | 394 | * PARAMETERS:  Op              - Op containing the Field definition and args | 
|  | 395 | *  `           walk_state      - Current method state | 
|  | 396 | * | 
|  | 397 | * RETURN:      Status | 
|  | 398 | * | 
|  | 399 | * DESCRIPTION: For each "Field Unit" name in the argument list that is | 
|  | 400 | *              part of the field declaration, enter the name into the | 
|  | 401 | *              namespace. | 
|  | 402 | * | 
|  | 403 | ******************************************************************************/ | 
|  | 404 |  | 
|  | 405 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 406 | acpi_ds_init_field_objects(union acpi_parse_object *op, | 
|  | 407 | struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 408 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 409 | acpi_status status; | 
|  | 410 | union acpi_parse_object *arg = NULL; | 
|  | 411 | struct acpi_namespace_node *node; | 
|  | 412 | u8 type = 0; | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 413 | u32 flags; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 414 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 415 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 416 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 417 | /* Execute flag should always be set when this function is entered */ | 
|  | 418 |  | 
|  | 419 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | 
|  | 420 | if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { | 
|  | 421 |  | 
|  | 422 | /* bank_field Op is deferred, just return OK */ | 
|  | 423 |  | 
|  | 424 | return_ACPI_STATUS(AE_OK); | 
|  | 425 | } | 
|  | 426 |  | 
|  | 427 | return_ACPI_STATUS(AE_AML_INTERNAL); | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 428 | } | 
|  | 429 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 430 | /* | 
|  | 431 | * Get the field_list argument for this opcode. This is the start of the | 
|  | 432 | * list of field elements. | 
|  | 433 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 434 | switch (walk_state->opcode) { | 
|  | 435 | case AML_FIELD_OP: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 436 | arg = acpi_ps_get_arg(op, 2); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 437 | type = ACPI_TYPE_LOCAL_REGION_FIELD; | 
|  | 438 | break; | 
|  | 439 |  | 
|  | 440 | case AML_BANK_FIELD_OP: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 441 | arg = acpi_ps_get_arg(op, 4); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 442 | type = ACPI_TYPE_LOCAL_BANK_FIELD; | 
|  | 443 | break; | 
|  | 444 |  | 
|  | 445 | case AML_INDEX_FIELD_OP: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 446 | arg = acpi_ps_get_arg(op, 3); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 447 | type = ACPI_TYPE_LOCAL_INDEX_FIELD; | 
|  | 448 | break; | 
|  | 449 |  | 
|  | 450 | default: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 451 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 452 | } | 
|  | 453 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 454 | /* Creating new namespace node(s), should not already exist */ | 
|  | 455 |  | 
|  | 456 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | 
|  | 457 | ACPI_NS_ERROR_IF_FOUND; | 
|  | 458 |  | 
|  | 459 | /* Mark node(s) temporary if we are executing a method */ | 
|  | 460 |  | 
|  | 461 | if (walk_state->method_node) { | 
|  | 462 | flags |= ACPI_NS_TEMPORARY; | 
|  | 463 | } | 
|  | 464 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 465 | /* | 
|  | 466 | * Walk the list of entries in the field_list | 
| Bob Moore | 7aa7d43 | 2008-06-10 13:00:32 +0800 | [diff] [blame] | 467 | * Note: field_list can be of zero length. In this case, Arg will be NULL. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 468 | */ | 
|  | 469 | while (arg) { | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 470 | /* | 
|  | 471 | * Ignore OFFSET and ACCESSAS terms here; we are only interested in the | 
|  | 472 | * field names in order to enter them into the namespace. | 
|  | 473 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 474 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 475 | status = acpi_ns_lookup(walk_state->scope_info, | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 476 | (char *)&arg->named.name, type, | 
|  | 477 | ACPI_IMODE_LOAD_PASS1, flags, | 
|  | 478 | walk_state, &node); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 479 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 480 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 
|  | 481 | status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 482 | if (status != AE_ALREADY_EXISTS) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 483 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 484 | } | 
|  | 485 |  | 
|  | 486 | /* Name already exists, just ignore this error */ | 
|  | 487 |  | 
|  | 488 | status = AE_OK; | 
|  | 489 | } | 
|  | 490 |  | 
|  | 491 | arg->common.node = node; | 
|  | 492 | } | 
|  | 493 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 494 | /* Get the next field element in the list */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 495 |  | 
|  | 496 | arg = arg->common.next; | 
|  | 497 | } | 
|  | 498 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 499 | return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 500 | } | 
|  | 501 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 502 | /******************************************************************************* | 
|  | 503 | * | 
|  | 504 | * FUNCTION:    acpi_ds_create_bank_field | 
|  | 505 | * | 
|  | 506 | * PARAMETERS:  Op              - Op containing the Field definition and args | 
|  | 507 | *              region_node     - Object for the containing Operation Region | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 508 | *              walk_state      - Current method state | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 509 | * | 
|  | 510 | * RETURN:      Status | 
|  | 511 | * | 
|  | 512 | * DESCRIPTION: Create a new bank field in the specified operation region | 
|  | 513 | * | 
|  | 514 | ******************************************************************************/ | 
|  | 515 |  | 
|  | 516 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 517 | acpi_ds_create_bank_field(union acpi_parse_object *op, | 
|  | 518 | struct acpi_namespace_node *region_node, | 
|  | 519 | struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 520 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 521 | acpi_status status; | 
|  | 522 | union acpi_parse_object *arg; | 
|  | 523 | struct acpi_create_field_info info; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 524 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 525 | ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 526 |  | 
|  | 527 | /* First arg is the name of the parent op_region (must already exist) */ | 
|  | 528 |  | 
|  | 529 | arg = op->common.value.arg; | 
|  | 530 | if (!region_node) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 531 | status = | 
|  | 532 | acpi_ns_lookup(walk_state->scope_info, | 
|  | 533 | arg->common.value.name, ACPI_TYPE_REGION, | 
|  | 534 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | 
|  | 535 | walk_state, ®ion_node); | 
|  | 536 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 537 | ACPI_ERROR_NAMESPACE(arg->common.value.name, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 538 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 539 | } | 
|  | 540 | } | 
|  | 541 |  | 
|  | 542 | /* Second arg is the Bank Register (Field) (must already exist) */ | 
|  | 543 |  | 
|  | 544 | arg = arg->common.next; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 545 | status = | 
|  | 546 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | 
|  | 547 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | 
|  | 548 | ACPI_NS_SEARCH_PARENT, walk_state, | 
|  | 549 | &info.register_node); | 
|  | 550 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 551 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 552 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 553 | } | 
|  | 554 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 555 | /* | 
|  | 556 | * Third arg is the bank_value | 
|  | 557 | * This arg is a term_arg, not a constant | 
|  | 558 | * It will be evaluated later, by acpi_ds_eval_bank_field_operands | 
|  | 559 | */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 560 | arg = arg->common.next; | 
| Bob Moore | 9c52657 | 2007-02-02 19:48:18 +0300 | [diff] [blame] | 561 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 562 | /* Fourth arg is the field flags */ | 
|  | 563 |  | 
|  | 564 | arg = arg->common.next; | 
|  | 565 | info.field_flags = (u8) arg->common.value.integer; | 
|  | 566 |  | 
|  | 567 | /* Each remaining arg is a Named Field */ | 
|  | 568 |  | 
|  | 569 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; | 
|  | 570 | info.region_node = region_node; | 
|  | 571 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 572 | /* | 
|  | 573 | * Use Info.data_register_node to store bank_field Op | 
|  | 574 | * It's safe because data_register_node will never be used when create bank field | 
|  | 575 | * We store aml_start and aml_length in the bank_field Op for late evaluation | 
|  | 576 | * Used in acpi_ex_prep_field_value(Info) | 
|  | 577 | * | 
|  | 578 | * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? | 
|  | 579 | */ | 
|  | 580 | info.data_register_node = (struct acpi_namespace_node *)op; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 581 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 582 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 583 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 584 | } | 
|  | 585 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 586 | /******************************************************************************* | 
|  | 587 | * | 
|  | 588 | * FUNCTION:    acpi_ds_create_index_field | 
|  | 589 | * | 
|  | 590 | * PARAMETERS:  Op              - Op containing the Field definition and args | 
|  | 591 | *              region_node     - Object for the containing Operation Region | 
|  | 592 | *  `           walk_state      - Current method state | 
|  | 593 | * | 
|  | 594 | * RETURN:      Status | 
|  | 595 | * | 
|  | 596 | * DESCRIPTION: Create a new index field in the specified operation region | 
|  | 597 | * | 
|  | 598 | ******************************************************************************/ | 
|  | 599 |  | 
|  | 600 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 601 | acpi_ds_create_index_field(union acpi_parse_object *op, | 
|  | 602 | struct acpi_namespace_node *region_node, | 
|  | 603 | struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 604 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 605 | acpi_status status; | 
|  | 606 | union acpi_parse_object *arg; | 
|  | 607 | struct acpi_create_field_info info; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 608 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 609 | ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 610 |  | 
|  | 611 | /* First arg is the name of the Index register (must already exist) */ | 
|  | 612 |  | 
|  | 613 | arg = op->common.value.arg; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 614 | status = | 
|  | 615 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | 
|  | 616 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | 
|  | 617 | ACPI_NS_SEARCH_PARENT, walk_state, | 
|  | 618 | &info.register_node); | 
|  | 619 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 620 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 621 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 622 | } | 
|  | 623 |  | 
|  | 624 | /* Second arg is the data register (must already exist) */ | 
|  | 625 |  | 
|  | 626 | arg = arg->common.next; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 627 | status = | 
|  | 628 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | 
|  | 629 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | 
|  | 630 | ACPI_NS_SEARCH_PARENT, walk_state, | 
|  | 631 | &info.data_register_node); | 
|  | 632 | if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 633 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 634 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 635 | } | 
|  | 636 |  | 
|  | 637 | /* Next arg is the field flags */ | 
|  | 638 |  | 
|  | 639 | arg = arg->common.next; | 
|  | 640 | info.field_flags = (u8) arg->common.value.integer; | 
|  | 641 |  | 
|  | 642 | /* Each remaining arg is a Named Field */ | 
|  | 643 |  | 
|  | 644 | info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; | 
|  | 645 | info.region_node = region_node; | 
|  | 646 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 647 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 648 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 649 | return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 650 | } |