void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) { union acpi_generic_state *state; ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); if (!walk_state) { return; } if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { ACPI_ERROR((AE_INFO, "%p is not a valid walk state", walk_state)); return; } /* There should not be any open scopes */ if (walk_state->parser_state.scope) { ACPI_ERROR((AE_INFO, "%p walk still has a scope list", walk_state)); acpi_ps_cleanup_scope(&walk_state->parser_state); } /* Always must free any linked control states */ while (walk_state->control_state) { state = walk_state->control_state; walk_state->control_state = state->common.next; acpi_ut_delete_generic_state(state); } /* Always must free any linked parse states */ while (walk_state->scope_info) { state = walk_state->scope_info; walk_state->scope_info = state->common.next; acpi_ut_delete_generic_state(state); } /* Always must free any stacked result states */ while (walk_state->results) { state = walk_state->results; walk_state->results = state->common.next; acpi_ut_delete_generic_state(state); } ACPI_FREE(walk_state); return_VOID; }
acpi_status acpi_ds_scope_stack_pop ( acpi_walk_state *walk_state) { acpi_generic_state *scope_info; FUNCTION_TRACE ("Ds_scope_stack_pop"); /* * Pop scope info object off the stack. */ scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info); if (!scope_info) { return_ACPI_STATUS (AE_STACK_UNDERFLOW); } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Popped object type %X\n", scope_info->common.value)); acpi_ut_delete_generic_state (scope_info); return_ACPI_STATUS (AE_OK); }
static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) { union acpi_generic_state *info = (union acpi_generic_state *)context; union acpi_operand_object *handler_obj; ACPI_FUNCTION_ENTRY(); /* Invoke a global notify handler if installed */ if (info->notify.global->handler) { info->notify.global->handler(info->notify.node, info->notify.value, info->notify.global->context); } /* Now invoke the local notify handler(s) if any are installed */ handler_obj = info->notify.handler_list_head; while (handler_obj) { handler_obj->notify.handler(info->notify.node, info->notify.value, handler_obj->notify.context); handler_obj = handler_obj->notify.next[info->notify.handler_list_id]; } /* All done with the info object */ acpi_ut_delete_generic_state(info); }
void acpi_ps_pop_scope(struct acpi_parse_state *parser_state, union acpi_parse_object **op, u32 * arg_list, u32 * arg_count) { union acpi_generic_state *scope = parser_state->scope; ACPI_FUNCTION_TRACE(ps_pop_scope); /* Only pop the scope if there is in fact a next scope */ if (scope->common.next) { scope = acpi_ut_pop_generic_state(&parser_state->scope); /* Return to parsing previous op */ *op = scope->parse_scope.op; *arg_list = scope->parse_scope.arg_list; *arg_count = scope->parse_scope.arg_count; parser_state->pkg_end = scope->parse_scope.pkg_end; /* All done with this scope state structure */ acpi_ut_delete_generic_state(scope); } else { /* Empty parse stack, prepare to fetch next opcode */ *op = NULL; *arg_list = 0; *arg_count = 0; } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped Op %p Args %X\n", *op, *arg_count)); return_VOID; }
static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) { union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_stack_pop); /* Check for stack underflow */ if (walk_state->results == NULL) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Result stack underflow - State=%p\n", walk_state)); return (AE_AML_NO_OPERAND); } if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { ACPI_ERROR((AE_INFO, "Insufficient result stack size")); return (AE_AML_INTERNAL); } state = acpi_ut_pop_generic_state(&walk_state->results); acpi_ut_delete_generic_state(state); /* Decrease the length of result stack by the length of frame */ walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Result=%p RemainingResults=%X State=%p\n", state, walk_state->result_count, walk_state)); return (AE_OK); }
static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) { union acpi_generic_state *notify_info = (union acpi_generic_state *)context; acpi_notify_handler global_handler = NULL; void *global_context = NULL; union acpi_operand_object *handler_obj; ACPI_FUNCTION_ENTRY(); /* * We will invoke a global notify handler if installed. This is done * _before_ we invoke the per-device handler attached to the device. */ if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { /* Global system notification handler */ if (acpi_gbl_system_notify.handler) { global_handler = acpi_gbl_system_notify.handler; global_context = acpi_gbl_system_notify.context; } } else { /* Global driver notification handler */ if (acpi_gbl_device_notify.handler) { global_handler = acpi_gbl_device_notify.handler; global_context = acpi_gbl_device_notify.context; } } /* Invoke the system handler first, if present */ if (global_handler) { global_handler(notify_info->notify.node, notify_info->notify.value, global_context); } /* Now invoke the per-device handler, if present */ handler_obj = notify_info->notify.handler_obj; if (handler_obj) { struct acpi_object_notify_handler *notifier; notifier = &handler_obj->notify; while (notifier) { notifier->handler(notify_info->notify.node, notify_info->notify.value, notifier->context); notifier = notifier->next; } } /* All done with the info object */ acpi_ut_delete_generic_state(notify_info); }
void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state) { union acpi_generic_state *scope; ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state); if (!parser_state) { return_VOID; } /* Delete anything on the scope stack */ while (parser_state->scope) { scope = acpi_ut_pop_generic_state(&parser_state->scope); acpi_ut_delete_generic_state(scope); } return_VOID; }
acpi_status acpi_ds_scope_stack_pop ( struct acpi_walk_state *walk_state) { union acpi_generic_state *scope_info; union acpi_generic_state *new_scope_info; ACPI_FUNCTION_TRACE ("ds_scope_stack_pop"); /* * Pop scope info object off the stack. */ scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info); if (!scope_info) { return_ACPI_STATUS (AE_STACK_UNDERFLOW); } walk_state->scope_depth--; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%.2d] Popped scope [%4.4s] (%s), New scope -> ", (u32) walk_state->scope_depth, acpi_ut_get_node_name (scope_info->scope.node), acpi_ut_get_type_name (scope_info->common.value))); new_scope_info = walk_state->scope_info; if (new_scope_info) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[%4.4s] (%s)\n", acpi_ut_get_node_name (new_scope_info->scope.node), acpi_ut_get_type_name (new_scope_info->common.value))); } else { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[\\___] (ROOT)\n")); } acpi_ut_delete_generic_state (scope_info); return_ACPI_STATUS (AE_OK); }
/**************************************************************************** * * FUNCTION: acpi_ds_scope_stack_clear * * PARAMETERS: walk_state - Current state * * RETURN: None * * DESCRIPTION: Pop (and free) everything on the scope stack except the * root scope object (which remains at the stack top.) * ***************************************************************************/ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) { union acpi_generic_state *scope_info; ACPI_FUNCTION_NAME(ds_scope_stack_clear); while (walk_state->scope_info) { /* Pop a scope off the stack */ scope_info = walk_state->scope_info; walk_state->scope_info = scope_info->scope.next; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Popped object type (%s)\n", acpi_ut_get_type_name(scope_info->common. value))); acpi_ut_delete_generic_state(scope_info); } }
void acpi_ds_scope_stack_clear ( acpi_walk_state *walk_state) { acpi_generic_state *scope_info; PROC_NAME ("Ds_scope_stack_clear"); while (walk_state->scope_info) { /* Pop a scope off the stack */ scope_info = walk_state->scope_info; walk_state->scope_info = scope_info->scope.next; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Popped object type %X\n", scope_info->common.value)); acpi_ut_delete_generic_state (scope_info); } }
acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) { union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_stack_pop); /* Check for stack underflow */ if (walk_state->results == NULL) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Underflow - State=%p\n", walk_state)); return (AE_AML_NO_OPERAND); } state = acpi_ut_pop_generic_state(&walk_state->results); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Result=%p RemainingResults=%X State=%p\n", state, state->results.num_results, walk_state)); acpi_ut_delete_generic_state(state); return (AE_OK); }
acpi_status acpi_ps_complete_op(struct acpi_walk_state *walk_state, union acpi_parse_object **op, acpi_status status) { acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); /* * Finished one argument of the containing scope */ walk_state->parser_state.scope->parse_scope.arg_count--; /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } *op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method */ walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); if (*op) { walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } /* Close this iteration of the While loop */ walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } status = AE_OK; break; case AE_CTRL_TERMINATE: /* Clean up */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state (&walk_state->control_state)); } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); return_ACPI_STATUS(AE_OK); default: /* All other non-AE_OK status */ do { if (*op) { /* * These Opcodes need to be removed from the namespace because they * get created even if these opcodes cannot be created due to * errors. */ if (((*op)->common.aml_opcode == AML_REGION_OP) || ((*op)->common.aml_opcode == AML_DATA_REGION_OP)) { acpi_ns_delete_children((*op)->common. node); acpi_ns_remove_node((*op)->common.node); (*op)->common.node = NULL; acpi_ps_delete_parse_tree(*op); } status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); #if 0 /* * TBD: Cleanup parse ops on error */ if (*op == NULL) { acpi_ps_pop_scope(parser_state, op, &walk_state->arg_types, &walk_state->arg_count); } #endif walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) { /* * There was something that went wrong while executing code at the * module-level. We need to skip parsing whatever caused the * error and keep going. One runtime error during the table load * should not cause the entire table to not be loaded. This is * because there could be correct AML beyond the parts that caused * the runtime error. */ ACPI_INFO(("Ignoring error and continuing table load")); return_ACPI_STATUS(AE_OK); } return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); } else { *op = NULL; } return_ACPI_STATUS(AE_OK); }
acpi_status acpi_ev_queue_notify_request ( struct acpi_namespace_node *node, u32 notify_value) { union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj = NULL; union acpi_generic_state *notify_info; acpi_status status = AE_OK; ACPI_FUNCTION_NAME ("ev_queue_notify_request"); /* * For value 3 (Ejection Request), some device method may need to be run. * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run. * For value 0x80 (Status Change) on the power button or sleep button, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify(%X) on node %p\n", notify_value, node)); if (notify_value <= 7) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n", acpi_notify_value_names[notify_value])); } else { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "notify value: 0x2.2_x **Device Specific**\n", notify_value)); } /* * Get the notify object attached to the NS Node */ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* We have the notify object, Get the right handler */ switch (node->type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { handler_obj = obj_desc->common_notify.system_notify; } else { handler_obj = obj_desc->common_notify.device_notify; } break; default: /* All other types are not supported */ return (AE_TYPE); } } /* If there is any handler to run, schedule the dispatcher */ if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { notify_info = acpi_ut_create_generic_state (); if (!notify_info) { return (AE_NO_MEMORY); } notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY; notify_info->notify.node = node; notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, acpi_ev_notify_dispatch, notify_info); if (ACPI_FAILURE (status)) { acpi_ut_delete_generic_state (notify_info); } } if (!handler_obj) { /* There is no per-device notify handler for this device */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for [%4.4s] node %p\n", acpi_ut_get_node_name (node), node)); } return (status); }
acpi_status acpi_ev_queue_notify_request(struct acpi_namespace_node *node, u32 notify_value) { union acpi_operand_object *obj_desc; union acpi_operand_object *handler_list_head = NULL; union acpi_generic_state *info; u8 handler_list_id = 0; acpi_status status = AE_OK; ACPI_FUNCTION_NAME(ev_queue_notify_request); /* Are Notifies allowed on this object? */ if (!acpi_ev_is_notify_object(node)) { return (AE_TYPE); } /* Get the correct notify list type (System or Device) */ if (notify_value <= ACPI_MAX_SYS_NOTIFY) { handler_list_id = ACPI_SYSTEM_HANDLER_LIST; } else { handler_list_id = ACPI_DEVICE_HANDLER_LIST; } /* Get the notify object attached to the namespace Node */ obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { /* We have an attached object, Get the correct handler list */ handler_list_head = obj_desc->common_notify.notify_list[handler_list_id]; } /* * If there is no notify handler (Global or Local) * for this object, just ignore the notify */ if (!acpi_gbl_global_notify[handler_list_id].handler && !handler_list_head) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", acpi_ut_get_node_name(node), notify_value, node)); return (AE_OK); } /* Setup notify info and schedule the notify dispatcher */ info = acpi_ut_create_generic_state(); if (!info) { return (AE_NO_MEMORY); } info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; info->notify.node = node; info->notify.value = (u16)notify_value; info->notify.handler_list_id = handler_list_id; info->notify.handler_list_head = handler_list_head; info->notify.global = &acpi_gbl_global_notify[handler_list_id]; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type), notify_value, acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY), node)); status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, info); if (ACPI_FAILURE(status)) { acpi_ut_delete_generic_state(info); } return (status); }
acpi_status acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, union acpi_parse_object * op) { acpi_status status = AE_OK; union acpi_generic_state *control_state; ACPI_FUNCTION_NAME(ds_exec_end_control_op); switch (op->common.aml_opcode) { case AML_IF_OP: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); /* * Save the result of the predicate in case there is an * ELSE to come */ walk_state->last_predicate = (u8) walk_state->control_state->common.value; /* * Pop the control state that was created at the start * of the IF and free it */ control_state = acpi_ut_pop_generic_state(&walk_state->control_state); acpi_ut_delete_generic_state(control_state); break; case AML_ELSE_OP: break; case AML_WHILE_OP: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); if (walk_state->control_state->common.value) { /* Predicate was true, go back and evaluate it again! */ status = AE_CTRL_PENDING; } ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] termination! Op=%p\n", op)); /* Pop this control state and free it */ control_state = acpi_ut_pop_generic_state(&walk_state->control_state); walk_state->aml_last_while = control_state->control.aml_predicate_start; acpi_ut_delete_generic_state(control_state); break; case AML_RETURN_OP: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[RETURN_OP] Op=%p Arg=%p\n", op, op->common.value.arg)); /* * One optional operand -- the return value * It can be either an immediate operand or a result that * has been bubbled up the tree */ if (op->common.value.arg) { /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); /* Return statement has an immediate operand */ status = acpi_ds_create_operands(walk_state, op->common.value.arg); if (ACPI_FAILURE(status)) { return (status); } /* * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. */ status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); if (ACPI_FAILURE(status)) { return (status); } /* * Get the return value and save as the last result * value. This is the only place where walk_state->return_desc * is set to anything other than zero! */ walk_state->return_desc = walk_state->operands[0]; } else if ((walk_state->results) && (walk_state->results->results.num_results > 0)) { /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); /* * The return value has come from a previous calculation. * * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. * * Allow references created by the Index operator to return unchanged. */ if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) && (ACPI_GET_OBJECT_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_TYPE_LOCAL_REFERENCE) && ((walk_state->results->results.obj_desc[0])-> reference.opcode != AML_INDEX_OP)) { status = acpi_ex_resolve_to_value(&walk_state-> results->results. obj_desc[0], walk_state); if (ACPI_FAILURE(status)) { return (status); } } walk_state->return_desc = walk_state->results->results.obj_desc[0]; } else { /* No return operand */ if (walk_state->num_operands) { acpi_ut_remove_reference(walk_state-> operands[0]); } walk_state->operands[0] = NULL; walk_state->num_operands = 0; walk_state->return_desc = NULL; } ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Completed RETURN_OP State=%p, RetVal=%p\n", walk_state, walk_state->return_desc)); /* End the control method execution right now */ status = AE_CTRL_TERMINATE; break; case AML_NOOP_OP: /* Just do nothing! */ break; case AML_BREAK_POINT_OP: /* Call up to the OS service layer to handle this */ status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); /* If and when it returns, all done. */ break; case AML_BREAK_OP: case AML_CONTINUE_OP: /* ACPI 2.0 */ /* Pop and delete control states until we find a while */ while (walk_state->control_state && (walk_state->control_state->control.opcode != AML_WHILE_OP)) { control_state = acpi_ut_pop_generic_state(&walk_state-> control_state); acpi_ut_delete_generic_state(control_state); } /* No while found? */ if (!walk_state->control_state) { return (AE_AML_NO_WHILE); } /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ walk_state->aml_last_while = walk_state->control_state->control.package_end; /* Return status depending on opcode */ if (op->common.aml_opcode == AML_BREAK_OP) { status = AE_CTRL_BREAK; } else { status = AE_CTRL_CONTINUE; } break; default: ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p", op->common.aml_opcode, op)); status = AE_AML_BAD_OPCODE; break; } return (status); }
acpi_status acpi_ev_queue_notify_request(struct acpi_namespace_node * node, u32 notify_value) { union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj = NULL; union acpi_generic_state *notify_info; acpi_status status = AE_OK; ACPI_FUNCTION_NAME(ev_queue_notify_request); /* * For value 3 (Ejection Request), some device method may need to be run. * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need * to be run. * For value 0x80 (Status Change) on the power button or sleep button, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", acpi_ut_get_node_name(node), node, notify_value, acpi_ut_get_notify_name(notify_value))); /* Get the notify object attached to the NS Node */ obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { /* We have the notify object, Get the right handler */ switch (node->type) { /* Notify allowed only on these types */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { handler_obj = obj_desc->common_notify.system_notify; } else { handler_obj = obj_desc->common_notify.device_notify; } break; default: /* All other types are not supported */ return (AE_TYPE); } } /* * If there is any handler to run, schedule the dispatcher. * Check for: * 1) Global system notify handler * 2) Global device notify handler * 3) Per-device notify handler */ if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { notify_info = acpi_ut_create_generic_state(); if (!notify_info) { return (AE_NO_MEMORY); } if (!handler_obj) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Executing system notify handler for Notify (%4.4s, %X) " "node %p\n", acpi_ut_get_node_name(node), notify_value, node)); } notify_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; notify_info->notify.node = node; notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, notify_info); if (ACPI_FAILURE(status)) { acpi_ut_delete_generic_state(notify_info); } } else { /* There is no notify handler (per-device or system) for this device */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No notify handler for Notify (%4.4s, %X) node %p\n", acpi_ut_get_node_name(node), notify_value, node)); } return (status); }
acpi_status acpi_ps_complete_op(struct acpi_walk_state *walk_state, union acpi_parse_object **op, acpi_status status) { acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); /* * Finished one argument of the containing scope */ walk_state->parser_state.scope->parse_scope.arg_count--; /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } *op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method */ walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); if (*op) { walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } /* Close this iteration of the While loop */ walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } status = AE_OK; break; case AE_CTRL_TERMINATE: /* Clean up */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state (&walk_state->control_state)); } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); return_ACPI_STATUS(AE_OK); default: /* All other non-AE_OK status */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); #if 0 /* * TBD: Cleanup parse ops on error */ if (*op == NULL) { acpi_ps_pop_scope(parser_state, op, &walk_state->arg_types, &walk_state->arg_count); } #endif walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); } else { *op = NULL; } return_ACPI_STATUS(AE_OK); }
acpi_status acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info) { acpi_status status; struct acpi_namespace_node *node = NULL; union acpi_generic_state *scope_info; char *internal_path = NULL; ACPI_FUNCTION_TRACE("ns_evaluate_relative"); /* * Must have a valid object handle */ if (!info || !info->node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Build an internal name string for the method */ status = acpi_ns_internalize_name(pathname, &internal_path); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } scope_info = acpi_ut_create_generic_state(); if (!scope_info) { goto cleanup1; } /* Get the prefix handle and Node */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto cleanup; } info->node = acpi_ns_map_handle_to_node(info->node); if (!info->node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); status = AE_BAD_PARAMETER; goto cleanup; } /* Lookup the name in the namespace */ scope_info->scope.node = info->node; status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, &node); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n", pathname, acpi_format_exception(status))); goto cleanup; } /* * Now that we have a handle to the object, we can attempt to evaluate it. */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", pathname, node, acpi_ns_get_attached_object(node))); info->node = node; status = acpi_ns_evaluate_by_handle(info); ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n", pathname)); cleanup: acpi_ut_delete_generic_state(scope_info); cleanup1: ACPI_MEM_FREE(internal_path); return_ACPI_STATUS(status); }
acpi_status acpi_ut_walk_package_tree(union acpi_operand_object *source_object, void *target_object, acpi_pkg_callback walk_callback, void *context) { acpi_status status = AE_OK; union acpi_generic_state *state_list = NULL; union acpi_generic_state *state; union acpi_operand_object *this_source_obj; u32 this_index; ACPI_FUNCTION_TRACE(ut_walk_package_tree); state = acpi_ut_create_pkg_state(source_object, target_object, 0); if (!state) { return_ACPI_STATUS(AE_NO_MEMORY); } while (state) { /* Get one element of the package */ this_index = state->pkg.index; this_source_obj = state->pkg.source_object->package.elements[this_index]; state->pkg.this_target_obj = &state->pkg.source_object->package.elements[this_index]; /* * Check for: * 1) An uninitialized package element. It is completely * legal to declare a package and leave it uninitialized * 2) Not an internal object - can be a namespace node instead * 3) Any type other than a package. Packages are handled in else * case below. */ if ((!this_source_obj) || (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) != ACPI_DESC_TYPE_OPERAND) || (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) { status = walk_callback(ACPI_COPY_TYPE_SIMPLE, this_source_obj, state, context); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } state->pkg.index++; while (state->pkg.index >= state->pkg.source_object->package.count) { /* * We've handled all of the objects at this level, This means * that we have just completed a package. That package may * have contained one or more packages itself. * * Delete this state and pop the previous state (package). */ acpi_ut_delete_generic_state(state); state = acpi_ut_pop_generic_state(&state_list); /* Finished when there are no more states */ if (!state) { /* * We have handled all of the objects in the top level * package just add the length of the package objects * and exit */ return_ACPI_STATUS(AE_OK); } /* * Go back up a level and move the index past the just * completed package object. */ state->pkg.index++; } } else { /* This is a subobject of type package */ status = walk_callback(ACPI_COPY_TYPE_PACKAGE, this_source_obj, state, context); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Push the current state and create a new one * The callback above returned a new target package object. */ acpi_ut_push_generic_state(&state_list, state); state = acpi_ut_create_pkg_state(this_source_obj, state->pkg.this_target_obj, 0); if (!state) { /* Free any stacked Update State objects */ while (state_list) { state = acpi_ut_pop_generic_state (&state_list); acpi_ut_delete_generic_state(state); } return_ACPI_STATUS(AE_NO_MEMORY); } } } /* We should never get here */ ACPI_ERROR((AE_INFO, "State list did not terminate correctly")); return_ACPI_STATUS(AE_AML_INTERNAL); }
acpi_status acpi_ut_walk_package_tree ( acpi_operand_object *source_object, void *target_object, ACPI_PKG_CALLBACK walk_callback, void *context) { acpi_status status = AE_OK; acpi_generic_state *state_list = NULL; acpi_generic_state *state; u32 this_index; acpi_operand_object *this_source_obj; FUNCTION_TRACE ("Ut_walk_package_tree"); state = acpi_ut_create_pkg_state (source_object, target_object, 0); if (!state) { return_ACPI_STATUS (AE_NO_MEMORY); } while (state) { this_index = state->pkg.index; this_source_obj = (acpi_operand_object *) state->pkg.source_object->package.elements[this_index]; /* * Check for * 1) An uninitialized package element. It is completely * legal to declare a package and leave it uninitialized * 2) Not an internal object - can be a namespace node instead * 3) Any type other than a package. Packages are handled in else * case below. */ if ((!this_source_obj) || (!VALID_DESCRIPTOR_TYPE ( this_source_obj, ACPI_DESC_TYPE_INTERNAL)) || (!IS_THIS_OBJECT_TYPE ( this_source_obj, ACPI_TYPE_PACKAGE))) { status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj, state, context); if (ACPI_FAILURE (status)) { /* TBD: must delete package created up to this point */ return_ACPI_STATUS (status); } state->pkg.index++; while (state->pkg.index >= state->pkg.source_object->package.count) { /* * We've handled all of the objects at this level, This means * that we have just completed a package. That package may * have contained one or more packages itself. * * Delete this state and pop the previous state (package). */ acpi_ut_delete_generic_state (state); state = acpi_ut_pop_generic_state (&state_list); /* Finished when there are no more states */ if (!state) { /* * We have handled all of the objects in the top level * package just add the length of the package objects * and exit */ return_ACPI_STATUS (AE_OK); } /* * Go back up a level and move the index past the just * completed package object. */ state->pkg.index++; } } else { /* This is a sub-object of type package */ status = walk_callback (ACPI_COPY_TYPE_PACKAGE, this_source_obj, state, context); if (ACPI_FAILURE (status)) { /* TBD: must delete package created up to this point */ return_ACPI_STATUS (status); } /* * The callback above returned a new target package object. */ /* * Push the current state and create a new one */ acpi_ut_push_generic_state (&state_list, state); state = acpi_ut_create_pkg_state (this_source_obj, state->pkg.this_target_obj, 0); if (!state) { /* TBD: must delete package created up to this point */ return_ACPI_STATUS (AE_NO_MEMORY); } } } /* We should never get here */ return (AE_AML_INTERNAL); }
acpi_status acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) { acpi_status status = AE_OK; union acpi_generic_state *state_list = NULL; union acpi_operand_object *next_object = NULL; union acpi_generic_state *state; acpi_native_uint i; ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object); while (object) { /* Make sure that this isn't a namespace handle */ if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object)); return_ACPI_STATUS(AE_OK); } /* * All sub-objects must have their reference count incremented also. * Different object types have different subobjects. */ switch (ACPI_GET_OBJECT_TYPE(object)) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: /* Update the notify objects for these types (if present) */ acpi_ut_update_ref_count(object->common_notify. system_notify, action); acpi_ut_update_ref_count(object->common_notify. device_notify, action); break; case ACPI_TYPE_PACKAGE: /* * We must update all the sub-objects of the package, * each of whom may have their own sub-objects. */ for (i = 0; i < object->package.count; i++) { /* * Push each element onto the stack for later processing. * Note: There can be null elements within the package, * these are simply ignored */ status = acpi_ut_create_update_state_and_push (object->package.elements[i], action, &state_list); if (ACPI_FAILURE(status)) { goto error_exit; } } break; case ACPI_TYPE_BUFFER_FIELD: next_object = object->buffer_field.buffer_obj; break; case ACPI_TYPE_LOCAL_REGION_FIELD: next_object = object->field.region_obj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: next_object = object->bank_field.bank_obj; status = acpi_ut_create_update_state_and_push(object-> bank_field. region_obj, action, &state_list); if (ACPI_FAILURE(status)) { goto error_exit; } break; case ACPI_TYPE_LOCAL_INDEX_FIELD: next_object = object->index_field.index_obj; status = acpi_ut_create_update_state_and_push(object-> index_field. data_obj, action, &state_list); if (ACPI_FAILURE(status)) { goto error_exit; } break; case ACPI_TYPE_LOCAL_REFERENCE: /* * The target of an Index (a package, string, or buffer) must track * changes to the ref count of the index. */ if (object->reference.opcode == AML_INDEX_OP) { next_object = object->reference.object; } break; case ACPI_TYPE_REGION: default: break; /* No subobjects for all other types */ } /* * Now we can update the count in the main object. This can only * happen after we update the sub-objects in case this causes the * main object to be deleted. */ acpi_ut_update_ref_count(object, action); object = NULL; /* Move on to the next object to be updated */ if (next_object) { object = next_object; next_object = NULL; } else if (state_list) { state = acpi_ut_pop_generic_state(&state_list); object = state->update.object; acpi_ut_delete_generic_state(state); } } return_ACPI_STATUS(AE_OK); error_exit: ACPI_EXCEPTION((AE_INFO, status, "Could not update object reference count")); return_ACPI_STATUS(status); }