예제 #1
0
acpi_status
acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
				 union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *operand_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
	union acpi_parse_object *arg;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);

	/*
	 * This is where we evaluate the bank_value field of the
	 * bank_field declaration
	 */

	/* next_op points to the op that holds the Region */

	next_op = op->common.value.arg;

	/* next_op points to the op that holds the Bank Register */

	next_op = next_op->common.next;

	/* next_op points to the op that holds the Bank Value */

	next_op = next_op->common.next;

	/*
	 * Set proper index into operand stack for acpi_ds_obj_stack_push
	 * invoked inside acpi_ds_create_operand.
	 *
	 * We use walk_state->Operands[0] to store the evaluated bank_value
	 */
	walk_state->operand_index = 0;

	status = acpi_ds_create_operand(walk_state, next_op, 0);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
	/*
	 * Get the bank_value operand and save it
	 * (at Top of stack)
	 */
	operand_desc = walk_state->operands[0];

	/* Arg points to the start Bank Field */

	arg = acpi_ps_get_arg(op, 4);
	while (arg) {

		/* Ignore OFFSET and ACCESSAS terms here */

		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
			node = arg->common.node;

			obj_desc = acpi_ns_get_attached_object(node);
			if (!obj_desc) {
				return_ACPI_STATUS(AE_NOT_EXIST);
			}

			obj_desc->bank_field.value =
			    (u32) operand_desc->integer.value;
		}

		/* Move to next field in the list */

		arg = arg->common.next;
	}

	acpi_ut_remove_reference(operand_desc);
	return_ACPI_STATUS(status);
}
예제 #2
0
파일: pswalk.c 프로젝트: ahenroid/linux-pm
ACPI_STATUS
acpi_ps_get_next_walk_op (
	ACPI_WALK_STATE         *walk_state,
	ACPI_PARSE_OBJECT       *op,
	ACPI_PARSE_UPWARDS      ascending_callback)
{
	ACPI_PARSE_OBJECT       *next;
	ACPI_PARSE_OBJECT       *parent;
	ACPI_PARSE_OBJECT       *grand_parent;
	ACPI_STATUS             status;


	/* Check for a argument only if we are descending in the tree */

	if (walk_state->next_op_info != NEXT_OP_UPWARD) {
		/* Look for an argument or child of the current op */

		next = acpi_ps_get_arg (op, 0);
		if (next) {
			/* Still going downward in tree (Op is not completed yet) */

			walk_state->prev_op     = op;
			walk_state->next_op     = next;
			walk_state->next_op_info = NEXT_OP_DOWNWARD;

			return (AE_OK);
		}


		/*
		 * No more children, this Op is complete.  Save Next and Parent
		 * in case the Op object gets deleted by the callback routine
		 */

		next    = op->next;
		parent  = op->parent;

		status = ascending_callback (walk_state, op);

		/*
		 * If we are back to the starting point, the walk is complete.
		 */
		if (op == walk_state->origin) {
			/* Reached the point of origin, the walk is complete */

			walk_state->prev_op     = op;
			walk_state->next_op     = NULL;

			return (status);
		}

		/*
		 * Check for a sibling to the current op.  A sibling means
		 * we are still going "downward" in the tree.
		 */

		if (next) {
			/* There is a sibling, it will be next */

			walk_state->prev_op     = op;
			walk_state->next_op     = next;
			walk_state->next_op_info = NEXT_OP_DOWNWARD;

			/* Continue downward */

			return (status);
		}


		/*
		 * Drop into the loop below because we are moving upwards in
		 * the tree
		 */
	}

	else {
		/*
		 * We are resuming a walk, and we were (are) going upward in the tree.
		 * So, we want to drop into the parent loop below.
		 */

		parent = op;
	}


	/*
	 * Look for a sibling of the current Op's parent
	 * Continue moving up the tree until we find a node that has not been
	 * visited, or we get back to where we started.
	 */
	while (parent) {
		/* We are moving up the tree, therefore this parent Op is complete */

		grand_parent = parent->parent;
		next        = parent->next;

		status = ascending_callback (walk_state, parent);

		/*
		 * If we are back to the starting point, the walk is complete.
		 */
		if (parent == walk_state->origin) {
			/* Reached the point of origin, the walk is complete */

			walk_state->prev_op     = parent;
			walk_state->next_op     = NULL;

			return (status);
		}

		/*
		 * If there is a sibling to this parent (it is not the starting point
		 * Op), then we will visit it.
		 */
		if (next) {
			/* found sibling of parent */

			walk_state->prev_op     = parent;
			walk_state->next_op     = next;
			walk_state->next_op_info = NEXT_OP_DOWNWARD;

			return (status);
		}

		/* No siblings, no errors, just move up one more level in the tree */

		op                  = parent;
		parent              = grand_parent;
		walk_state->prev_op = op;
	}


	/* Got all the way to the top of the tree, we must be done! */
	/* However, the code should have terminated in the loop above */

	walk_state->next_op     = NULL;

	return (AE_OK);
}
예제 #3
0
파일: psargs.c 프로젝트: ahenroid/linux-pm
void
acpi_ps_get_next_namepath (
	ACPI_PARSE_STATE        *parser_state,
	ACPI_PARSE_OBJECT       *arg,
	u32                     *arg_count,
	u8                      method_call)
{
	NATIVE_CHAR             *path;
	ACPI_PARSE_OBJECT       *name_op;
	ACPI_PARSE_OBJECT       *op;
	ACPI_PARSE_OBJECT       *count;


	path = acpi_ps_get_next_namestring (parser_state);
	if (!path || !method_call) {
		/* Null name case, create a null namepath object */

		acpi_ps_init_op (arg, AML_NAMEPATH_OP);
		arg->value.name = path;
		return;
	}


	if (acpi_gbl_parsed_namespace_root) {
		/*
		 * Lookup the name in the parsed namespace
		 */

		op = NULL;
		if (method_call) {
			op = acpi_ps_find (acpi_ps_get_parent_scope (parser_state),
					   path, AML_METHOD_OP, 0);
		}

		if (op) {
			if (op->opcode == AML_METHOD_OP) {
				/*
				 * The name refers to a control method, so this namepath is a
				 * method invocation.  We need to 1) Get the number of arguments
				 * associated with this method, and 2) Change the NAMEPATH
				 * object into a METHODCALL object.
				 */

				count = acpi_ps_get_arg (op, 0);
				if (count && count->opcode == AML_BYTE_OP) {
					name_op = acpi_ps_alloc_op (AML_NAMEPATH_OP);
					if (name_op) {
						/* Change arg into a METHOD CALL and attach the name */

						acpi_ps_init_op (arg, AML_METHODCALL_OP);

						name_op->value.name = path;

						/* Point METHODCALL/NAME to the METHOD Node */

						name_op->node = (ACPI_NAMESPACE_NODE *) op;
						acpi_ps_append_arg (arg, name_op);

						*arg_count = count->value.integer &
								 METHOD_FLAGS_ARG_COUNT;
					}
				}

				return;
			}

			/*
			 * Else this is normal named object reference.
			 * Just init the NAMEPATH object with the pathname.
			 * (See code below)
			 */
		}
	}


	/*
	 * Either we didn't find the object in the namespace, or the object is
	 * something other than a control method.  Just initialize the Op with the
	 * pathname
	 */

	acpi_ps_init_op (arg, AML_NAMEPATH_OP);
	arg->value.name = path;


	return;
}
예제 #4
0
void
acpi_db_display_path (
	acpi_parse_object       *op)
{
	acpi_parse_object       *prev;
	acpi_parse_object       *search;
	u32                     name;
	u8                      do_dot = FALSE;
	acpi_parse_object       *name_path;
	const acpi_opcode_info  *op_info;


	/* We are only interested in named objects */

	op_info = acpi_ps_get_opcode_info (op->opcode);
	if (!(op_info->flags & AML_NSNODE)) {
		return;
	}


	if (op_info->flags & AML_CREATE) {
		/* Field creation - check for a fully qualified namepath */

		if (op->opcode == AML_CREATE_FIELD_OP) {
			name_path = acpi_ps_get_arg (op, 3);
		}
		else {
			name_path = acpi_ps_get_arg (op, 2);
		}

		if ((name_path) &&
			(name_path->value.string) &&
			(name_path->value.string[0] == '\\')) {
			acpi_db_display_namestring (name_path->value.string);
			return;
		}
	}

	prev = NULL;            /* Start with Root Node */

	while (prev != op) {
		/* Search upwards in the tree to find scope with "prev" as its parent */

		search = op;
		for (; ;) {
			if (search->parent == prev) {
				break;
			}

			/* Go up one level */

			search = search->parent;
		}

		if (prev) {
			op_info = acpi_ps_get_opcode_info (search->opcode);
			if (!(op_info->flags & AML_FIELD)) {
				/* below root scope, append scope name */

				if (do_dot) {
					/* append dot */

					acpi_os_printf (".");
				}

				if (op_info->flags & AML_CREATE) {
					if (op->opcode == AML_CREATE_FIELD_OP) {
						name_path = acpi_ps_get_arg (op, 3);
					}
					else {
						name_path = acpi_ps_get_arg (op, 2);
					}

					if ((name_path) &&
						(name_path->value.string)) {
						acpi_os_printf ("%4.4s", name_path->value.string);
					}
				}

				else {
					name = acpi_ps_get_name (search);
					acpi_os_printf ("%4.4s", &name);
				}

				do_dot = TRUE;
			}
		}

		prev = search;
	}
}
예제 #5
0
void
acpi_db_display_op (
	acpi_walk_state         *walk_state,
	acpi_parse_object       *origin,
	u32                     num_opcodes)
{
	acpi_parse_object       *op = origin;
	acpi_parse_object       *arg;
	acpi_parse_object       *depth;
	u32                     depth_count = 0;
	u32                     last_depth = 0;
	u32                     i;
	u32                     j;


	if (op) {
		while (op) {
			/* indentation */

			depth_count = 0;
			if (!acpi_gbl_db_opt_verbose) {
				depth_count++;
			}

			/* Determine the nesting depth of this argument */

			for (depth = op->parent; depth; depth = depth->parent) {
				arg = acpi_ps_get_arg (depth, 0);
				while (arg && arg != origin) {
					arg = arg->next;
				}

				if (arg) {
					break;
				}

				depth_count++;
			}


			/* Open a new block if we are nested further than last time */

			if (depth_count > last_depth) {
				VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth));
				for (i = 0; i < last_depth; i++) {
					acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
				}

				if (acpi_db_block_type (op) == BLOCK_PAREN) {
					acpi_os_printf ("(\n");
				}
				else {
					acpi_os_printf ("{\n");
				}
			}

			/* Close a block if we are nested less than last time */

			else if (depth_count < last_depth) {
				for (j = 0; j < (last_depth - depth_count); j++) {
					VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - j));
					for (i = 0; i < (last_depth - j - 1); i++) {
						acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
					}

					if (acpi_db_block_type (op) == BLOCK_PAREN) {
						acpi_os_printf (")\n");
					}
					else {
						acpi_os_printf ("}\n");
					}
				}
			}

			/* In verbose mode, print the AML offset, opcode and depth count */

			VERBOSE_PRINT ((DB_FULL_OP_INFO, (unsigned) op->aml_offset, op->opcode, depth_count));


			/* Indent the output according to the depth count */

			for (i = 0; i < depth_count; i++) {
				acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
			}


			/* Now print the opcode */

			acpi_db_display_opcode (walk_state, op);

			/* Resolve a name reference */

			if ((op->opcode == AML_INT_NAMEPATH_OP && op->value.name)  &&
				(op->parent) &&
				(acpi_gbl_db_opt_verbose)) {
				acpi_ps_display_object_pathname (walk_state, op);
			}

			acpi_os_printf ("\n");

			/* Get the next node in the tree */

			op = acpi_ps_get_depth_next (origin, op);
			last_depth = depth_count;

			num_opcodes--;
			if (!num_opcodes) {
				op = NULL;
			}
		}

		/* Close the last block(s) */

		depth_count = last_depth -1;
		for (i = 0; i < last_depth; i++) {
			VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - i));
			for (j = 0; j < depth_count; j++) {
				acpi_os_printf ("%s", acpi_gbl_db_disasm_indent);
			}
			acpi_os_printf ("}\n");
			depth_count--;
		}

	}

	else {
		acpi_db_display_opcode (walk_state, op);
	}
}
예제 #6
0
acpi_status
acpi_ds_create_buffer_field(union acpi_parse_object *op,
			    struct acpi_walk_state *walk_state)
{
	union acpi_parse_object *arg;
	struct acpi_namespace_node *node;
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *second_desc = NULL;
	u32 flags;

	ACPI_FUNCTION_TRACE(ds_create_buffer_field);

	/*
	 * Get the name_string argument (name of the new buffer_field)
	 */
	if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {

		/* For create_field, name is the 4th argument */

		arg = acpi_ps_get_arg(op, 3);
	} else {
		/* For all other create_xXXField operators, name is the 3rd argument */

		arg = acpi_ps_get_arg(op, 2);
	}

	if (!arg) {
		return_ACPI_STATUS(AE_AML_NO_OPERAND);
	}

	if (walk_state->deferred_node) {
		node = walk_state->deferred_node;
		status = AE_OK;
	} else {
		/* Execute flag should always be set when this function is entered */

		if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
			return_ACPI_STATUS(AE_AML_INTERNAL);
		}

		/* Creating new namespace node, should not already exist */

		flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
		    ACPI_NS_ERROR_IF_FOUND;

		/*
		 * Mark node temporary if we are executing a normal control
		 * method. (Don't mark if this is a module-level code method)
		 */
		if (walk_state->method_node &&
		    !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
			flags |= ACPI_NS_TEMPORARY;
		}

		/* Enter the name_string into the namespace */

		status =
		    acpi_ns_lookup(walk_state->scope_info,
				   arg->common.value.string, ACPI_TYPE_ANY,
				   ACPI_IMODE_LOAD_PASS1, flags, walk_state,
				   &node);
		if (ACPI_FAILURE(status)) {
			ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
			return_ACPI_STATUS(status);
		}
	}

	/*
	 * We could put the returned object (Node) on the object stack for later,
	 * but for now, we will put it in the "op" object that the parser uses,
	 * so we can get it again at the end of this scope.
	 */
	op->common.node = node;

	/*
	 * If there is no object attached to the node, this node was just created
	 * and we need to create the field object. Otherwise, this was a lookup
	 * of an existing node and we don't want to create the field object again.
	 */
	obj_desc = acpi_ns_get_attached_object(node);
	if (obj_desc) {
		return_ACPI_STATUS(AE_OK);
	}

	/*
	 * The Field definition is not fully parsed at this time.
	 * (We must save the address of the AML for the buffer and index operands)
	 */

	/* Create the buffer field object */

	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD);
	if (!obj_desc) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	/*
	 * Remember location in AML stream of the field unit opcode and operands --
	 * since the buffer and index operands must be evaluated.
	 */
	second_desc = obj_desc->common.next_object;
	second_desc->extra.aml_start = op->named.data;
	second_desc->extra.aml_length = op->named.length;
	obj_desc->buffer_field.node = node;

	/* Attach constructed field descriptors to parent node */

	status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

      cleanup:

	/* Remove local reference to the object */

	acpi_ut_remove_reference(obj_desc);
	return_ACPI_STATUS(status);
}