| 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 | 7784813 | 2012-01-12 13:27:23 +0800 | [diff] [blame] | 8 |  * Copyright (C) 2000 - 2012, 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; | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 224 | 	union acpi_parse_object *child; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 225 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 226 | 	ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 227 |  | 
 | 228 | 	/* First field starts at bit zero */ | 
 | 229 |  | 
 | 230 | 	info->field_bit_position = 0; | 
 | 231 |  | 
 | 232 | 	/* Process all elements in the field list (of parse nodes) */ | 
 | 233 |  | 
 | 234 | 	while (arg) { | 
 | 235 | 		/* | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 236 | 		 * Four types of field elements are handled: | 
 | 237 | 		 * 1) Name - Enters a new named field into the namespace | 
 | 238 | 		 * 2) Offset - specifies a bit offset | 
 | 239 | 		 * 3) access_as - changes the access mode/attributes | 
 | 240 | 		 * 4) Connection - Associate a resource template with the field | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 241 | 		 */ | 
 | 242 | 		switch (arg->common.aml_opcode) { | 
 | 243 | 		case AML_INT_RESERVEDFIELD_OP: | 
 | 244 |  | 
| Bob Moore | 5df7e6c | 2010-01-21 10:06:32 +0800 | [diff] [blame] | 245 | 			position = (u64) info->field_bit_position | 
 | 246 | 			    + (u64) arg->common.value.size; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 247 |  | 
 | 248 | 			if (position > ACPI_UINT32_MAX) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 249 | 				ACPI_ERROR((AE_INFO, | 
 | 250 | 					    "Bit offset within field too large (> 0xFFFFFFFF)")); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 251 | 				return_ACPI_STATUS(AE_SUPPORT); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 252 | 			} | 
 | 253 |  | 
 | 254 | 			info->field_bit_position = (u32) position; | 
 | 255 | 			break; | 
 | 256 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 257 | 		case AML_INT_ACCESSFIELD_OP: | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 258 | 		case AML_INT_EXTACCESSFIELD_OP: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 259 | 			/* | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 260 | 			 * Get new access_type, access_attribute, and access_length fields | 
 | 261 | 			 * -- to be used for all field units that follow, until the | 
 | 262 | 			 * end-of-field or another access_as keyword is encountered. | 
 | 263 | 			 * NOTE. These three bytes are encoded in the integer value | 
 | 264 | 			 * of the parseop for convenience. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 265 | 			 * | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 266 | 			 * In field_flags, preserve the flag bits other than the | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 267 | 			 * ACCESS_TYPE bits. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 268 | 			 */ | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 269 |  | 
 | 270 | 			/* access_type (byte_acc, word_acc, etc.) */ | 
 | 271 |  | 
| Robert Moore | 44f6c01 | 2005-04-18 22:49:35 -0400 | [diff] [blame] | 272 | 			info->field_flags = (u8) | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 273 | 			    ((info-> | 
 | 274 | 			      field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 275 | 			     ((u8)((u32)(arg->common.value.integer & 0x07)))); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 276 |  | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 277 | 			/* access_attribute (attrib_quick, attrib_byte, etc.) */ | 
 | 278 |  | 
 | 279 | 			info->attribute = | 
 | 280 | 			    (u8)((arg->common.value.integer >> 8) & 0xFF); | 
 | 281 |  | 
 | 282 | 			/* access_length (for serial/buffer protocols) */ | 
 | 283 |  | 
 | 284 | 			info->access_length = | 
 | 285 | 			    (u8)((arg->common.value.integer >> 16) & 0xFF); | 
 | 286 | 			break; | 
 | 287 |  | 
 | 288 | 		case AML_INT_CONNECTION_OP: | 
 | 289 | 			/* | 
 | 290 | 			 * Clear any previous connection. New connection is used for all | 
 | 291 | 			 * fields that follow, similar to access_as | 
 | 292 | 			 */ | 
 | 293 | 			info->resource_buffer = NULL; | 
 | 294 | 			info->connection_node = NULL; | 
 | 295 |  | 
 | 296 | 			/* | 
 | 297 | 			 * A Connection() is either an actual resource descriptor (buffer) | 
 | 298 | 			 * or a named reference to a resource template | 
 | 299 | 			 */ | 
 | 300 | 			child = arg->common.value.arg; | 
 | 301 | 			if (child->common.aml_opcode == AML_INT_BYTELIST_OP) { | 
 | 302 | 				info->resource_buffer = child->named.data; | 
 | 303 | 				info->resource_length = | 
 | 304 | 				    (u16)child->named.value.integer; | 
 | 305 | 			} else { | 
 | 306 | 				/* Lookup the Connection() namepath, it should already exist */ | 
 | 307 |  | 
 | 308 | 				status = acpi_ns_lookup(walk_state->scope_info, | 
 | 309 | 							child->common.value. | 
 | 310 | 							name, ACPI_TYPE_ANY, | 
 | 311 | 							ACPI_IMODE_EXECUTE, | 
 | 312 | 							ACPI_NS_DONT_OPEN_SCOPE, | 
 | 313 | 							walk_state, | 
 | 314 | 							&info->connection_node); | 
 | 315 | 				if (ACPI_FAILURE(status)) { | 
 | 316 | 					ACPI_ERROR_NAMESPACE(child->common. | 
 | 317 | 							     value.name, | 
 | 318 | 							     status); | 
 | 319 | 					return_ACPI_STATUS(status); | 
 | 320 | 				} | 
 | 321 | 			} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 322 | 			break; | 
 | 323 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 324 | 		case AML_INT_NAMEDFIELD_OP: | 
 | 325 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 326 | 			/* Lookup the name, it should already exist */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 327 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 328 | 			status = acpi_ns_lookup(walk_state->scope_info, | 
 | 329 | 						(char *)&arg->named.name, | 
 | 330 | 						info->field_type, | 
 | 331 | 						ACPI_IMODE_EXECUTE, | 
 | 332 | 						ACPI_NS_DONT_OPEN_SCOPE, | 
 | 333 | 						walk_state, &info->field_node); | 
 | 334 | 			if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 335 | 				ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 
 | 336 | 						     status); | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 337 | 				return_ACPI_STATUS(status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 338 | 			} else { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 339 | 				arg->common.node = info->field_node; | 
 | 340 | 				info->field_bit_length = arg->common.value.size; | 
 | 341 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 342 | 				/* | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 343 | 				 * If there is no object attached to the node, this node was | 
 | 344 | 				 * just created and we need to create the field object. | 
 | 345 | 				 * Otherwise, this was a lookup of an existing node and we | 
 | 346 | 				 * don't want to create the field object again. | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 347 | 				 */ | 
 | 348 | 				if (!acpi_ns_get_attached_object | 
 | 349 | 				    (info->field_node)) { | 
 | 350 | 					status = acpi_ex_prep_field_value(info); | 
 | 351 | 					if (ACPI_FAILURE(status)) { | 
 | 352 | 						return_ACPI_STATUS(status); | 
 | 353 | 					} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 354 | 				} | 
 | 355 | 			} | 
 | 356 |  | 
 | 357 | 			/* Keep track of bit position for the next field */ | 
 | 358 |  | 
| Bob Moore | 5df7e6c | 2010-01-21 10:06:32 +0800 | [diff] [blame] | 359 | 			position = (u64) info->field_bit_position | 
 | 360 | 			    + (u64) arg->common.value.size; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 361 |  | 
 | 362 | 			if (position > ACPI_UINT32_MAX) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 363 | 				ACPI_ERROR((AE_INFO, | 
 | 364 | 					    "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", | 
 | 365 | 					    ACPI_CAST_PTR(char, | 
 | 366 | 							  &info->field_node-> | 
 | 367 | 							  name))); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 368 | 				return_ACPI_STATUS(AE_SUPPORT); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 369 | 			} | 
 | 370 |  | 
 | 371 | 			info->field_bit_position += info->field_bit_length; | 
 | 372 | 			break; | 
 | 373 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 374 | 		default: | 
 | 375 |  | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 376 | 			ACPI_ERROR((AE_INFO, | 
| Bob Moore | f6a22b0 | 2010-03-05 17:56:40 +0800 | [diff] [blame] | 377 | 				    "Invalid opcode in field list: 0x%X", | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 378 | 				    arg->common.aml_opcode)); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 379 | 			return_ACPI_STATUS(AE_AML_BAD_OPCODE); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 380 | 		} | 
 | 381 |  | 
 | 382 | 		arg = arg->common.next; | 
 | 383 | 	} | 
 | 384 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 385 | 	return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 386 | } | 
 | 387 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 388 | /******************************************************************************* | 
 | 389 |  * | 
 | 390 |  * FUNCTION:    acpi_ds_create_field | 
 | 391 |  * | 
 | 392 |  * PARAMETERS:  Op              - Op containing the Field definition and args | 
 | 393 |  *              region_node     - Object for the containing Operation Region | 
 | 394 |  *  `           walk_state      - Current method state | 
 | 395 |  * | 
 | 396 |  * RETURN:      Status | 
 | 397 |  * | 
 | 398 |  * DESCRIPTION: Create a new field in the specified operation region | 
 | 399 |  * | 
 | 400 |  ******************************************************************************/ | 
 | 401 |  | 
 | 402 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 403 | acpi_ds_create_field(union acpi_parse_object *op, | 
 | 404 | 		     struct acpi_namespace_node *region_node, | 
 | 405 | 		     struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 406 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 407 | 	acpi_status status; | 
 | 408 | 	union acpi_parse_object *arg; | 
 | 409 | 	struct acpi_create_field_info info; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 410 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 411 | 	ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 412 |  | 
 | 413 | 	/* First arg is the name of the parent op_region (must already exist) */ | 
 | 414 |  | 
 | 415 | 	arg = op->common.value.arg; | 
 | 416 | 	if (!region_node) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 417 | 		status = | 
 | 418 | 		    acpi_ns_lookup(walk_state->scope_info, | 
 | 419 | 				   arg->common.value.name, ACPI_TYPE_REGION, | 
 | 420 | 				   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | 
 | 421 | 				   walk_state, ®ion_node); | 
 | 422 | 		if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 423 | 			ACPI_ERROR_NAMESPACE(arg->common.value.name, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 424 | 			return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 425 | 		} | 
 | 426 | 	} | 
 | 427 |  | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 428 | 	ACPI_MEMSET(&info, 0, sizeof(struct acpi_create_field_info)); | 
 | 429 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 430 | 	/* Second arg is the field flags */ | 
 | 431 |  | 
 | 432 | 	arg = arg->common.next; | 
 | 433 | 	info.field_flags = (u8) arg->common.value.integer; | 
 | 434 | 	info.attribute = 0; | 
 | 435 |  | 
 | 436 | 	/* Each remaining arg is a Named Field */ | 
 | 437 |  | 
 | 438 | 	info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; | 
 | 439 | 	info.region_node = region_node; | 
 | 440 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 441 | 	status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 442 | 	return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 443 | } | 
 | 444 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 445 | /******************************************************************************* | 
 | 446 |  * | 
 | 447 |  * FUNCTION:    acpi_ds_init_field_objects | 
 | 448 |  * | 
 | 449 |  * PARAMETERS:  Op              - Op containing the Field definition and args | 
 | 450 |  *  `           walk_state      - Current method state | 
 | 451 |  * | 
 | 452 |  * RETURN:      Status | 
 | 453 |  * | 
 | 454 |  * DESCRIPTION: For each "Field Unit" name in the argument list that is | 
 | 455 |  *              part of the field declaration, enter the name into the | 
 | 456 |  *              namespace. | 
 | 457 |  * | 
 | 458 |  ******************************************************************************/ | 
 | 459 |  | 
 | 460 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 461 | acpi_ds_init_field_objects(union acpi_parse_object *op, | 
 | 462 | 			   struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 463 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 464 | 	acpi_status status; | 
 | 465 | 	union acpi_parse_object *arg = NULL; | 
 | 466 | 	struct acpi_namespace_node *node; | 
 | 467 | 	u8 type = 0; | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 468 | 	u32 flags; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 469 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 470 | 	ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 471 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 472 | 	/* Execute flag should always be set when this function is entered */ | 
 | 473 |  | 
 | 474 | 	if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | 
 | 475 | 		if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { | 
 | 476 |  | 
 | 477 | 			/* bank_field Op is deferred, just return OK */ | 
 | 478 |  | 
 | 479 | 			return_ACPI_STATUS(AE_OK); | 
 | 480 | 		} | 
 | 481 |  | 
 | 482 | 		return_ACPI_STATUS(AE_AML_INTERNAL); | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 483 | 	} | 
 | 484 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 485 | 	/* | 
 | 486 | 	 * Get the field_list argument for this opcode. This is the start of the | 
 | 487 | 	 * list of field elements. | 
 | 488 | 	 */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 489 | 	switch (walk_state->opcode) { | 
 | 490 | 	case AML_FIELD_OP: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 491 | 		arg = acpi_ps_get_arg(op, 2); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 492 | 		type = ACPI_TYPE_LOCAL_REGION_FIELD; | 
 | 493 | 		break; | 
 | 494 |  | 
 | 495 | 	case AML_BANK_FIELD_OP: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 496 | 		arg = acpi_ps_get_arg(op, 4); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 497 | 		type = ACPI_TYPE_LOCAL_BANK_FIELD; | 
 | 498 | 		break; | 
 | 499 |  | 
 | 500 | 	case AML_INDEX_FIELD_OP: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 501 | 		arg = acpi_ps_get_arg(op, 3); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 502 | 		type = ACPI_TYPE_LOCAL_INDEX_FIELD; | 
 | 503 | 		break; | 
 | 504 |  | 
 | 505 | 	default: | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 506 | 		return_ACPI_STATUS(AE_BAD_PARAMETER); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 507 | 	} | 
 | 508 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 509 | 	/* Creating new namespace node(s), should not already exist */ | 
 | 510 |  | 
 | 511 | 	flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | 
 | 512 | 	    ACPI_NS_ERROR_IF_FOUND; | 
 | 513 |  | 
| Lin Ming | 7f0c826 | 2009-08-13 14:03:15 +0800 | [diff] [blame] | 514 | 	/* | 
 | 515 | 	 * Mark node(s) temporary if we are executing a normal control | 
 | 516 | 	 * method. (Don't mark if this is a module-level code method) | 
 | 517 | 	 */ | 
 | 518 | 	if (walk_state->method_node && | 
 | 519 | 	    !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 520 | 		flags |= ACPI_NS_TEMPORARY; | 
 | 521 | 	} | 
 | 522 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 523 | 	/* | 
 | 524 | 	 * Walk the list of entries in the field_list | 
| Bob Moore | 7aa7d43 | 2008-06-10 13:00:32 +0800 | [diff] [blame] | 525 | 	 * 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] | 526 | 	 */ | 
 | 527 | 	while (arg) { | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 528 | 		/* | 
| Bob Moore | 9ce8178 | 2011-11-16 13:39:07 +0800 | [diff] [blame] | 529 | 		 * Ignore OFFSET/ACCESSAS/CONNECTION terms here; we are only interested | 
 | 530 | 		 * in the field names in order to enter them into the namespace. | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 531 | 		 */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 532 | 		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 533 | 			status = acpi_ns_lookup(walk_state->scope_info, | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 534 | 						(char *)&arg->named.name, type, | 
 | 535 | 						ACPI_IMODE_LOAD_PASS1, flags, | 
 | 536 | 						walk_state, &node); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 537 | 			if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 538 | 				ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 
 | 539 | 						     status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 540 | 				if (status != AE_ALREADY_EXISTS) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 541 | 					return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 542 | 				} | 
 | 543 |  | 
 | 544 | 				/* Name already exists, just ignore this error */ | 
 | 545 |  | 
 | 546 | 				status = AE_OK; | 
 | 547 | 			} | 
 | 548 |  | 
 | 549 | 			arg->common.node = node; | 
 | 550 | 		} | 
 | 551 |  | 
| Bob Moore | cca97b8 | 2008-04-10 19:06:44 +0400 | [diff] [blame] | 552 | 		/* Get the next field element in the list */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 553 |  | 
 | 554 | 		arg = arg->common.next; | 
 | 555 | 	} | 
 | 556 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 557 | 	return_ACPI_STATUS(AE_OK); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 558 | } | 
 | 559 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 560 | /******************************************************************************* | 
 | 561 |  * | 
 | 562 |  * FUNCTION:    acpi_ds_create_bank_field | 
 | 563 |  * | 
 | 564 |  * PARAMETERS:  Op              - Op containing the Field definition and args | 
 | 565 |  *              region_node     - Object for the containing Operation Region | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 566 |  *              walk_state      - Current method state | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 567 |  * | 
 | 568 |  * RETURN:      Status | 
 | 569 |  * | 
 | 570 |  * DESCRIPTION: Create a new bank field in the specified operation region | 
 | 571 |  * | 
 | 572 |  ******************************************************************************/ | 
 | 573 |  | 
 | 574 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 575 | acpi_ds_create_bank_field(union acpi_parse_object *op, | 
 | 576 | 			  struct acpi_namespace_node *region_node, | 
 | 577 | 			  struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 578 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 579 | 	acpi_status status; | 
 | 580 | 	union acpi_parse_object *arg; | 
 | 581 | 	struct acpi_create_field_info info; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 582 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 583 | 	ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 584 |  | 
 | 585 | 	/* First arg is the name of the parent op_region (must already exist) */ | 
 | 586 |  | 
 | 587 | 	arg = op->common.value.arg; | 
 | 588 | 	if (!region_node) { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 589 | 		status = | 
 | 590 | 		    acpi_ns_lookup(walk_state->scope_info, | 
 | 591 | 				   arg->common.value.name, ACPI_TYPE_REGION, | 
 | 592 | 				   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | 
 | 593 | 				   walk_state, ®ion_node); | 
 | 594 | 		if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 595 | 			ACPI_ERROR_NAMESPACE(arg->common.value.name, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 596 | 			return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 597 | 		} | 
 | 598 | 	} | 
 | 599 |  | 
 | 600 | 	/* Second arg is the Bank Register (Field) (must already exist) */ | 
 | 601 |  | 
 | 602 | 	arg = arg->common.next; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 603 | 	status = | 
 | 604 | 	    acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | 
 | 605 | 			   ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | 
 | 606 | 			   ACPI_NS_SEARCH_PARENT, walk_state, | 
 | 607 | 			   &info.register_node); | 
 | 608 | 	if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 609 | 		ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 610 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 611 | 	} | 
 | 612 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 613 | 	/* | 
 | 614 | 	 * Third arg is the bank_value | 
 | 615 | 	 * This arg is a term_arg, not a constant | 
 | 616 | 	 * It will be evaluated later, by acpi_ds_eval_bank_field_operands | 
 | 617 | 	 */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 618 | 	arg = arg->common.next; | 
| Bob Moore | 9c52657 | 2007-02-02 19:48:18 +0300 | [diff] [blame] | 619 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 620 | 	/* Fourth arg is the field flags */ | 
 | 621 |  | 
 | 622 | 	arg = arg->common.next; | 
 | 623 | 	info.field_flags = (u8) arg->common.value.integer; | 
 | 624 |  | 
 | 625 | 	/* Each remaining arg is a Named Field */ | 
 | 626 |  | 
 | 627 | 	info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; | 
 | 628 | 	info.region_node = region_node; | 
 | 629 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 630 | 	/* | 
 | 631 | 	 * Use Info.data_register_node to store bank_field Op | 
 | 632 | 	 * It's safe because data_register_node will never be used when create bank field | 
 | 633 | 	 * We store aml_start and aml_length in the bank_field Op for late evaluation | 
 | 634 | 	 * Used in acpi_ex_prep_field_value(Info) | 
 | 635 | 	 * | 
 | 636 | 	 * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? | 
 | 637 | 	 */ | 
 | 638 | 	info.data_register_node = (struct acpi_namespace_node *)op; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 639 |  | 
| Lin Ming | ef805d9 | 2008-04-10 19:06:41 +0400 | [diff] [blame] | 640 | 	status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 641 | 	return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 642 | } | 
 | 643 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 644 | /******************************************************************************* | 
 | 645 |  * | 
 | 646 |  * FUNCTION:    acpi_ds_create_index_field | 
 | 647 |  * | 
 | 648 |  * PARAMETERS:  Op              - Op containing the Field definition and args | 
 | 649 |  *              region_node     - Object for the containing Operation Region | 
 | 650 |  *  `           walk_state      - Current method state | 
 | 651 |  * | 
 | 652 |  * RETURN:      Status | 
 | 653 |  * | 
 | 654 |  * DESCRIPTION: Create a new index field in the specified operation region | 
 | 655 |  * | 
 | 656 |  ******************************************************************************/ | 
 | 657 |  | 
 | 658 | acpi_status | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 659 | acpi_ds_create_index_field(union acpi_parse_object *op, | 
 | 660 | 			   struct acpi_namespace_node *region_node, | 
 | 661 | 			   struct acpi_walk_state *walk_state) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 662 | { | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 663 | 	acpi_status status; | 
 | 664 | 	union acpi_parse_object *arg; | 
 | 665 | 	struct acpi_create_field_info info; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 666 |  | 
| Bob Moore | b229cf9 | 2006-04-21 17:15:00 -0400 | [diff] [blame] | 667 | 	ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 668 |  | 
 | 669 | 	/* First arg is the name of the Index register (must already exist) */ | 
 | 670 |  | 
 | 671 | 	arg = op->common.value.arg; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 672 | 	status = | 
 | 673 | 	    acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | 
 | 674 | 			   ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | 
 | 675 | 			   ACPI_NS_SEARCH_PARENT, walk_state, | 
 | 676 | 			   &info.register_node); | 
 | 677 | 	if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 678 | 		ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 679 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 680 | 	} | 
 | 681 |  | 
 | 682 | 	/* Second arg is the data register (must already exist) */ | 
 | 683 |  | 
 | 684 | 	arg = arg->common.next; | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 685 | 	status = | 
 | 686 | 	    acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | 
 | 687 | 			   ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | 
 | 688 | 			   ACPI_NS_SEARCH_PARENT, walk_state, | 
 | 689 | 			   &info.data_register_node); | 
 | 690 | 	if (ACPI_FAILURE(status)) { | 
| Bob Moore | b8e4d89 | 2006-01-27 16:43:00 -0500 | [diff] [blame] | 691 | 		ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 692 | 		return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 693 | 	} | 
 | 694 |  | 
 | 695 | 	/* Next arg is the field flags */ | 
 | 696 |  | 
 | 697 | 	arg = arg->common.next; | 
 | 698 | 	info.field_flags = (u8) arg->common.value.integer; | 
 | 699 |  | 
 | 700 | 	/* Each remaining arg is a Named Field */ | 
 | 701 |  | 
 | 702 | 	info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; | 
 | 703 | 	info.region_node = region_node; | 
 | 704 |  | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 705 | 	status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 
| Len Brown | 4be44fc | 2005-08-05 00:44:28 -0400 | [diff] [blame] | 706 | 	return_ACPI_STATUS(status); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 707 | } |