*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
-#include <acpi/acnamesp.h>
-
#define _COMPONENT ACPI_PARSER
- ACPI_MODULE_NAME ("psxface")
+ACPI_MODULE_NAME("psxface")
+
+/* Local Prototypes */
+static void acpi_ps_start_trace(struct acpi_evaluate_info *info);
+
+static void acpi_ps_stop_trace(struct acpi_evaluate_info *info);
+
+static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info);
+static void
+acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
/*******************************************************************************
*
- * FUNCTION: acpi_psx_execute
+ * FUNCTION: acpi_debug_trace
*
- * PARAMETERS: method_node - A method object containing both the AML
- * address and length.
- * **Params - List of parameters to pass to method,
- * terminated by NULL. Params itself may be
- * NULL if no parameters are being passed.
- * **return_obj_desc - Return object from execution of the
- * method.
+ * PARAMETERS: method_name - Valid ACPI name string
+ * debug_level - Optional level mask. 0 to use default
+ * debug_layer - Optional layer mask. 0 to use default
+ * Flags - bit 1: one shot(1) or persistent(0)
*
* RETURN: Status
*
- * DESCRIPTION: Execute a control method
+ * DESCRIPTION: External interface to enable debug tracing during control
+ * method execution
*
******************************************************************************/
acpi_status
-acpi_psx_execute (
- struct acpi_namespace_node *method_node,
- union acpi_operand_object **params,
- union acpi_operand_object **return_obj_desc)
+acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
{
- acpi_status status;
- union acpi_operand_object *obj_desc;
- u32 i;
- union acpi_parse_object *op;
- struct acpi_walk_state *walk_state;
+ acpi_status status;
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
- ACPI_FUNCTION_TRACE ("psx_execute");
+ /* TBDs: Validate name, allow full path or just nameseg */
+
+ acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name);
+ acpi_gbl_trace_flags = flags;
+
+ if (debug_level) {
+ acpi_gbl_trace_dbg_level = debug_level;
+ }
+ if (debug_layer) {
+ acpi_gbl_trace_dbg_layer = debug_layer;
+ }
+
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_start_trace
+ *
+ * PARAMETERS: Info - Method info struct
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Start control method execution trace
+ *
+ ******************************************************************************/
+static void acpi_ps_start_trace(struct acpi_evaluate_info *info)
+{
+ acpi_status status;
- /* Validate the Node and get the attached object */
+ ACPI_FUNCTION_ENTRY();
- if (!method_node) {
- return_ACPI_STATUS (AE_NULL_ENTRY);
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return;
}
- obj_desc = acpi_ns_get_attached_object (method_node);
- if (!obj_desc) {
- return_ACPI_STATUS (AE_NULL_OBJECT);
+ if ((!acpi_gbl_trace_method_name) ||
+ (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
+ goto exit;
}
- /* Init for new method, wait on concurrency semaphore */
+ acpi_gbl_original_dbg_level = acpi_dbg_level;
+ acpi_gbl_original_dbg_layer = acpi_dbg_layer;
+
+ acpi_dbg_level = 0x00FFFFFF;
+ acpi_dbg_layer = ACPI_UINT32_MAX;
- status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+ if (acpi_gbl_trace_dbg_level) {
+ acpi_dbg_level = acpi_gbl_trace_dbg_level;
+ }
+ if (acpi_gbl_trace_dbg_layer) {
+ acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
}
- if (params) {
- /*
- * The caller "owns" the parameters, so give each one an extra
- * reference
- */
- for (i = 0; params[i]; i++) {
- acpi_ut_add_reference (params[i]);
- }
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_stop_trace
+ *
+ * PARAMETERS: Info - Method info struct
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Stop control method execution trace
+ *
+ ******************************************************************************/
+
+static void acpi_ps_stop_trace(struct acpi_evaluate_info *info)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_ENTRY();
+
+ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return;
}
- /*
- * 1) Perform the first pass parse of the method to enter any
- * named objects that it creates into the namespace
- */
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** Begin Method Parse **** Entry=%p obj=%p\n",
- method_node, obj_desc));
+ if ((!acpi_gbl_trace_method_name) ||
+ (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
+ goto exit;
+ }
- /* Create and init a Root Node */
+ /* Disable further tracing if type is one-shot */
- op = acpi_ps_create_scope_op ();
- if (!op) {
- status = AE_NO_MEMORY;
- goto cleanup1;
+ if (acpi_gbl_trace_flags & 1) {
+ acpi_gbl_trace_method_name = 0;
+ acpi_gbl_trace_dbg_level = 0;
+ acpi_gbl_trace_dbg_layer = 0;
}
- /*
- * Get a new owner_id for objects created by this method. Namespace
- * objects (such as Operation Regions) can be created during the
- * first pass parse.
- */
- obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
+ acpi_dbg_level = acpi_gbl_original_dbg_level;
+ acpi_dbg_layer = acpi_gbl_original_dbg_layer;
- /* Create and initialize a new walk state */
+ exit:
+ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
- walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
- NULL, NULL, NULL);
- if (!walk_state) {
- status = AE_NO_MEMORY;
- goto cleanup2;
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_execute_method
+ *
+ * PARAMETERS: Info - Method info block, contains:
+ * Node - Method Node to execute
+ * obj_desc - Method object
+ * Parameters - List of parameters to pass to the method,
+ * terminated by NULL. Params itself may be
+ * NULL if no parameters are being passed.
+ * return_object - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ * parameter_type - Type of Parameter list
+ * return_object - Where to put method's return value (if
+ * any). If NULL, no value is returned.
+ * pass_number - Parse or execute pass
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Execute a control method
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ps_execute_method);
+
+ /* Validate the Info and method Node */
+
+ if (!info || !info->resolved_node) {
+ return_ACPI_STATUS(AE_NULL_ENTRY);
}
- status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
- obj_desc->method.aml_length, NULL, NULL, 1);
- if (ACPI_FAILURE (status)) {
- goto cleanup3;
+ /* Init for new method, wait on concurrency semaphore */
+
+ status =
+ acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc,
+ NULL);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
- /* Parse the AML */
+ /*
+ * The caller "owns" the parameters, so give each one an extra
+ * reference
+ */
+ acpi_ps_update_parameter_list(info, REF_INCREMENT);
+
+ /* Begin tracing if requested */
- status = acpi_ps_parse_aml (walk_state);
- acpi_ps_delete_parse_tree (op);
- if (ACPI_FAILURE (status)) {
- goto cleanup1; /* Walk state is already deleted */
+ acpi_ps_start_trace(info);
+ /*
+ * 1) Perform the first pass parse of the method to enter any
+ * named objects that it creates into the namespace
+ */
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Begin Method Parse **** Entry=%p obj=%p\n",
+ info->resolved_node, info->obj_desc));
+
+ info->pass_number = 1;
+ status = acpi_ps_execute_pass(info);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup;
}
/*
- * 2) Execute the method. Performs second pass parse simultaneously
+ * 2) Execute the method. Performs second pass parse simultaneously
*/
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
- "**** Begin Method Execution **** Entry=%p obj=%p\n",
- method_node, obj_desc));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "**** Begin Method Execution **** Entry=%p obj=%p\n",
+ info->resolved_node, info->obj_desc));
- /* Create and init a Root Node */
+ info->pass_number = 3;
+ status = acpi_ps_execute_pass(info);
- op = acpi_ps_create_scope_op ();
- if (!op) {
- status = AE_NO_MEMORY;
- goto cleanup1;
- }
+ cleanup:
+ /* End optional tracing */
- /* Init new op with the method name and pointer back to the NS node */
+ acpi_ps_stop_trace(info);
- acpi_ps_set_name (op, method_node->name.integer);
- op->common.node = method_node;
+ /* Take away the extra reference that we gave the parameters above */
- /* Create and initialize a new walk state */
+ acpi_ps_update_parameter_list(info, REF_DECREMENT);
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
- if (!walk_state) {
- status = AE_NO_MEMORY;
- goto cleanup2;
- }
+ /* Exit now if error above */
- status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
- obj_desc->method.aml_length, params, return_obj_desc, 3);
- if (ACPI_FAILURE (status)) {
- goto cleanup3;
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
/*
- * The walk of the parse tree is where we actually execute the method
+ * If the method has returned an object, signal this to the caller with
+ * a control exception code
*/
- status = acpi_ps_parse_aml (walk_state);
- goto cleanup2; /* Walk state already deleted */
+ if (info->return_object) {
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
+ info->return_object));
+ ACPI_DUMP_STACK_ENTRY(info->return_object);
+ status = AE_CTRL_RETURN_VALUE;
+ }
-cleanup3:
- acpi_ds_delete_walk_state (walk_state);
+ return_ACPI_STATUS(status);
+}
-cleanup2:
- acpi_ps_delete_parse_tree (op);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_update_parameter_list
+ *
+ * PARAMETERS: Info - See struct acpi_evaluate_info
+ * (Used: parameter_type and Parameters)
+ * Action - Add or Remove reference
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Update reference count on all method parameter objects
+ *
+ ******************************************************************************/
-cleanup1:
- if (params) {
- /* Take away the extra reference that we gave the parameters above */
+static void
+acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
+{
+ acpi_native_uint i;
+
+ if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) {
+
+ /* Update reference count for each parameter */
+
+ for (i = 0; info->parameters[i]; i++) {
- for (i = 0; params[i]; i++) {
/* Ignore errors, just do them all */
- (void) acpi_ut_update_object_reference (params[i], REF_DECREMENT);
+ (void)acpi_ut_update_object_reference(info->
+ parameters[i],
+ action);
}
}
+}
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ps_execute_pass
+ *
+ * PARAMETERS: Info - See struct acpi_evaluate_info
+ * (Used: pass_number, Node, and obj_desc)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Single AML pass: Parse or Execute a control method
+ *
+ ******************************************************************************/
+
+static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info)
+{
+ acpi_status status;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+
+ ACPI_FUNCTION_TRACE(ps_execute_pass);
+
+ /* Create and init a Root Node */
+
+ op = acpi_ps_create_scope_op();
+ if (!op) {
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- /*
- * If the method has returned an object, signal this to the caller with
- * a control exception code
- */
- if (*return_obj_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
- *return_obj_desc));
- ACPI_DUMP_STACK_ENTRY (*return_obj_desc);
+ /* Create and initialize a new walk state */
- status = AE_CTRL_RETURN_VALUE;
+ walk_state =
+ acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
+ NULL, NULL);
+ if (!walk_state) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
- return_ACPI_STATUS (status);
-}
+ status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node,
+ info->obj_desc->method.aml_start,
+ info->obj_desc->method.aml_length,
+ info->pass_number == 1 ? NULL : info,
+ info->pass_number);
+ if (ACPI_FAILURE(status)) {
+ acpi_ds_delete_walk_state(walk_state);
+ goto cleanup;
+ }
+ /* Parse the AML */
+
+ status = acpi_ps_parse_aml(walk_state);
+ /* Walk state was deleted by parse_aml */
+
+ cleanup:
+ acpi_ps_delete_parse_tree(op);
+ return_ACPI_STATUS(status);
+}