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