Commit 5eb3a43d authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] ACPICA 20040427 from Bob Moore

Completed a major overhaul of the GPE handling within ACPI CA.
There are now three types of GPEs:
wake-only; runtime-only; combination wake/run.

The only GPEs allowed to be combination wake/run are for
button-style devices such as a control-method power button,
control-method sleep button, or a notebook lid switch.
GPEs that have an _Lxx or _Exx method and are not referenced
by any _PRW methods are marked for "runtime" and hardware enabled.

Any GPE that is referenced by a _PRW method is marked for "wake"
(and disabled at runtime).  However, at sleep time, only those
GPEs that have been specifically enabled for wake via the
acpi_enable_gpe() interface will actually be hardware enabled.

A new external interface has been added, acpi_set_gpe_type()
that is meant to be used by device drivers to force a GPE
to a particular type.  It will be especially useful for the
drivers for the button devices mentioned above.

Completed restructuring of the ACPI CA initialization sequence
so that default operation region handlers are installed
before GPEs are initialized and the _PRW methods are executed.
This will prevent errors when the _PRW methods attempt to
access system memory or I/O space.

GPE enable/disable no longer reads the GPE enable register.
We now keep the enable info for runtime and wake separate
and in the GPE_EVENT_INFO.  We thus no longer depend on
the hardware to maintain these bits.

Always clear the wake status and fixed/GPE status bits
before sleep, even for state S5.

Improved the AML debugger output for displaying the
GPE blocks and their current status.

Added new strings for the _OSI method, of the form
"Windows 2001 SPx" where x = 0,1,2,3,4.

Fixed a problem where the physical address was incorrectly
calculated when the Load() operator was used to directly
load from an Operation Region (vs. loading from a Field object.)
Also added check for minimum table length for this case.

Fix for multiple mutex acquisition.  Restore original thread
SyncLevel on mutex release.

Added ACPI_VALID_SXDS flag to the acpi_get_object_info interface
for consistency with the other fields returned.

Shrunk the ACPI_GPE_EVENT_INFO structure by 40%.
There is one such structure for each GPE in the system,
so the size of this structure is important.

CPU stack requirement reduction:
Cleaned up the method execution and object evaluation paths
so that now a parameter structure is passed, instead of copying
the various method parameters over and over again.

In evregion.c:
Correctly exit and reenter the interpreter region if and only
if dispatching an operation region request to a user-installed
handler. Do not exit/reenter when dispatching to a default
handler (e.g., default system memory or I/O handlers)
parent a308df02
......@@ -145,8 +145,9 @@ acpi_ds_parse_method (
return_ACPI_STATUS (AE_NO_MEMORY);
}
status = acpi_ds_init_aml_walk (walk_state, op, node, obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, NULL, 1);
status = acpi_ds_init_aml_walk (walk_state, op, node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, 1);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (walk_state);
return_ACPI_STATUS (status);
......@@ -267,8 +268,9 @@ acpi_ds_call_control_method (
{
acpi_status status;
struct acpi_namespace_node *method_node;
union acpi_operand_object *obj_desc;
struct acpi_walk_state *next_walk_state;
union acpi_operand_object *obj_desc;
struct acpi_parameter_info info;
u32 i;
......@@ -309,7 +311,6 @@ acpi_ds_call_control_method (
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* Create and init a Root Node */
op = acpi_ps_create_scope_op ();
......@@ -320,7 +321,7 @@ acpi_ds_call_control_method (
status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
obj_desc->method.aml_start, obj_desc->method.aml_length,
NULL, NULL, 1);
NULL, 1);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (next_walk_state);
goto cleanup;
......@@ -348,9 +349,12 @@ acpi_ds_call_control_method (
*/
this_walk_state->operands [this_walk_state->num_operands] = NULL;
info.parameters = &this_walk_state->operands[0];
info.parameter_type = ACPI_PARAM_ARGS;
status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
obj_desc->method.aml_start, obj_desc->method.aml_length,
&this_walk_state->operands[0], NULL, 3);
&info, 3);
if (ACPI_FAILURE (status)) {
goto cleanup;
}
......
......@@ -105,7 +105,7 @@ acpi_ds_execute_arguments (
}
status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
aml_length, NULL, NULL, 1);
aml_length, NULL, 1);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (walk_state);
return_ACPI_STATUS (status);
......@@ -150,7 +150,7 @@ acpi_ds_execute_arguments (
/* Execute the opcode and arguments */
status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
aml_length, NULL, NULL, 3);
aml_length, NULL, 3);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (walk_state);
return_ACPI_STATUS (status);
......
......@@ -906,8 +906,7 @@ acpi_ds_init_aml_walk (
struct acpi_namespace_node *method_node,
u8 *aml_start,
u32 aml_length,
union acpi_operand_object **params,
union acpi_operand_object **return_obj_desc,
struct acpi_parameter_info *info,
u32 pass_number)
{
acpi_status status;
......@@ -926,8 +925,17 @@ acpi_ds_init_aml_walk (
/* The next_op of the next_walk will be the beginning of the method */
walk_state->next_op = NULL;
walk_state->params = params;
walk_state->caller_return_desc = return_obj_desc;
if (info) {
if (info->parameter_type == ACPI_PARAM_GPE) {
walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
info->parameters);
}
else {
walk_state->params = info->parameters;
walk_state->caller_return_desc = &info->return_object;
}
}
status = acpi_ps_init_scope (&walk_state->parser_state, op);
if (ACPI_FAILURE (status)) {
......@@ -949,7 +957,7 @@ acpi_ds_init_aml_walk (
/* Init the method arguments */
status = acpi_ds_method_data_init_args (params, ACPI_METHOD_NUM_ARGS, walk_state);
status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
......
......@@ -50,7 +50,7 @@
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize
* FUNCTION: acpi_ev_initialize_events
*
* PARAMETERS: None
*
......@@ -61,13 +61,13 @@
******************************************************************************/
acpi_status
acpi_ev_initialize (
acpi_ev_initialize_events (
void)
{
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_initialize");
ACPI_FUNCTION_TRACE ("ev_initialize_events");
/* Make sure we have ACPI tables */
......@@ -104,7 +104,7 @@ acpi_ev_initialize (
/*******************************************************************************
*
* FUNCTION: acpi_ev_handler_initialize
* FUNCTION: acpi_ev_install_xrupt_handlers
*
* PARAMETERS: None
*
......@@ -115,13 +115,13 @@ acpi_ev_initialize (
******************************************************************************/
acpi_status
acpi_ev_handler_initialize (
acpi_ev_install_xrupt_handlers (
void)
{
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_handler_initialize");
ACPI_FUNCTION_TRACE ("ev_install_xrupt_handlers");
/* Install the SCI handler */
......
......@@ -49,6 +49,244 @@
ACPI_MODULE_NAME ("evgpe")
/*******************************************************************************
*
* FUNCTION: acpi_ev_set_gpe_type
*
* PARAMETERS: gpe_event_info - GPE to set
* Type - New type
*
* RETURN: Status
*
* DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
*
******************************************************************************/
acpi_status
acpi_ev_set_gpe_type (
struct acpi_gpe_event_info *gpe_event_info,
u8 type)
{
ACPI_FUNCTION_TRACE ("ev_set_gpe_type");
/* Validate type and update register enable masks */
switch (type) {
case ACPI_GPE_TYPE_WAKE:
case ACPI_GPE_TYPE_RUNTIME:
case ACPI_GPE_TYPE_WAKE_RUN:
break;
default:
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/* Disable the GPE if currently enabled */
acpi_ev_disable_gpe (gpe_event_info);
/* Type was validated above */
gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */
gpe_event_info->flags |= type; /* Insert type */
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_update_gpe_enable_masks
*
* PARAMETERS: gpe_event_info - GPE to update
*
* RETURN: Status
*
* DESCRIPTION: Updates GPE register enable masks based on the GPE type
*
******************************************************************************/
acpi_status
acpi_ev_update_gpe_enable_masks (
struct acpi_gpe_event_info *gpe_event_info,
u8 type)
{
struct acpi_gpe_register_info *gpe_register_info;
u8 register_bit;
ACPI_FUNCTION_TRACE ("ev_update_gpe_enable_masks");
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return_ACPI_STATUS (AE_NOT_EXIST);
}
register_bit = gpe_event_info->register_bit;
/* 1) Disable case. Simply clear all enable bits */
if (type == ACPI_GPE_DISABLE) {
gpe_register_info->enable_for_wake &= ~register_bit;
gpe_register_info->enable_for_run &= ~register_bit;
return_ACPI_STATUS (AE_OK);
}
/* 2) Enable case. Set the appropriate enable bits */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
gpe_register_info->enable_for_wake |= register_bit;
gpe_register_info->enable_for_run &= ~register_bit;
break;
case ACPI_GPE_TYPE_RUNTIME:
gpe_register_info->enable_for_wake &= ~register_bit;
gpe_register_info->enable_for_run |= register_bit;
break;
case ACPI_GPE_TYPE_WAKE_RUN:
gpe_register_info->enable_for_wake |= register_bit;
gpe_register_info->enable_for_run |= register_bit;
break;
default:
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_enable_gpe
*
* PARAMETERS: gpe_event_info - GPE to enable
*
* RETURN: Status
*
* DESCRIPTION: Enable a GPE based on the GPE type
*
******************************************************************************/
acpi_status
acpi_ev_enable_gpe (
struct acpi_gpe_event_info *gpe_event_info,
u8 write_to_hardware)
{
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_enable_gpe");
/* Make sure HW enable masks are updated */
status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_ENABLE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Mark wake-enabled or HW enable, or both */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
gpe_event_info->flags |= ACPI_GPE_WAKE_ENABLED;
break;
case ACPI_GPE_TYPE_WAKE_RUN:
gpe_event_info->flags |= ACPI_GPE_WAKE_ENABLED;
/* Fallthrough */
case ACPI_GPE_TYPE_RUNTIME:
gpe_event_info->flags |= ACPI_GPE_RUN_ENABLED;
if (write_to_hardware) {
/* Clear the GPE (of stale events), then enable it */
status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Enable the requested runtime GPE */
status = acpi_hw_enable_gpe (gpe_event_info);
}
break;
default:
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_disable_gpe
*
* PARAMETERS: gpe_event_info - GPE to disable
*
* RETURN: Status
*
* DESCRIPTION: Disable a GPE based on the GPE type
*
******************************************************************************/
acpi_status
acpi_ev_disable_gpe (
struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_disable_gpe");
if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
return_ACPI_STATUS (AE_OK);
}
/* Make sure HW enable masks are updated */
status = acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Mark wake-disabled or HW disable, or both */
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
case ACPI_GPE_TYPE_WAKE:
gpe_event_info->flags &= ~ACPI_GPE_WAKE_ENABLED;
break;
case ACPI_GPE_TYPE_WAKE_RUN:
gpe_event_info->flags &= ~ACPI_GPE_WAKE_ENABLED;
/* Fallthrough */
case ACPI_GPE_TYPE_RUNTIME:
/* Disable the requested runtime GPE */
gpe_event_info->flags &= ~ACPI_GPE_RUN_ENABLED;
status = acpi_hw_disable_gpe (gpe_event_info);
break;
default:
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_event_info
......@@ -139,7 +377,8 @@ acpi_ev_gpe_detect (
u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
u8 enabled_status_byte;
struct acpi_gpe_register_info *gpe_register_info;
u32 in_value;
u32 status_reg;
u32 enable_reg;
acpi_status status;
struct acpi_gpe_block_info *gpe_block;
u32 i;
......@@ -171,33 +410,32 @@ acpi_ev_gpe_detect (
/* Read the Status Register */
status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &status_reg,
&gpe_register_info->status_address);
gpe_register_info->status = (u8) in_value;
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
/* Read the Enable Register */
status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value,
status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &enable_reg,
&gpe_register_info->enable_address);
gpe_register_info->enable = (u8) in_value;
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
"GPE pair: Status %8.8X%8.8X = %02X, Enable %8.8X%8.8X = %02X\n",
ACPI_FORMAT_UINT64 (gpe_register_info->status_address.address),
gpe_register_info->status,
ACPI_FORMAT_UINT64 (gpe_register_info->enable_address.address),
gpe_register_info->enable));
ACPI_FORMAT_UINT64 (
gpe_register_info->status_address.address),
status_reg,
ACPI_FORMAT_UINT64 (
gpe_register_info->enable_address.address),
enable_reg));
/* First check if there is anything active at all in this register */
enabled_status_byte = (u8) (gpe_register_info->status &
gpe_register_info->enable);
enabled_status_byte = (u8) (status_reg & enable_reg);
if (!enabled_status_byte) {
/* No active GPEs in this register, move on */
......@@ -255,6 +493,7 @@ acpi_ev_asynch_execute_gpe_method (
u32 gpe_number = 0;
acpi_status status;
struct acpi_gpe_event_info local_gpe_event_info;
struct acpi_parameter_info info;
ACPI_FUNCTION_TRACE ("ev_asynch_execute_gpe_method");
......@@ -283,23 +522,33 @@ acpi_ev_asynch_execute_gpe_method (
return_VOID;
}
if (local_gpe_event_info.method_node) {
/*
* Must check for control method type dispatch one more
* time to avoid race with ev_gpe_install_handler
*/
if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) {
/*
* Invoke the GPE Method (_Lxx, _Exx):
* (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
* control method that corresponds to this GPE
*/
status = acpi_ns_evaluate_by_handle (local_gpe_event_info.method_node, NULL, NULL);
info.node = local_gpe_event_info.dispatch.method_node;
info.parameters = ACPI_CAST_PTR (union acpi_operand_object *, gpe_event_info);
info.parameter_type = ACPI_PARAM_GPE;
status = acpi_ns_evaluate_by_handle (&info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR (("%s while evaluating method [%4.4s] for GPE[%2X]\n",
ACPI_REPORT_ERROR ((
"%s while evaluating method [%4.4s] for GPE[%2X]\n",
acpi_format_exception (status),
acpi_ut_get_node_name (local_gpe_event_info.method_node), gpe_number));
acpi_ut_get_node_name (local_gpe_event_info.dispatch.method_node),
gpe_number));
}
}
if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) {
/*
* GPE is level-triggered, we clear the GPE status bit after handling
* the event.
* GPE is level-triggered, we clear the GPE status bit after
* handling the event.
*/
status = acpi_hw_clear_gpe (&local_gpe_event_info);
if (ACPI_FAILURE (status)) {
......@@ -354,6 +603,15 @@ acpi_ev_gpe_dispatch (
}
}
/* Save current system state */
if (acpi_gbl_system_awake_and_running) {
gpe_event_info->flags |= ACPI_GPE_SYSTEM_RUNNING;
}
else {
gpe_event_info->flags &= ~ACPI_GPE_SYSTEM_RUNNING;
}
/*
* Dispatch the GPE to either an installed handler, or the control
* method associated with this GPE (_Lxx or _Exx).
......@@ -361,10 +619,13 @@ acpi_ev_gpe_dispatch (
* If there is neither a handler nor a method, we disable the level to
* prevent further events from coming in here.
*/
if (gpe_event_info->handler) {
switch (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) {
case ACPI_GPE_DISPATCH_HANDLER:
/* Invoke the installed handler (at interrupt level) */
gpe_event_info->handler (gpe_event_info->context);
gpe_event_info->dispatch.handler->address (
gpe_event_info->dispatch.handler->context);
/* It is now safe to clear level-triggered events. */
......@@ -377,8 +638,10 @@ acpi_ev_gpe_dispatch (
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
}
else if (gpe_event_info->method_node) {
break;
case ACPI_GPE_DISPATCH_METHOD:
/*
* Disable GPE, so it doesn't keep firing before the method has a
* chance to run.
......@@ -402,8 +665,10 @@ acpi_ev_gpe_dispatch (
"acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
gpe_number));
}
}
else {
break;
default:
/* No handler or method to run! */
ACPI_REPORT_ERROR ((
......@@ -421,8 +686,61 @@ acpi_ev_gpe_dispatch (
gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
break;
}
return_VALUE (ACPI_INTERRUPT_HANDLED);
}
#ifdef ACPI_GPE_NOTIFY_CHECK
/*******************************************************************************
* NOT USED, PROTOTYPE ONLY AND WILL PROBABLY BE REMOVED
*
* FUNCTION: acpi_ev_check_for_wake_only_gpe
*
* PARAMETERS: gpe_event_info - info for this GPE
*
* RETURN: Status
*
* DESCRIPTION: Determine if a a GPE is "wake-only".
*
* Called from Notify() code in interpreter when a "device_wake"
* Notify comes in.
*
******************************************************************************/
acpi_status
acpi_ev_check_for_wake_only_gpe (
struct acpi_gpe_event_info *gpe_event_info)
{
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_check_for_wake_only_gpe");
if ((gpe_event_info) && /* Only >0 for _Lxx/_Exx */
((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) /* System state at GPE time */ {
/* This must be a wake-only GPE, disable it */
status = acpi_hw_disable_gpe (gpe_event_info);
/* Set GPE to wake-only. Do not change wake disabled/enabled status */
acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
ACPI_REPORT_INFO (("GPE %p was updated from wake/run to wake-only\n",
gpe_event_info));
/* This was a wake-only GPE */
return_ACPI_STATUS (AE_WAKE_ONLY_GPE);
}
return_ACPI_STATUS (AE_OK);
}
#endif
......@@ -53,7 +53,7 @@
*
* FUNCTION: acpi_ev_valid_gpe_event
*
* PARAMETERS: gpe_event_info - Info for this GPE
* PARAMETERS: gpe_event_info - Info for this GPE
*
* RETURN: TRUE if the gpe_event is valid
*
......@@ -154,6 +154,50 @@ acpi_ev_walk_gpe_list (
}
/******************************************************************************
*
* FUNCTION: acpi_ev_delete_gpe_handlers
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Delete all Handler objects found in the GPE data structs.
* Used only prior to termination.
*
******************************************************************************/
acpi_status
acpi_ev_delete_gpe_handlers (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
{
struct acpi_gpe_event_info *gpe_event_info;
u32 i;
u32 j;
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Now look at the individual GPEs in this byte register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
ACPI_MEM_FREE (gpe_event_info->dispatch.handler);
gpe_event_info->dispatch.handler = NULL;
gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK;
}
}
}
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_save_method_info
......@@ -206,16 +250,16 @@ acpi_ev_save_method_info (
* 2) Edge/Level determination is based on the 2nd character
* of the method name
*
* NOTE: Default GPE type is RUNTIME. May be changed later to WAKE if a
* _PRW object is found that points to this GPE.
* NOTE: Default GPE type is RUNTIME. May be changed later to WAKE
* if a _PRW object is found that points to this GPE.
*/
switch (name[1]) {
case 'L':
type = ACPI_GPE_LEVEL_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
type = ACPI_GPE_LEVEL_TRIGGERED;
break;
case 'E':
type = ACPI_GPE_EDGE_TRIGGERED | ACPI_GPE_TYPE_RUNTIME;
type = ACPI_GPE_EDGE_TRIGGERED;
break;
default:
......@@ -253,12 +297,19 @@ acpi_ev_save_method_info (
/*
* Now we can add this information to the gpe_event_info block
* for use during dispatch of this GPE.
* for use during dispatch of this GPE. Default type is RUNTIME, although
* this may change when the _PRW methods are executed later.
*/
gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
gpe_event_info->flags = type;
gpe_event_info->method_node = (struct acpi_namespace_node *) obj_handle;
gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD |
ACPI_GPE_TYPE_RUNTIME);
gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *) obj_handle;
/* Update enable mask, but don't enable the HW GPE as of yet */
acpi_ev_enable_gpe (gpe_event_info, FALSE);
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD,
"Registered GPE method %s as GPE number 0x%.2X\n",
......@@ -269,7 +320,7 @@ acpi_ev_save_method_info (
/*******************************************************************************
*
* FUNCTION: acpi_ev_get_gpe_type
* FUNCTION: acpi_ev_match_prw_and_gpe
*
* PARAMETERS: Callback from walk_namespace
*
......@@ -282,7 +333,7 @@ acpi_ev_save_method_info (
******************************************************************************/
static acpi_status
acpi_ev_get_gpe_type (
acpi_ev_match_prw_and_gpe (
acpi_handle obj_handle,
u32 level,
void *info,
......@@ -299,7 +350,7 @@ acpi_ev_get_gpe_type (
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_get_gpe_type");
ACPI_FUNCTION_TRACE ("ev_match_prw_and_gpe");
/* Check for a _PRW method under this device */
......@@ -369,10 +420,13 @@ acpi_ev_get_gpe_type (
if ((gpe_device == target_gpe_device) &&
(gpe_number >= gpe_block->block_base_number) &&
(gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) {
/* Mark GPE for WAKE but DISABLED (even for wake) */
gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
gpe_event_info->flags |= ACPI_GPE_TYPE_WAKE;
/* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
acpi_ev_set_gpe_type (gpe_event_info, ACPI_GPE_TYPE_WAKE);
acpi_ev_update_gpe_enable_masks (gpe_event_info, ACPI_GPE_DISABLE);
}
cleanup:
......@@ -740,7 +794,7 @@ acpi_ev_create_gpe_info_blocks (
/* Init the event_info for each GPE within this register */
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
this_event->bit_mask = acpi_gbl_decode_to8bit[j];
this_event->register_bit = acpi_gbl_decode_to8bit[j];
this_event->register_info = this_register;
this_event++;
}
......@@ -815,6 +869,7 @@ acpi_ev_create_gpe_block (
acpi_status status;
struct acpi_gpe_walk_info gpe_info;
ACPI_FUNCTION_TRACE ("ev_create_gpe_block");
......@@ -833,6 +888,7 @@ acpi_ev_create_gpe_block (
gpe_block->register_count = register_count;
gpe_block->block_base_number = gpe_block_base_number;
gpe_block->node = gpe_device;
ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address, sizeof (struct acpi_generic_address));
......@@ -852,18 +908,6 @@ acpi_ev_create_gpe_block (
return_ACPI_STATUS (status);
}
/* Dump info about this GPE block */
ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
"GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
gpe_block->block_base_number,
(u32) (gpe_block->block_base_number +
((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
gpe_device->name.ascii,
gpe_block->register_count,
ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
interrupt_level));
/* Find all GPE methods (_Lxx, _Exx) for this block */
status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
......@@ -871,27 +915,28 @@ acpi_ev_create_gpe_block (
gpe_block, NULL);
/*
* Runtime option: Should Wake GPEs be enabled at runtime? The default is
* No,they should only be enabled just as the machine goes to sleep.
* Runtime option: Should Wake GPEs be enabled at runtime? The default
* is No,they should only be enabled just as the machine goes to sleep.
*/
if (acpi_gbl_leave_wake_gpes_disabled) {
/*
* Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods. (Each
* GPE that has one or more _PRWs that reference it is by definition a
* WAKE GPE and will not be enabled while the machine is running.)
* Differentiate RUNTIME vs WAKE GPEs, via the _PRW control methods.
* (Each GPE that has one or more _PRWs that reference it is by
* definition a WAKE GPE and will not be enabled while the machine
* is running.)
*/
gpe_info.gpe_block = gpe_block;
gpe_info.gpe_device = gpe_device;
status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_get_gpe_type,
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, acpi_ev_match_prw_and_gpe,
&gpe_info, NULL);
}
/*
* Enable all GPEs in this block that are 1) "runtime" GPEs, and 2) have
* a corresponding _Lxx or _Exx method. All other GPEs must be enabled via
* the acpi_enable_gpe() external interface.
* Enable all GPEs in this block that are 1) "runtime" or "run/wake" GPEs,
* and 2) have a corresponding _Lxx or _Exx method. All other GPEs must
* be enabled via the acpi_enable_gpe() external interface.
*/
wake_gpe_count = 0;
gpe_enabled_count = 0;
......@@ -901,23 +946,35 @@ acpi_ev_create_gpe_block (
/* Get the info block for this particular GPE */
gpe_event_info = &gpe_block->event_info[(i * ACPI_GPE_REGISTER_WIDTH) + j];
if ((gpe_event_info->method_node) &&
((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_RUNTIME)) {
/* Enable this GPE, it is 1) RUNTIME and 2) has an _Lxx or _Exx method */
status = acpi_hw_enable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) &&
(gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
gpe_enabled_count++;
}
if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == ACPI_GPE_TYPE_WAKE) {
if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
wake_gpe_count++;
}
}
}
/* Dump info about this GPE block */
ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
"GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
gpe_block->block_base_number,
(u32) (gpe_block->block_base_number +
((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
gpe_device->name.ascii,
gpe_block->register_count,
ACPI_FORMAT_UINT64 (gpe_block->block_address.address),
interrupt_level));
/* Enable all valid GPEs found above */
status = acpi_hw_enable_runtime_gpe_block (NULL, gpe_block);
ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
wake_gpe_count, gpe_enabled_count));
......@@ -1054,7 +1111,8 @@ acpi_ev_gpe_initialize (
if ((register_count0 + register_count1) == 0) {
/* GPEs are not required by ACPI, this is OK */
ACPI_REPORT_INFO (("There are no GPE blocks defined in the FADT\n"));
ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
"There are no GPE blocks defined in the FADT\n"));
status = AE_OK;
goto cleanup;
}
......
......@@ -557,6 +557,10 @@ acpi_ev_terminate (void)
}
}
/* Deallocate all handler objects installed within GPE info structs */
status = acpi_ev_walk_gpe_list (acpi_ev_delete_gpe_handlers);
/* Return to original mode if necessary */
if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
......
......@@ -61,7 +61,7 @@ static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA
/*******************************************************************************
*
* FUNCTION: acpi_ev_init_address_spaces
* FUNCTION: acpi_ev_install_region_handlers
*
* PARAMETERS: None
*
......@@ -72,15 +72,20 @@ static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPA
******************************************************************************/
acpi_status
acpi_ev_init_address_spaces (
acpi_ev_install_region_handlers (
void) {
acpi_status status;
acpi_native_uint i;
ACPI_FUNCTION_TRACE ("ev_init_address_spaces");
ACPI_FUNCTION_TRACE ("ev_install_region_handlers");
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/*
* All address spaces (PCI Config, EC, SMBus) are scope dependent
* and registration must occur for a specific device.
......@@ -99,9 +104,8 @@ acpi_ev_init_address_spaces (
* has already been installed (via acpi_install_address_space_handler).
* Similar for AE_SAME_HANDLER.
*/
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
status = acpi_ev_install_space_handler (acpi_gbl_root_node,
acpi_gbl_default_address_spaces[i],
ACPI_DEFAULT_HANDLER, NULL, NULL);
switch (status) {
......@@ -111,15 +115,63 @@ acpi_ev_init_address_spaces (
/* These exceptions are all OK */
status = AE_OK;
break;
default:
return_ACPI_STATUS (status);
goto unlock_and_exit;
}
}
return_ACPI_STATUS (AE_OK);
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_initialize_op_regions
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Execute _REG methods for all Operation Regions that have
* an installed default region handler.
*
******************************************************************************/
acpi_status
acpi_ev_initialize_op_regions (
void)
{
acpi_status status;
acpi_native_uint i;
ACPI_FUNCTION_TRACE ("ev_initialize_op_regions");
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/*
* Run the _REG methods for op_regions in each default address space
*/
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
/* TBD: Make sure handler is the DEFAULT handler, otherwise
* _REG will have already been run.
*/
status = acpi_ev_execute_reg_methods (acpi_gbl_root_node,
acpi_gbl_default_address_spaces[i]);
}
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (status);
}
......@@ -138,11 +190,12 @@ acpi_ev_init_address_spaces (
acpi_status
acpi_ev_execute_reg_method (
union acpi_operand_object *region_obj,
union acpi_operand_object *region_obj,
u32 function)
{
union acpi_operand_object *params[3];
union acpi_operand_object *region_obj2;
struct acpi_parameter_info info;
union acpi_operand_object *params[3];
union acpi_operand_object *region_obj2;
acpi_status status;
......@@ -159,10 +212,11 @@ acpi_ev_execute_reg_method (
}
/*
* _REG method has two arguments
* Arg0: Integer: Operation region space ID
* The _REG method has two arguments:
*
* Arg0, Integer: Operation region space ID
* Same value as region_obj->Region.space_id
* Arg1: Integer: connection status
* Arg1, Integer: connection status
* 1 for connecting the handler,
* 0 for disconnecting the handler
* Passed as a parameter
......@@ -184,10 +238,15 @@ acpi_ev_execute_reg_method (
params[1]->integer.value = function;
params[2] = NULL;
info.node = region_obj2->extra.method_REG;
info.parameters = params;
info.parameter_type = ACPI_PARAM_ARGS;
/* Execute the method, no return value */
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL));
status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL);
ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (
ACPI_TYPE_METHOD, info.node, NULL));
status = acpi_ns_evaluate_by_handle (&info);
acpi_ut_remove_reference (params[1]);
......@@ -326,7 +385,7 @@ acpi_ev_address_space_dispatch (
ACPI_FORMAT_UINT64 (address),
acpi_ut_get_region_name (region_obj->region.space_id)));
if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* For handlers other than the default (supplied) handlers, we must
* exit the interpreter because the handler *might* block -- we don't
......@@ -347,7 +406,7 @@ acpi_ev_address_space_dispatch (
acpi_format_exception (status)));
}
if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
if (!(handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
......@@ -676,6 +735,273 @@ acpi_ev_install_handler (
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_space_handler
*
* PARAMETERS: Node - Namespace node for the device
* space_id - The address space ID
* Handler - Address of the handler
* Setup - Address of the setup function
* Context - Value passed to the handler on each access
*
* RETURN: Status
*
* DESCRIPTION: Install a handler for all op_regions of a given space_id.
* Assumes namespace is locked
*
******************************************************************************/
acpi_status
acpi_ev_install_space_handler (
struct acpi_namespace_node *node,
acpi_adr_space_type space_id,
acpi_adr_space_handler handler,
acpi_adr_space_setup setup,
void *context)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj;
acpi_status status;
acpi_object_type type;
u16 flags = 0;
ACPI_FUNCTION_TRACE ("ev_install_space_handler");
/*
* This registration is valid for only the types below
* and the root. This is where the default handlers
* get placed.
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR) &&
(node->type != ACPI_TYPE_THERMAL) &&
(node != acpi_gbl_root_node)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if (handler == ACPI_DEFAULT_HANDLER) {
flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
handler = acpi_ex_system_memory_space_handler;
setup = acpi_ev_system_memory_region_setup;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
handler = acpi_ex_system_io_space_handler;
setup = acpi_ev_io_space_region_setup;
break;
case ACPI_ADR_SPACE_PCI_CONFIG:
handler = acpi_ex_pci_config_space_handler;
setup = acpi_ev_pci_config_region_setup;
break;
case ACPI_ADR_SPACE_CMOS:
handler = acpi_ex_cmos_space_handler;
setup = acpi_ev_cmos_region_setup;
break;
case ACPI_ADR_SPACE_PCI_BAR_TARGET:
handler = acpi_ex_pci_bar_space_handler;
setup = acpi_ev_pci_bar_region_setup;
break;
case ACPI_ADR_SPACE_DATA_TABLE:
handler = acpi_ex_data_table_space_handler;
setup = NULL;
break;
default:
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
}
/* If the caller hasn't specified a setup routine, use the default */
if (!setup) {
setup = acpi_ev_default_region_setup;
}
/* Check for an existing internal object */
obj_desc = acpi_ns_get_attached_object (node);
if (obj_desc) {
/*
* The attached device object already exists.
* Make sure the handler is not already installed.
*/
handler_obj = obj_desc->device.handler;
/* Walk the handler list for this device */
while (handler_obj) {
/* Same space_id indicates a handler already installed */
if (handler_obj->address_space.space_id == space_id) {
if (handler_obj->address_space.handler == handler) {
/*
* It is (relatively) OK to attempt to install the SAME
* handler twice. This can easily happen with PCI_Config space.
*/
status = AE_SAME_HANDLER;
goto unlock_and_exit;
}
else {
/* A handler is already installed */
status = AE_ALREADY_EXISTS;
}
goto unlock_and_exit;
}
/* Walk the linked list of handlers */
handler_obj = handler_obj->address_space.next;
}
}
else {
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Creating object on Device %p while installing handler\n", node));
/* obj_desc does not exist, create one */
if (node->type == ACPI_TYPE_ANY) {
type = ACPI_TYPE_DEVICE;
}
else {
type = node->type;
}
obj_desc = acpi_ut_create_internal_object (type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
/* Init new descriptor */
obj_desc->common.type = (u8) type;
/* Attach the new object to the Node */
status = acpi_ns_attach_object (node, obj_desc, type);
/* Remove local reference to the object */
acpi_ut_remove_reference (obj_desc);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
}
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
acpi_ut_get_region_name (space_id), space_id,
acpi_ut_get_node_name (node), node, obj_desc));
/*
* Install the handler
*
* At this point there is no existing handler.
* Just allocate the object for the handler and link it
* into the list.
*/
handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
if (!handler_obj) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
/* Init handler obj */
handler_obj->address_space.space_id = (u8) space_id;
handler_obj->address_space.hflags = flags;
handler_obj->address_space.region_list = NULL;
handler_obj->address_space.node = node;
handler_obj->address_space.handler = handler;
handler_obj->address_space.context = context;
handler_obj->address_space.setup = setup;
/* Install at head of Device.address_space list */
handler_obj->address_space.next = obj_desc->device.handler;
/*
* The Device object is the first reference on the handler_obj.
* Each region that uses the handler adds a reference.
*/
obj_desc->device.handler = handler_obj;
/*
* Walk the namespace finding all of the regions this
* handler will manage.
*
* Start at the device and search the branch toward
* the leaf nodes until either the leaf is encountered or
* a device is detected that has an address handler of the
* same type.
*
* In either case, back up and search down the remainder
* of the branch
*/
status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
handler_obj, NULL);
unlock_and_exit:
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_methods
*
* PARAMETERS: Node - Namespace node for the device
* space_id - The address space ID
*
* RETURN: Status
*
* DESCRIPTION: Run _REG methods for the Space ID;
* Note: assumes namespace is locked, or system init time.
*
******************************************************************************/
acpi_status
acpi_ev_execute_reg_methods (
struct acpi_namespace_node *node,
acpi_adr_space_type space_id)
{
acpi_status status;
ACPI_FUNCTION_TRACE ("ev_execute_reg_methods");
/*
* Run all _REG methods for all Operation Regions for this
* space ID. This is a separate walk in order to handle any
* interdependencies between regions and _REG methods. (i.e. handlers
* must be installed for all regions of this Space ID before we
* can run any _REG methods)
*/
status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
&space_id, NULL);
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_reg_run
......@@ -693,19 +1019,13 @@ acpi_ev_reg_run (
void *context,
void **return_value)
{
union acpi_operand_object *handler_obj;
union acpi_operand_object *obj_desc;
struct acpi_namespace_node *node;
acpi_adr_space_type space_id;
acpi_status status;
handler_obj = (union acpi_operand_object *) context;
/* Parameter validation */
if (!handler_obj) {
return (AE_OK);
}
space_id = *ACPI_CAST_PTR (acpi_adr_space_type, context);
/* Convert and validate the device handle */
......@@ -732,10 +1052,9 @@ acpi_ev_reg_run (
return (AE_OK);
}
/* Object is a Region */
if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
if (obj_desc->region.space_id != space_id) {
/*
* This region is for a different address space
* -- just ignore it
......
......@@ -479,7 +479,7 @@ acpi_remove_notify_handler (
* gpe_block - GPE block (NULL == FADT GPEs)
* Type - Whether this GPE should be treated as an
* edge- or level-triggered interrupt.
* Handler - Address of the handler
* Address - Address of the handler
* Context - Value passed to the handler on each GPE
*
* RETURN: Status
......@@ -493,11 +493,12 @@ acpi_install_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
u32 type,
acpi_gpe_handler handler,
acpi_event_handler address,
void *context)
{
acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_handler_info *handler;
acpi_status status;
ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
......@@ -505,7 +506,7 @@ acpi_install_gpe_handler (
/* Parameter validation */
if (!handler) {
if ((!address) || (type > ACPI_GPE_XRUPT_TYPE_MASK)) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
......@@ -524,27 +525,41 @@ acpi_install_gpe_handler (
/* Make sure that there isn't a handler there already */
if (gpe_event_info->handler) {
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
/* Install the handler */
/* Allocate and init handler object */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
gpe_event_info->handler = handler;
gpe_event_info->context = context;
gpe_event_info->flags = (u8) type;
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
handler = ACPI_MEM_CALLOCATE (sizeof (struct acpi_handler_info));
if (!handler) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
handler->address = address;
handler->context = context;
handler->method_node = gpe_event_info->dispatch.method_node;
/* Clear the GPE (of stale events), the enable it */
/* Disable the GPE before installing the handler */
status = acpi_hw_clear_gpe (gpe_event_info);
status = acpi_ev_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
status = acpi_hw_enable_gpe (gpe_event_info);
/* Install the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
gpe_event_info->dispatch.handler = handler;
/* Setup up dispatch flags to indicate handler (vs. method) */
gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */
gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
unlock_and_exit:
......@@ -559,7 +574,7 @@ acpi_install_gpe_handler (
*
* PARAMETERS: gpe_number - The event to remove a handler
* gpe_block - GPE block (NULL == FADT GPEs)
* Handler - Address of the handler
* Address - Address of the handler
*
* RETURN: Status
*
......@@ -571,10 +586,11 @@ acpi_status
acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
acpi_gpe_handler handler)
acpi_event_handler address)
{
acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_handler_info *handler;
acpi_status status;
ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
......@@ -582,7 +598,7 @@ acpi_remove_gpe_handler (
/* Parameter validation */
if (!handler) {
if (!address) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
......@@ -599,28 +615,45 @@ acpi_remove_gpe_handler (
goto unlock_and_exit;
}
/* Disable the GPE before removing the handler */
/* Make sure that a handler is indeed installed */
status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}
/* Make sure that the installed handler is the same */
if (gpe_event_info->handler != handler) {
(void) acpi_hw_enable_gpe (gpe_event_info);
if (gpe_event_info->dispatch.handler->address != address) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Disable the GPE before removing the handler */
status = acpi_ev_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
/* Remove the handler */
acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
gpe_event_info->handler = NULL;
gpe_event_info->context = NULL;
handler = gpe_event_info->dispatch.handler;
/* Restore Method node (if any), set dispatch flags */
gpe_event_info->dispatch.method_node = handler->method_node;
gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */
if (handler->method_node) {
gpe_event_info->flags |= ACPI_GPE_DISPATCH_METHOD;
}
acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
/* Now we can free the handler object */
ACPI_MEM_FREE (handler);
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
......
......@@ -204,12 +204,11 @@ acpi_enable_event (
/*******************************************************************************
*
* FUNCTION: acpi_enable_gpe
* FUNCTION: acpi_set_gpe_type
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable?
* Called from ISR or not
* Type - New GPE type
*
* RETURN: Status
*
......@@ -218,26 +217,17 @@ acpi_enable_event (
******************************************************************************/
acpi_status
acpi_enable_gpe (
acpi_set_gpe_type (
acpi_handle gpe_device,
u32 gpe_number,
u32 flags)
u8 type)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
ACPI_FUNCTION_TRACE ("acpi_set_gpe_type");
/* Use semaphore lock if not executing at interrupt level */
if (flags & ACPI_NOT_ISR) {
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
/* Ensure that we have a valid GPE number */
......@@ -247,91 +237,79 @@ acpi_enable_gpe (
goto unlock_and_exit;
}
/* Check for Wake vs Runtime GPE */
if (flags & ACPI_EVENT_WAKE_ENABLE) {
/* Ensure the requested wake GPE is disabled */
status = acpi_hw_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
return_ACPI_STATUS (AE_OK);
}
/* Defer Enable of Wake GPE until sleep time */
/* Disable the GPE if enabled */
acpi_hw_enable_gpe_for_wakeup (gpe_event_info);
status = acpi_ev_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
else {
/* Enable the requested runtime GPE */
status = acpi_hw_enable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
}
/* Set the new type */
status = acpi_ev_set_gpe_type (gpe_event_info, type);
unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
}
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_disable_event
* FUNCTION: acpi_enable_gpe
*
* PARAMETERS: Event - The fixed eventto be enabled
* Flags - Reserved
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable?
* Called from ISR or not
*
* RETURN: Status
*
* DESCRIPTION: Disable an ACPI event (fixed)
* DESCRIPTION: Enable an ACPI event (general purpose)
*
******************************************************************************/
acpi_status
acpi_disable_event (
u32 event,
acpi_enable_gpe (
acpi_handle gpe_device,
u32 gpe_number,
u32 flags)
{
acpi_status status = AE_OK;
u32 value;
struct acpi_gpe_event_info *gpe_event_info;
ACPI_FUNCTION_TRACE ("acpi_disable_event");
ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
/* Decode the Fixed Event */
/* Use semaphore lock if not executing at interrupt level */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
if (flags & ACPI_NOT_ISR) {
status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
/*
* Disable the requested fixed event (by writing a zero to the
* enable register bit)
*/
status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
0, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Ensure that we have a valid GPE number */
status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
&value, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if (value != 0) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Could not disable %s events\n", acpi_ut_get_event_name (event)));
return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
}
/* Perform the enable */
status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
}
return_ACPI_STATUS (status);
}
......@@ -342,7 +320,7 @@ acpi_disable_event (
*
* PARAMETERS: gpe_device - Parent GPE Device
* gpe_number - GPE level within the GPE block
* Flags - Just enable, or also wake enable?
* Flags - Just disable, or also wake disable?
* Called from ISR or not
*
* RETURN: Status
......@@ -381,21 +359,69 @@ acpi_disable_gpe (
goto unlock_and_exit;
}
status = acpi_ev_disable_gpe (gpe_event_info);
unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
}
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_disable_event
*
* PARAMETERS: Event - The fixed eventto be enabled
* Flags - Reserved
*
* RETURN: Status
*
* DESCRIPTION: Disable an ACPI event (fixed)
*
******************************************************************************/
acpi_status
acpi_disable_event (
u32 event,
u32 flags)
{
acpi_status status = AE_OK;
u32 value;
ACPI_FUNCTION_TRACE ("acpi_disable_event");
/* Decode the Fixed Event */
if (event > ACPI_EVENT_MAX) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/*
* Only disable the requested GPE number for wake if specified.
* Otherwise, turn it totally off
* Disable the requested fixed event (by writing a zero to the
* enable register bit)
*/
if (flags & ACPI_EVENT_WAKE_DISABLE) {
acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
0, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
else {
status = acpi_hw_disable_gpe (gpe_event_info);
status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
&value, ACPI_MTX_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
unlock_and_exit:
if (flags & ACPI_NOT_ISR) {
(void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
if (value != 0) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Could not disable %s events\n", acpi_ut_get_event_name (event)));
return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
}
return_ACPI_STATUS (status);
}
......
......@@ -76,12 +76,8 @@ acpi_install_address_space_handler (
acpi_adr_space_setup setup,
void *context)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj;
struct acpi_namespace_node *node;
acpi_status status;
acpi_object_type type;
u16 flags = 0;
ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
......@@ -106,202 +102,16 @@ acpi_install_address_space_handler (
goto unlock_and_exit;
}
/*
* This registration is valid for only the types below
* and the root. This is where the default handlers
* get placed.
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR) &&
(node->type != ACPI_TYPE_THERMAL) &&
(node != acpi_gbl_root_node)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
if (handler == ACPI_DEFAULT_HANDLER) {
flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
handler = acpi_ex_system_memory_space_handler;
setup = acpi_ev_system_memory_region_setup;
break;
case ACPI_ADR_SPACE_SYSTEM_IO:
handler = acpi_ex_system_io_space_handler;
setup = acpi_ev_io_space_region_setup;
break;
case ACPI_ADR_SPACE_PCI_CONFIG:
handler = acpi_ex_pci_config_space_handler;
setup = acpi_ev_pci_config_region_setup;
break;
case ACPI_ADR_SPACE_CMOS:
handler = acpi_ex_cmos_space_handler;
setup = acpi_ev_cmos_region_setup;
break;
case ACPI_ADR_SPACE_PCI_BAR_TARGET:
handler = acpi_ex_pci_bar_space_handler;
setup = acpi_ev_pci_bar_region_setup;
break;
case ACPI_ADR_SPACE_DATA_TABLE:
handler = acpi_ex_data_table_space_handler;
setup = NULL;
break;
default:
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
}
/* If the caller hasn't specified a setup routine, use the default */
if (!setup) {
setup = acpi_ev_default_region_setup;
}
/* Check for an existing internal object */
obj_desc = acpi_ns_get_attached_object (node);
if (obj_desc) {
/*
* The attached device object already exists.
* Make sure the handler is not already installed.
*/
handler_obj = obj_desc->device.handler;
/* Walk the handler list for this device */
while (handler_obj) {
/* Same space_id indicates a handler already installed */
if(handler_obj->address_space.space_id == space_id) {
if (handler_obj->address_space.handler == handler) {
/*
* It is (relatively) OK to attempt to install the SAME
* handler twice. This can easily happen with PCI_Config space.
*/
status = AE_SAME_HANDLER;
goto unlock_and_exit;
}
else {
/* A handler is already installed */
status = AE_ALREADY_EXISTS;
}
goto unlock_and_exit;
}
/* Walk the linked list of handlers */
handler_obj = handler_obj->address_space.next;
}
}
else {
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Creating object on Device %p while installing handler\n", node));
/* obj_desc does not exist, create one */
if (node->type == ACPI_TYPE_ANY) {
type = ACPI_TYPE_DEVICE;
}
else {
type = node->type;
}
obj_desc = acpi_ut_create_internal_object (type);
if (!obj_desc) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
/* Init new descriptor */
obj_desc->common.type = (u8) type;
/* Attach the new object to the Node */
/* Install the handler for all Regions for this Space ID */
status = acpi_ns_attach_object (node, obj_desc, type);
/* Remove local reference to the object */
acpi_ut_remove_reference (obj_desc);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
}
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
acpi_ut_get_region_name (space_id), space_id,
acpi_ut_get_node_name (node), node, obj_desc));
/*
* Install the handler
*
* At this point there is no existing handler.
* Just allocate the object for the handler and link it
* into the list.
*/
handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
if (!handler_obj) {
status = AE_NO_MEMORY;
status = acpi_ev_install_space_handler (node, space_id, handler, setup, context);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
/* Init handler obj */
handler_obj->address_space.space_id = (u8) space_id;
handler_obj->address_space.hflags = flags;
handler_obj->address_space.region_list = NULL;
handler_obj->address_space.node = node;
handler_obj->address_space.handler = handler;
handler_obj->address_space.context = context;
handler_obj->address_space.setup = setup;
/* Install at head of Device.address_space list */
handler_obj->address_space.next = obj_desc->device.handler;
/*
* The Device object is the first reference on the handler_obj.
* Each region that uses the handler adds a reference.
*/
obj_desc->device.handler = handler_obj;
/*
* Walk the namespace finding all of the regions this
* handler will manage.
*
* Start at the device and search the branch toward
* the leaf nodes until either the leaf is encountered or
* a device is detected that has an address handler of the
* same type.
*
* In either case, back up and search down the remainder
* of the branch
*/
status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
handler_obj, NULL);
/*
* Now we can run the _REG methods for all Regions for this
* space ID. This is a separate walk in order to handle any
* interdependencies between regions and _REG methods. (i.e. handlers
* must be installed for all regions of this Space ID before we
* can run any _REG methods.
*/
status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
handler_obj, NULL);
/* Run all _REG methods for this address space */
status = acpi_ev_execute_reg_methods (node, space_id);
unlock_and_exit:
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
......
......@@ -48,6 +48,7 @@
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
#include <acpi/actables.h>
#include <acpi/acdispat.h>
#define _COMPONENT ACPI_EXECUTER
......@@ -285,7 +286,7 @@ acpi_ex_load_op (
union acpi_operand_object *ddb_handle;
union acpi_operand_object *buffer_desc = NULL;
struct acpi_table_header *table_ptr = NULL;
u8 *table_data_ptr;
acpi_physical_address address;
struct acpi_table_header table_header;
u32 i;
......@@ -300,18 +301,39 @@ acpi_ex_load_op (
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
obj_desc, acpi_ut_get_object_type_name (obj_desc)));
/* Get the table header */
/*
* If the Region Address and Length have not been previously evaluated,
* evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
status = acpi_ds_get_region_arguments (obj_desc);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
/* Get the base physical address of the region */
address = obj_desc->region.address;
/* Get the table length from the table header */
table_header.length = 0;
for (i = 0; i < sizeof (struct acpi_table_header); i++) {
for (i = 0; i < 8; i++) {
status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
(acpi_physical_address) i, 8,
(acpi_physical_address) i + address, 8,
((u8 *) &table_header) + i);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
/* Sanity check the table length */
if (table_header.length < sizeof (struct acpi_table_header)) {
return_ACPI_STATUS (AE_BAD_HEADER);
}
/* Allocate a buffer for the entire table */
table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
......@@ -319,17 +341,12 @@ acpi_ex_load_op (
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* Copy the header to the buffer */
ACPI_MEMCPY (table_ptr, &table_header, sizeof (struct acpi_table_header));
table_data_ptr = ACPI_PTR_ADD (u8, table_ptr, sizeof (struct acpi_table_header));
/* Get the table from the op region */
/* Get the entire table from the op region */
for (i = 0; i < table_header.length; i++) {
status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
(acpi_physical_address) i, 8,
((u8 *) table_data_ptr + i));
(acpi_physical_address) i + address, 8,
((u8 *) table_ptr + i));
if (ACPI_FAILURE (status)) {
goto cleanup;
}
......@@ -355,6 +372,12 @@ acpi_ex_load_op (
}
table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer);
/* Sanity check the table length */
if (table_ptr->length < sizeof (struct acpi_table_header)) {
return_ACPI_STATUS (AE_BAD_HEADER);
}
break;
......
......@@ -54,7 +54,7 @@
*
* FUNCTION: acpi_ex_unlink_mutex
*
* PARAMETERS: *obj_desc - The mutex to be unlinked
* PARAMETERS: obj_desc - The mutex to be unlinked
*
* RETURN: Status
*
......@@ -73,6 +73,8 @@ acpi_ex_unlink_mutex (
return;
}
/* Doubly linked list */
if (obj_desc->mutex.next) {
(obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
}
......@@ -90,8 +92,8 @@ acpi_ex_unlink_mutex (
*
* FUNCTION: acpi_ex_link_mutex
*
* PARAMETERS: *obj_desc - The mutex to be linked
* *list_head - head of the "acquired_mutex" list
* PARAMETERS: obj_desc - The mutex to be linked
* list_head - head of the "acquired_mutex" list
*
* RETURN: Status
*
......@@ -130,8 +132,8 @@ acpi_ex_link_mutex (
*
* FUNCTION: acpi_ex_acquire_mutex
*
* PARAMETERS: *time_desc - The 'time to delay' object descriptor
* *obj_desc - The object descriptor for this op
* PARAMETERS: time_desc - The 'time to delay' object descriptor
* obj_desc - The object descriptor for this op
*
* RETURN: Status
*
......@@ -173,9 +175,8 @@ acpi_ex_acquire_mutex (
return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
}
/*
* Support for multiple acquires by the owning thread
*/
/* Support for multiple acquires by the owning thread */
if (obj_desc->mutex.owner_thread) {
/* Special case for Global Lock, allow all threads */
......@@ -199,10 +200,11 @@ acpi_ex_acquire_mutex (
return_ACPI_STATUS (status);
}
/* Have the mutex, update mutex and walk info */
/* Have the mutex: update mutex and walk info and save the sync_level */
obj_desc->mutex.owner_thread = walk_state->thread;
obj_desc->mutex.owner_thread = walk_state->thread;
obj_desc->mutex.acquisition_depth = 1;
obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
......@@ -218,7 +220,7 @@ acpi_ex_acquire_mutex (
*
* FUNCTION: acpi_ex_release_mutex
*
* PARAMETERS: *obj_desc - The object descriptor for this op
* PARAMETERS: obj_desc - The object descriptor for this op
*
* RETURN: Status
*
......@@ -281,9 +283,8 @@ acpi_ex_release_mutex (
return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
}
/*
* Match multiple Acquires with multiple Releases
*/
/* Match multiple Acquires with multiple Releases */
obj_desc->mutex.acquisition_depth--;
if (obj_desc->mutex.acquisition_depth != 0) {
/* Just decrement the depth and return */
......@@ -299,10 +300,10 @@ acpi_ex_release_mutex (
status = acpi_ex_system_release_mutex (obj_desc);
/* Update the mutex and walk state */
/* Update the mutex and walk state, restore sync_level before acquire */
obj_desc->mutex.owner_thread = NULL;
walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
return_ACPI_STATUS (status);
}
......@@ -312,7 +313,7 @@ acpi_ex_release_mutex (
*
* FUNCTION: acpi_ex_release_all_mutexes
*
* PARAMETERS: *mutex_list - Head of the mutex list
* PARAMETERS: mutex_list - Head of the mutex list
*
* RETURN: Status
*
......@@ -332,9 +333,8 @@ acpi_ex_release_all_mutexes (
ACPI_FUNCTION_ENTRY ();
/*
* Traverse the list of owned mutexes, releasing each one.
*/
/* Traverse the list of owned mutexes, releasing each one */
while (next) {
this = next;
next = this->mutex.next;
......@@ -352,7 +352,11 @@ acpi_ex_release_all_mutexes (
/* Mark mutex unowned */
this->mutex.owner_thread = NULL;
this->mutex.owner_thread = NULL;
/* Update Thread sync_level (Last mutex is the important one) */
thread->current_sync_level = this->mutex.original_sync_level;
}
}
......
......@@ -97,6 +97,7 @@ acpi_ex_opcode_2A_0T_0R (
{
union acpi_operand_object **operand = &walk_state->operands[0];
struct acpi_namespace_node *node;
u32 value;
acpi_status status = AE_OK;
......@@ -113,16 +114,46 @@ acpi_ex_opcode_2A_0T_0R (
node = (struct acpi_namespace_node *) operand[0];
/* Second value is the notify value */
value = (u32) operand[1]->integer.value;
/* Notifies allowed on this object? */
if (!acpi_ev_is_notify_object (node)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n",
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Unexpected notify object type [%s]\n",
acpi_ut_get_type_name (node->type)));
status = AE_AML_OPERAND_TYPE;
break;
}
#ifdef ACPI_GPE_NOTIFY_CHECK
/*
* GPE method wake/notify check. Here, we want to ensure that we
* don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
* GPE method during system runtime. If we do, the GPE is marked
* as "wake-only" and disabled.
*
* 1) Is the Notify() value == device_wake?
* 2) Is this a GPE deferred method? (An _Lxx or _Exx method)
* 3) Did the original GPE happen at system runtime?
* (versus during wake)
*
* If all three cases are true, this is a wake-only GPE that should
* be disabled at runtime.
*/
if (value == 2) /* device_wake */ {
status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
if (ACPI_FAILURE (status)) {
/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
return_ACPI_STATUS (AE_OK)
}
}
#endif
/*
* Dispatch the notify to the appropriate handler
* NOTE: the request is queued for execution after this method
......@@ -130,8 +161,7 @@ acpi_ex_opcode_2A_0T_0R (
* from this thread -- because handlers may in turn run other
* control methods.
*/
status = acpi_ev_queue_notify_request (node,
(u32) operand[1]->integer.value);
status = acpi_ev_queue_notify_request (node, value);
break;
......
......@@ -57,58 +57,17 @@
*
* RETURN: Status
*
* DESCRIPTION: Enable a single GPE.
* DESCRIPTION: Enable a single GPE. Note: The bit for this GPE must already
* be set in the parent register enable_for_run mask.
*
******************************************************************************/
acpi_status
acpi_hw_enable_gpe (
struct acpi_gpe_event_info *gpe_event_info)
{
u32 in_byte;
acpi_status status;
ACPI_FUNCTION_ENTRY ();
/*
* Read the current value of the register, set the appropriate bit
* to enable the GPE, and write out the new register.
*/
status = acpi_hw_low_level_read (8, &in_byte,
&gpe_event_info->register_info->enable_address);
if (ACPI_FAILURE (status)) {
return (status);
}
/* Write with the new GPE bit enabled */
status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask),
&gpe_event_info->register_info->enable_address);
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_gpe_for_wakeup
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be enabled
*
* RETURN: None
*
* DESCRIPTION: Keep track of which GPEs the OS has requested not be
* disabled when going to sleep.
*
******************************************************************************/
void
acpi_hw_enable_gpe_for_wakeup (
struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
ACPI_FUNCTION_ENTRY ();
......@@ -118,15 +77,15 @@ acpi_hw_enable_gpe_for_wakeup (
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return;
return (AE_NOT_EXIST);
}
/*
* Set the bit so we will not enable this GPE when sleeping (and disable
* it upon wake)
*/
gpe_register_info->wake_enable |= gpe_event_info->bit_mask;
gpe_event_info->flags |= (ACPI_GPE_TYPE_WAKE | ACPI_GPE_ENABLED);
/* Write GPE enable register with the new GPE bit enabled */
status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
&gpe_register_info->enable_address);
return (status);
}
......@@ -146,9 +105,8 @@ acpi_status
acpi_hw_disable_gpe (
struct acpi_gpe_event_info *gpe_event_info)
{
u32 in_byte;
acpi_status status;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
ACPI_FUNCTION_ENTRY ();
......@@ -158,67 +116,14 @@ acpi_hw_disable_gpe (
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return (AE_BAD_PARAMETER);
}
/*
* Read the current value of the register, clear the appropriate bit,
* and write out the new register value to disable the GPE.
*/
status = acpi_hw_low_level_read (8, &in_byte,
&gpe_register_info->enable_address);
if (ACPI_FAILURE (status)) {
return (status);
return (AE_NOT_EXIST);
}
/* Write the byte with this GPE bit cleared */
/* Write the GPE enable register with this GPE bit cleared */
status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)),
status = acpi_hw_low_level_write (8, gpe_register_info->enable_for_run,
&gpe_register_info->enable_address);
if (ACPI_FAILURE (status)) {
return (status);
}
/* Make sure this GPE is disabled for wake, also */
acpi_hw_disable_gpe_for_wakeup (gpe_event_info);
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_disable_gpe_for_wakeup
*
* PARAMETERS: gpe_event_info - Info block for the GPE to be disabled
*
* RETURN: None
*
* DESCRIPTION: Keep track of which GPEs the OS has requested not be
* disabled when going to sleep.
*
******************************************************************************/
void
acpi_hw_disable_gpe_for_wakeup (
struct acpi_gpe_event_info *gpe_event_info)
{
struct acpi_gpe_register_info *gpe_register_info;
ACPI_FUNCTION_ENTRY ();
/* Get the info block for the entire GPE register */
gpe_register_info = gpe_event_info->register_info;
if (!gpe_register_info) {
return;
}
/* Clear the bit so we will disable this when sleeping */
gpe_register_info->wake_enable &= ~(gpe_event_info->bit_mask);
return (status);
}
......@@ -248,7 +153,7 @@ acpi_hw_clear_gpe (
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask,
status = acpi_hw_low_level_write (8, gpe_event_info->register_bit,
&gpe_event_info->register_info->status_address);
return (status);
......@@ -274,7 +179,7 @@ acpi_hw_get_gpe_status (
acpi_event_status *event_status)
{
u32 in_byte;
u8 bit_mask;
u8 register_bit;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
acpi_event_status local_event_status = 0;
......@@ -293,33 +198,28 @@ acpi_hw_get_gpe_status (
/* Get the register bitmask for this GPE */
bit_mask = gpe_event_info->bit_mask;
register_bit = gpe_event_info->register_bit;
/* GPE Enabled? */
/* GPE currently enabled? (enabled for runtime?) */
status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
if (bit_mask & in_byte) {
if (register_bit & gpe_register_info->enable_for_run) {
local_event_status |= ACPI_EVENT_FLAG_ENABLED;
}
/* GPE Enabled for wake? */
/* GPE enabled for wake? */
if (bit_mask & gpe_register_info->wake_enable) {
if (register_bit & gpe_register_info->enable_for_wake) {
local_event_status |= ACPI_EVENT_FLAG_WAKE_ENABLED;
}
/* GPE active (set)? */
/* GPE currently active (status bit == 1)? */
status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address);
if (ACPI_FAILURE (status)) {
goto unlock_and_exit;
}
if (bit_mask & in_byte) {
if (register_bit & in_byte) {
local_event_status |= ACPI_EVENT_FLAG_SET;
}
......@@ -411,64 +311,43 @@ acpi_hw_clear_gpe_block (
/******************************************************************************
*
* FUNCTION: acpi_hw_prepare_gpe_block_for_sleep
* FUNCTION: acpi_hw_enable_runtime_gpe_block
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Disable all runtime GPEs and enable all wakeup GPEs -- within
* a single GPE block
* DESCRIPTION: Enable all "runtime" GPEs within a GPE block. (Includes
* combination wake/run GPEs.)
*
******************************************************************************/
static acpi_status
acpi_hw_prepare_gpe_block_for_sleep (
acpi_status
acpi_hw_enable_runtime_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
{
u32 i;
struct acpi_gpe_register_info *gpe_register_info;
u32 in_value;
acpi_status status;
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info;
/* NOTE: assumes that all GPEs are currently disabled */
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/*
* Read the enabled/disabled status of all GPEs. We
* will be using it to restore all the GPEs later.
*
* NOTE: Wake GPEs are are ALL disabled at this time, so when we wake
* and restore this register, they will be automatically disabled.
*/
status = acpi_hw_low_level_read (8, &in_value,
&gpe_register_info->enable_address);
if (ACPI_FAILURE (status)) {
return (status);
if (!gpe_block->register_info[i].enable_for_run) {
continue;
}
gpe_register_info->enable = (u8) in_value;
/* Enable all "runtime" GPEs in this register */
/*
* 1) Disable all runtime GPEs
* 2) Enable all wakeup GPEs
*/
status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable,
&gpe_register_info->enable_address);
status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_run,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE (status)) {
return (status);
}
/* Point to next GPE register */
gpe_register_info++;
}
return (AE_OK);
......@@ -477,114 +356,113 @@ acpi_hw_prepare_gpe_block_for_sleep (
/******************************************************************************
*
* FUNCTION: acpi_hw_prepare_gpes_for_sleep
* FUNCTION: acpi_hw_enable_wakeup_gpe_block
*
* PARAMETERS: None
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
*
* RETURN: Status
*
* DESCRIPTION: Disable all runtime GPEs, enable all wake GPEs.
* Called with interrupts disabled. The interrupt handler also
* modifies gpe_register_info->Enable, so it should not be
* given the chance to run until after the runtime GPEs are
* re-enabled.
* DESCRIPTION: Enable all "wake" GPEs within a GPE block. (Includes
* combination wake/run GPEs.)
*
******************************************************************************/
acpi_status
acpi_hw_prepare_gpes_for_sleep (
void)
acpi_hw_enable_wakeup_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
{
u32 i;
acpi_status status;
ACPI_FUNCTION_ENTRY ();
/* Examine each GPE Register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Enable all "wake" GPEs in this register */
status = acpi_ev_walk_gpe_list (acpi_hw_prepare_gpe_block_for_sleep);
return (status);
status = acpi_hw_low_level_write (8, gpe_block->register_info[i].enable_for_wake,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE (status)) {
return (status);
}
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_restore_gpe_block_on_wake
* FUNCTION: acpi_hw_disable_all_gpes
*
* PARAMETERS: gpe_xrupt_info - GPE Interrupt info
* gpe_block - Gpe Block info
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in one
* GPE block
* DESCRIPTION: Disable and clear all GPEs
*
******************************************************************************/
static acpi_status
acpi_hw_restore_gpe_block_on_wake (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block)
acpi_status
acpi_hw_disable_all_gpes (
void)
{
u32 i;
struct acpi_gpe_register_info *gpe_register_info;
acpi_status status;
/* This callback processes one entire GPE block */
ACPI_FUNCTION_ENTRY ();
/* Get the register info for the entire GPE block */
gpe_register_info = gpe_block->register_info;
status = acpi_ev_walk_gpe_list (acpi_hw_disable_gpe_block);
status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
return (status);
}
/* Examine each GPE register within the block */
for (i = 0; i < gpe_block->register_count; i++) {
/* Clear the entire status register */
/******************************************************************************
*
* FUNCTION: acpi_hw_enable_all_runtime_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Enable all GPEs of the given type
*
******************************************************************************/
status = acpi_hw_low_level_write (8, 0xFF,
&gpe_block->register_info[i].status_address);
if (ACPI_FAILURE (status)) {
return (status);
}
acpi_status
acpi_hw_enable_all_runtime_gpes (
void)
{
acpi_status status;
/*
* Restore the GPE Enable register, which will do the following:
*
* 1) Disable all wakeup GPEs
* 2) Enable all runtime GPEs
*
* (On sleep, we saved the enabled status of all GPEs)
*/
status = acpi_hw_low_level_write (8, gpe_register_info->enable,
&gpe_register_info->enable_address);
if (ACPI_FAILURE (status)) {
return (status);
}
/* Point to next GPE register */
ACPI_FUNCTION_ENTRY ();
gpe_register_info++;
}
return (AE_OK);
status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
status = acpi_ev_walk_gpe_list (acpi_hw_enable_runtime_gpe_block);
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_restore_gpes_on_wake
* FUNCTION: acpi_hw_enable_all_wakeup_gpes
*
* PARAMETERS: None
*
* RETURN: Status
*
* DESCRIPTION: Enable all runtime GPEs and disable all wake GPEs -- in all
* GPE blocks
* DESCRIPTION: Enable all GPEs of the given type
*
******************************************************************************/
acpi_status
acpi_hw_restore_gpes_on_wake (
acpi_hw_enable_all_wakeup_gpes (
void)
{
acpi_status status;
......@@ -593,6 +471,8 @@ acpi_hw_restore_gpes_on_wake (
ACPI_FUNCTION_ENTRY ();
status = acpi_ev_walk_gpe_list (acpi_hw_restore_gpe_block_on_wake);
status = acpi_ev_walk_gpe_list (acpi_hw_clear_gpe_block);
status = acpi_ev_walk_gpe_list (acpi_hw_enable_wakeup_gpe_block);
return (status);
}
......@@ -135,7 +135,7 @@ acpi_get_sleep_type_data (
u8 *sleep_type_b)
{
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
struct acpi_parameter_info info;
ACPI_FUNCTION_TRACE ("acpi_get_sleep_type_data");
......@@ -152,8 +152,9 @@ acpi_get_sleep_type_data (
/*
* Evaluate the namespace object containing the values for this state
*/
info.parameters = NULL;
status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state],
NULL, &obj_desc);
&info);
if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n",
acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state]));
......@@ -163,48 +164,50 @@ acpi_get_sleep_type_data (
/* Must have a return object */
if (!obj_desc) {
if (!info.return_object) {
ACPI_REPORT_ERROR (("Missing Sleep State object\n"));
status = AE_NOT_EXIST;
}
/* It must be of type Package */
else if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_PACKAGE) {
else if (ACPI_GET_OBJECT_TYPE (info.return_object) != ACPI_TYPE_PACKAGE) {
ACPI_REPORT_ERROR (("Sleep State object not a Package\n"));
status = AE_AML_OPERAND_TYPE;
}
/* The package must have at least two elements */
else if (obj_desc->package.count < 2) {
else if (info.return_object->package.count < 2) {
ACPI_REPORT_ERROR (("Sleep State package does not have at least two elements\n"));
status = AE_AML_NO_OPERAND;
}
/* The first two elements must both be of type Integer */
else if ((ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[0]) != ACPI_TYPE_INTEGER) ||
(ACPI_GET_OBJECT_TYPE (obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) {
else if ((ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[0]) != ACPI_TYPE_INTEGER) ||
(ACPI_GET_OBJECT_TYPE (info.return_object->package.elements[1]) != ACPI_TYPE_INTEGER)) {
ACPI_REPORT_ERROR (("Sleep State package elements are not both Integers (%s, %s)\n",
acpi_ut_get_object_type_name (obj_desc->package.elements[0]),
acpi_ut_get_object_type_name (obj_desc->package.elements[1])));
acpi_ut_get_object_type_name (info.return_object->package.elements[0]),
acpi_ut_get_object_type_name (info.return_object->package.elements[1])));
status = AE_AML_OPERAND_TYPE;
}
else {
/*
* Valid _Sx_ package size, type, and value
*/
*sleep_type_a = (u8) (obj_desc->package.elements[0])->integer.value;
*sleep_type_b = (u8) (obj_desc->package.elements[1])->integer.value;
*sleep_type_a = (u8) (info.return_object->package.elements[0])->integer.value;
*sleep_type_b = (u8) (info.return_object->package.elements[1])->integer.value;
}
if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc)));
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"While evaluating sleep_state [%s], bad Sleep object %p type %s\n",
acpi_gbl_sleep_state_names[sleep_state], info.return_object,
acpi_ut_get_object_type_name (info.return_object)));
}
acpi_ut_remove_reference (obj_desc);
acpi_ut_remove_reference (info.return_object);
return_ACPI_STATUS (status);
}
......
......@@ -265,19 +265,21 @@ acpi_enter_sleep_state (
sleep_type_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_TYPE_A);
sleep_enable_reg_info = acpi_hw_get_bit_register_info (ACPI_BITREG_SLEEP_ENABLE);
if (sleep_state != ACPI_STATE_S5) {
/* Clear wake status */
/* Clear wake status */
status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
status = acpi_set_register (ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
/* Clear all fixed and general purpose status bits */
status = acpi_hw_clear_acpi_status (ACPI_MTX_DO_NOT_LOCK);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (sleep_state != ACPI_STATE_S5) {
/* Disable BM arbitration */
status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
......@@ -287,10 +289,16 @@ acpi_enter_sleep_state (
}
/*
* 1) Disable all runtime GPEs
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
status = acpi_hw_prepare_gpes_for_sleep ();
status = acpi_hw_disable_all_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
acpi_gbl_system_awake_and_running = FALSE;
status = acpi_hw_enable_all_wakeup_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
......@@ -420,10 +428,16 @@ acpi_enter_sleep_state_s4bios (
}
/*
* 1) Disable all runtime GPEs
* 1) Disable/Clear all GPEs
* 2) Enable all wakeup GPEs
*/
status = acpi_hw_prepare_gpes_for_sleep ();
status = acpi_hw_disable_all_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
acpi_gbl_system_awake_and_running = FALSE;
status = acpi_hw_enable_all_wakeup_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
......@@ -540,10 +554,16 @@ acpi_leave_sleep_state (
/*
* Restore the GPEs:
* 1) Disable all wakeup GPEs
* 1) Disable/Clear all GPEs
* 2) Enable all runtime GPEs
*/
status = acpi_hw_restore_gpes_on_wake ();
status = acpi_hw_disable_all_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
acpi_gbl_system_awake_and_running = TRUE;
status = acpi_hw_enable_all_runtime_gpes ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
......
......@@ -193,7 +193,7 @@ acpi_ns_root_initialize (void)
case ACPI_TYPE_MUTEX:
obj_desc->mutex.node = new_node;
obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL
obj_desc->mutex.sync_level = (u8) ACPI_STRTOUL
(val, NULL, 10);
if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
......
......@@ -77,13 +77,10 @@
acpi_status
acpi_ns_evaluate_relative (
struct acpi_namespace_node *handle,
char *pathname,
union acpi_operand_object **params,
union acpi_operand_object **return_object)
struct acpi_parameter_info *info)
{
acpi_status status;
struct acpi_namespace_node *prefix_node;
struct acpi_namespace_node *node = NULL;
union acpi_generic_state *scope_info;
char *internal_path = NULL;
......@@ -95,7 +92,7 @@ acpi_ns_evaluate_relative (
/*
* Must have a valid object handle
*/
if (!handle) {
if (!info || !info->node) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
......@@ -118,8 +115,8 @@ acpi_ns_evaluate_relative (
goto cleanup;
}
prefix_node = acpi_ns_map_handle_to_node (handle);
if (!prefix_node) {
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;
......@@ -127,7 +124,7 @@ acpi_ns_evaluate_relative (
/* Lookup the name in the namespace */
scope_info->scope.node = prefix_node;
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);
......@@ -147,7 +144,8 @@ acpi_ns_evaluate_relative (
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
pathname, node, acpi_ns_get_attached_object (node)));
status = acpi_ns_evaluate_by_handle (node, params, return_object);
info->node = node;
status = acpi_ns_evaluate_by_handle (info);
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
pathname));
......@@ -166,6 +164,7 @@ acpi_ns_evaluate_relative (
* FUNCTION: acpi_ns_evaluate_by_name
*
* PARAMETERS: Pathname - Fully qualified pathname to the object
* Info - Contains:
* return_object - Where to put method's return value (if
* any). If NULL, no value is returned.
* Params - List of parameters to pass to the method,
......@@ -184,11 +183,9 @@ acpi_ns_evaluate_relative (
acpi_status
acpi_ns_evaluate_by_name (
char *pathname,
union acpi_operand_object **params,
union acpi_operand_object **return_object)
struct acpi_parameter_info *info)
{
acpi_status status;
struct acpi_namespace_node *node = NULL;
char *internal_path = NULL;
......@@ -211,7 +208,7 @@ acpi_ns_evaluate_by_name (
status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
&node);
&info->node);
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
......@@ -226,9 +223,9 @@ acpi_ns_evaluate_by_name (
* to evaluate it.
*/
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
pathname, node, acpi_ns_get_attached_object (node)));
pathname, info->node, acpi_ns_get_attached_object (info->node)));
status = acpi_ns_evaluate_by_handle (node, params, return_object);
status = acpi_ns_evaluate_by_handle (info);
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
pathname));
......@@ -254,6 +251,7 @@ acpi_ns_evaluate_by_name (
* Params - List of parameters to pass to the method,
* terminated by NULL. Params itself may be
* NULL if no parameters are being passed.
* param_type - Type of Parameter list
* return_object - Where to put method's return value (if
* any). If NULL, no value is returned.
*
......@@ -267,13 +265,9 @@ acpi_ns_evaluate_by_name (
acpi_status
acpi_ns_evaluate_by_handle (
struct acpi_namespace_node *handle,
union acpi_operand_object **params,
union acpi_operand_object **return_object)
struct acpi_parameter_info *info)
{
struct acpi_namespace_node *node;
acpi_status status;
union acpi_operand_object *local_return_object;
ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
......@@ -287,15 +281,13 @@ acpi_ns_evaluate_by_handle (
/* Parameter Validation */
if (!handle) {
if (!info) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
if (return_object) {
/* Initialize the return value to an invalid object */
/* Initialize the return value to an invalid object */
*return_object = NULL;
}
info->return_object = NULL;
/* Get the prefix handle and Node */
......@@ -304,8 +296,8 @@ acpi_ns_evaluate_by_handle (
return_ACPI_STATUS (status);
}
node = acpi_ns_map_handle_to_node (handle);
if (!node) {
info->node = acpi_ns_map_handle_to_node (info->node);
if (!info->node) {
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
......@@ -315,8 +307,8 @@ acpi_ns_evaluate_by_handle (
* so that proper scoping context will be established
* before execution.
*/
if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
}
/*
......@@ -328,19 +320,18 @@ acpi_ns_evaluate_by_handle (
* In both cases, the namespace is unlocked by the
* acpi_ns* procedure
*/
if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) {
if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
/*
* Case 1) We have an actual control method to execute
*/
status = acpi_ns_execute_control_method (node, params,
&local_return_object);
status = acpi_ns_execute_control_method (info);
}
else {
/*
* Case 2) Object is NOT a method, just return its
* current value
*/
status = acpi_ns_get_object_value (node, &local_return_object);
status = acpi_ns_get_object_value (info);
}
/*
......@@ -348,20 +339,6 @@ acpi_ns_evaluate_by_handle (
* be dealt with
*/
if (status == AE_CTRL_RETURN_VALUE) {
/*
* If the Method returned a value and the caller
* provided a place to store a returned value, Copy
* the returned value to the object descriptor provided
* by the caller.
*/
if (return_object) {
/*
* Valid return object, copy the pointer to
* the returned object
*/
*return_object = local_return_object;
}
/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
status = AE_OK;
......@@ -396,9 +373,7 @@ acpi_ns_evaluate_by_handle (
acpi_status
acpi_ns_execute_control_method (
struct acpi_namespace_node *method_node,
union acpi_operand_object **params,
union acpi_operand_object **return_obj_desc)
struct acpi_parameter_info *info)
{
acpi_status status;
union acpi_operand_object *obj_desc;
......@@ -409,7 +384,7 @@ acpi_ns_execute_control_method (
/* Verify that there is a method associated with this object */
obj_desc = acpi_ns_get_attached_object (method_node);
obj_desc = acpi_ns_get_attached_object (info->node);
if (!obj_desc) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
......@@ -417,7 +392,7 @@ acpi_ns_execute_control_method (
return_ACPI_STATUS (AE_NULL_OBJECT);
}
ACPI_DUMP_PATHNAME (method_node, "Execute Method:",
ACPI_DUMP_PATHNAME (info->node, "Execute Method:",
ACPI_LV_INFO, _COMPONENT);
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
......@@ -444,7 +419,7 @@ acpi_ns_execute_control_method (
return_ACPI_STATUS (status);
}
status = acpi_psx_execute (method_node, params, return_obj_desc);
status = acpi_psx_execute (info);
acpi_ex_exit_interpreter ();
return_ACPI_STATUS (status);
......@@ -468,11 +443,10 @@ acpi_ns_execute_control_method (
acpi_status
acpi_ns_get_object_value (
struct acpi_namespace_node *node,
union acpi_operand_object **return_obj_desc)
struct acpi_parameter_info *info)
{
acpi_status status = AE_OK;
struct acpi_namespace_node *resolved_node = node;
struct acpi_namespace_node *resolved_node = info->node;
ACPI_FUNCTION_TRACE ("ns_get_object_value");
......@@ -518,9 +492,9 @@ acpi_ns_get_object_value (
if (ACPI_SUCCESS (status)) {
status = AE_CTRL_RETURN_VALUE;
*return_obj_desc = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
info->return_object = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
*return_obj_desc, acpi_ut_get_object_type_name (*return_obj_desc)));
*info->return_object, acpi_ut_get_object_type_name (info->return_object)));
}
}
......
......@@ -337,25 +337,28 @@ acpi_ns_init_one_device (
void *context,
void **return_value)
{
acpi_status status;
struct acpi_namespace_node *node;
u32 flags;
struct acpi_device_walk_info *info = (struct acpi_device_walk_info *) context;
struct acpi_parameter_info pinfo;
u32 flags;
acpi_status status;
ACPI_FUNCTION_TRACE ("ns_init_one_device");
node = acpi_ns_map_handle_to_node (obj_handle);
if (!node) {
pinfo.parameters = NULL;
pinfo.parameter_type = ACPI_PARAM_ARGS;
pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
if (!pinfo.node) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
/*
* We will run _STA/_INI on Devices and Processors only
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR)) {
if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
(pinfo.node->type != ACPI_TYPE_PROCESSOR)) {
return_ACPI_STATUS (AE_OK);
}
......@@ -368,11 +371,11 @@ acpi_ns_init_one_device (
/*
* Run _STA to determine if we can run _INI on the device.
*/
ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, node, "_STA"));
status = acpi_ut_execute_STA (node, &flags);
ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_STA"));
status = acpi_ut_execute_STA (pinfo.node, &flags);
if (ACPI_FAILURE (status)) {
if (node->type == ACPI_TYPE_DEVICE) {
if (pinfo.node->type == ACPI_TYPE_DEVICE) {
/* Ignore error and move on to next device */
return_ACPI_STATUS (AE_OK);
......@@ -393,8 +396,8 @@ acpi_ns_init_one_device (
/*
* The device is present. Run _INI.
*/
ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, obj_handle, "_INI"));
status = acpi_ns_evaluate_relative (obj_handle, "_INI", NULL, NULL);
ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_INI"));
status = acpi_ns_evaluate_relative ("_INI", &pinfo);
if (ACPI_FAILURE (status)) {
/* No _INI (AE_NOT_FOUND) means device requires no initialization */
......@@ -402,7 +405,7 @@ acpi_ns_init_one_device (
/* Ignore error and move on to next device */
#ifdef ACPI_DEBUG_OUTPUT
char *scope_name = acpi_ns_get_external_pathname (obj_handle);
char *scope_name = acpi_ns_get_external_pathname (pinfo.node);
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
scope_name, acpi_format_exception (status)));
......@@ -422,7 +425,7 @@ acpi_ns_init_one_device (
if (acpi_gbl_init_handler) {
/* External initialization handler is present, call it */
status = acpi_gbl_init_handler (obj_handle, ACPI_INIT_DEVICE_INI);
status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
}
......
......@@ -94,8 +94,9 @@ acpi_ns_one_complete_parse (
return_ACPI_STATUS (AE_NO_MEMORY);
}
status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL, table_desc->aml_start,
table_desc->aml_length, NULL, NULL, pass_number);
status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
table_desc->aml_start, table_desc->aml_length,
NULL, pass_number);
if (ACPI_FAILURE (status)) {
acpi_ds_delete_walk_state (walk_state);
return_ACPI_STATUS (status);
......
......@@ -174,8 +174,7 @@ acpi_evaluate_object (
{
acpi_status status;
acpi_status status2;
union acpi_operand_object **internal_params = NULL;
union acpi_operand_object *internal_return_obj = NULL;
struct acpi_parameter_info info;
acpi_size buffer_space_needed;
u32 i;
......@@ -183,6 +182,11 @@ acpi_evaluate_object (
ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
info.node = handle;
info.parameters = NULL;
info.return_object = NULL;
info.parameter_type = ACPI_PARAM_ARGS;
/*
* If there are parameters to be passed to the object
* (which must be a control method), the external objects
......@@ -193,9 +197,10 @@ acpi_evaluate_object (
* Allocate a new parameter block for the internal objects
* Add 1 to count to allow for null terminated internal list
*/
internal_params = ACPI_MEM_CALLOCATE (((acpi_size) external_params->count + 1) *
sizeof (void *));
if (!internal_params) {
info.parameters = ACPI_MEM_CALLOCATE (
((acpi_size) external_params->count + 1) *
sizeof (void *));
if (!info.parameters) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
......@@ -205,15 +210,16 @@ acpi_evaluate_object (
*/
for (i = 0; i < external_params->count; i++) {
status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
&internal_params[i]);
&info.parameters[i]);
if (ACPI_FAILURE (status)) {
acpi_ut_delete_internal_object_list (internal_params);
acpi_ut_delete_internal_object_list (info.parameters);
return_ACPI_STATUS (status);
}
}
internal_params[external_params->count] = NULL;
info.parameters[external_params->count] = NULL;
}
/*
* Three major cases:
* 1) Fully qualified pathname
......@@ -225,8 +231,7 @@ acpi_evaluate_object (
/*
* The path is fully qualified, just evaluate by name
*/
status = acpi_ns_evaluate_by_name (pathname, internal_params,
&internal_return_obj);
status = acpi_ns_evaluate_by_name (pathname, &info);
}
else if (!handle) {
/*
......@@ -256,15 +261,13 @@ acpi_evaluate_object (
* The null pathname case means the handle is for
* the actual object to be evaluated
*/
status = acpi_ns_evaluate_by_handle (handle, internal_params,
&internal_return_obj);
status = acpi_ns_evaluate_by_handle (&info);
}
else {
/*
* Both a Handle and a relative Pathname
*/
status = acpi_ns_evaluate_relative (handle, pathname, internal_params,
&internal_return_obj);
status = acpi_ns_evaluate_relative (pathname, &info);
}
}
......@@ -274,11 +277,11 @@ acpi_evaluate_object (
* copy the return value to an external object.
*/
if (return_buffer) {
if (!internal_return_obj) {
if (!info.return_object) {
return_buffer->length = 0;
}
else {
if (ACPI_GET_DESCRIPTOR_TYPE (internal_return_obj) == ACPI_DESC_TYPE_NAMED) {
if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
/*
* If we received a NS Node as a return object, this means that
* the object we are evaluating has nothing interesting to
......@@ -288,7 +291,7 @@ acpi_evaluate_object (
* support for various types at a later date if necessary.
*/
status = AE_TYPE;
internal_return_obj = NULL; /* No need to delete a NS Node */
info.return_object = NULL; /* No need to delete a NS Node */
return_buffer->length = 0;
}
......@@ -297,7 +300,7 @@ acpi_evaluate_object (
* Find out how large a buffer is needed
* to contain the returned object
*/
status = acpi_ut_get_object_size (internal_return_obj,
status = acpi_ut_get_object_size (info.return_object,
&buffer_space_needed);
if (ACPI_SUCCESS (status)) {
/* Validate/Allocate/Clear caller buffer */
......@@ -309,13 +312,14 @@ acpi_evaluate_object (
*/
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
"Needed buffer size %X, %s\n",
(u32) buffer_space_needed, acpi_format_exception (status)));
(u32) buffer_space_needed,
acpi_format_exception (status)));
}
else {
/*
* We have enough space for the object, build it
*/
status = acpi_ut_copy_iobject_to_eobject (internal_return_obj,
status = acpi_ut_copy_iobject_to_eobject (info.return_object,
return_buffer);
}
}
......@@ -323,7 +327,7 @@ acpi_evaluate_object (
}
}
if (internal_return_obj) {
if (info.return_object) {
/*
* Delete the internal return object. NOTE: Interpreter
* must be locked to avoid race condition.
......@@ -334,7 +338,7 @@ acpi_evaluate_object (
* Delete the internal return object. (Or at least
* decrement the reference count by one)
*/
acpi_ut_remove_reference (internal_return_obj);
acpi_ut_remove_reference (info.return_object);
acpi_ex_exit_interpreter ();
}
}
......@@ -342,10 +346,10 @@ acpi_evaluate_object (
/*
* Free the input parameter list (if we created one),
*/
if (internal_params) {
if (info.parameters) {
/* Free the allocated parameter block */
acpi_ut_delete_internal_object_list (internal_params);
acpi_ut_delete_internal_object_list (info.parameters);
}
return_ACPI_STATUS (status);
......
......@@ -281,7 +281,7 @@ acpi_get_object_info (
if (info.type == ACPI_TYPE_DEVICE) {
/*
* Get extra info for ACPI Devices objects only:
* Run the Device _HID, _UID, _CID, _STA, and _ADR methods.
* Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info.Valid bitfield is used
......@@ -330,7 +330,7 @@ acpi_get_object_info (
status = acpi_ut_execute_sxds (node, info.highest_dstates);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_STA;
info.valid |= ACPI_VALID_SXDS;
}
status = AE_OK;
......
......@@ -57,7 +57,7 @@
*
* FUNCTION: acpi_psx_execute
*
* PARAMETERS: method_node - A method object containing both the AML
* PARAMETERS: Info->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
......@@ -73,9 +73,7 @@
acpi_status
acpi_psx_execute (
struct acpi_namespace_node *method_node,
union acpi_operand_object **params,
union acpi_operand_object **return_obj_desc)
struct acpi_parameter_info *info)
{
acpi_status status;
union acpi_operand_object *obj_desc;
......@@ -89,29 +87,31 @@ acpi_psx_execute (
/* Validate the Node and get the attached object */
if (!method_node) {
if (!info || !info->node) {
return_ACPI_STATUS (AE_NULL_ENTRY);
}
obj_desc = acpi_ns_get_attached_object (method_node);
obj_desc = acpi_ns_get_attached_object (info->node);
if (!obj_desc) {
return_ACPI_STATUS (AE_NULL_OBJECT);
}
/* Init for new method, wait on concurrency semaphore */
status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL);
status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
if (params) {
if (info &&
(info->parameter_type == ACPI_PARAM_ARGS) &&
(info->parameters)) {
/*
* The caller "owns" the parameters, so give each one an extra
* reference
*/
for (i = 0; params[i]; i++) {
acpi_ut_add_reference (params[i]);
for (i = 0; info->parameters[i]; i++) {
acpi_ut_add_reference (info->parameters[i]);
}
}
......@@ -121,7 +121,7 @@ acpi_psx_execute (
*/
ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
"**** Begin Method Parse **** Entry=%p obj=%p\n",
method_node, obj_desc));
info->node, obj_desc));
/* Create and init a Root Node */
......@@ -147,8 +147,9 @@ acpi_psx_execute (
goto cleanup2;
}
status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, NULL, 1);
status = acpi_ds_init_aml_walk (walk_state, op, info->node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, NULL, 1);
if (ACPI_FAILURE (status)) {
goto cleanup3;
}
......@@ -159,7 +160,6 @@ acpi_psx_execute (
acpi_ps_delete_parse_tree (op);
if (ACPI_FAILURE (status)) {
goto cleanup1; /* Walk state is already deleted */
}
/*
......@@ -167,7 +167,7 @@ acpi_psx_execute (
*/
ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
"**** Begin Method Execution **** Entry=%p obj=%p\n",
method_node, obj_desc));
info->node, obj_desc));
/* Create and init a Root Node */
......@@ -179,8 +179,8 @@ acpi_psx_execute (
/* Init new op with the method name and pointer back to the NS node */
acpi_ps_set_name (op, method_node->name.integer);
op->common.node = method_node;
acpi_ps_set_name (op, info->node->name.integer);
op->common.node = info->node;
/* Create and initialize a new walk state */
......@@ -190,8 +190,9 @@ acpi_psx_execute (
goto cleanup2;
}
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);
status = acpi_ds_init_aml_walk (walk_state, op, info->node,
obj_desc->method.aml_start,
obj_desc->method.aml_length, info, 3);
if (ACPI_FAILURE (status)) {
goto cleanup3;
}
......@@ -210,13 +211,14 @@ acpi_psx_execute (
acpi_ps_delete_parse_tree (op);
cleanup1:
if (params) {
if ((info->parameter_type == ACPI_PARAM_ARGS) &&
(info->parameters)) {
/* Take away the extra reference that we gave the parameters above */
for (i = 0; params[i]; i++) {
for (i = 0; info->parameters[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], REF_DECREMENT);
}
}
......@@ -228,10 +230,10 @@ acpi_psx_execute (
* If the method has returned an object, signal this to the caller with
* a control exception code
*/
if (*return_obj_desc) {
if (info->return_object) {
ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n",
*return_obj_desc));
ACPI_DUMP_STACK_ENTRY (*return_obj_desc);
info->return_object));
ACPI_DUMP_STACK_ENTRY (info->return_object);
status = AE_CTRL_RETURN_VALUE;
}
......
......@@ -289,6 +289,7 @@ acpi_rs_set_srs_method_data (
acpi_handle handle,
struct acpi_buffer *in_buffer)
{
struct acpi_parameter_info info;
union acpi_operand_object *params[2];
acpi_status status;
struct acpi_buffer buffer;
......@@ -329,10 +330,14 @@ acpi_rs_set_srs_method_data (
params[0]->common.flags = AOPOBJ_DATA_VALID;
params[1] = NULL;
info.node = handle;
info.parameters = params;
info.parameter_type = ACPI_PARAM_ARGS;
/*
* Execute the method, no return value
*/
status = acpi_ns_evaluate_relative (handle, "_SRS", params, NULL);
status = acpi_ns_evaluate_relative ("_SRS", &info);
/*
* Clean up and return the status from acpi_ns_evaluate_relative
......
......@@ -133,7 +133,7 @@ acpi_ut_evaluate_object (
u32 expected_return_btypes,
union acpi_operand_object **return_desc)
{
union acpi_operand_object *obj_desc;
struct acpi_parameter_info info;
acpi_status status;
u32 return_btype;
......@@ -141,9 +141,13 @@ acpi_ut_evaluate_object (
ACPI_FUNCTION_TRACE ("ut_evaluate_object");
info.node = prefix_node;
info.parameters = NULL;
info.parameter_type = ACPI_PARAM_ARGS;
/* Evaluate the object/method */
status = acpi_ns_evaluate_relative (prefix_node, path, NULL, &obj_desc);
status = acpi_ns_evaluate_relative (path, &info);
if (ACPI_FAILURE (status)) {
if (status == AE_NOT_FOUND) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
......@@ -159,7 +163,7 @@ acpi_ut_evaluate_object (
/* Did we get a return object? */
if (!obj_desc) {
if (!info.return_object) {
if (expected_return_btypes) {
ACPI_REPORT_METHOD_ERROR ("No object was returned from",
prefix_node, path, AE_NOT_EXIST);
......@@ -172,7 +176,7 @@ acpi_ut_evaluate_object (
/* Map the return object type to the bitmapped type */
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
switch (ACPI_GET_OBJECT_TYPE (info.return_object)) {
case ACPI_TYPE_INTEGER:
return_btype = ACPI_BTYPE_INTEGER;
break;
......@@ -202,17 +206,17 @@ acpi_ut_evaluate_object (
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Type returned from %s was incorrect: %X\n",
path, ACPI_GET_OBJECT_TYPE (obj_desc)));
path, ACPI_GET_OBJECT_TYPE (info.return_object)));
/* On error exit, we must delete the return object */
acpi_ut_remove_reference (obj_desc);
acpi_ut_remove_reference (info.return_object);
return_ACPI_STATUS (AE_TYPE);
}
/* Object type is OK, return it */
*return_desc = obj_desc;
*return_desc = info.return_object;
return_ACPI_STATUS (AE_OK);
}
......
......@@ -171,27 +171,40 @@ u8 acpi_gbl_shutdown = TRUE;
const u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
"\\_S0_",
"\\_S1_",
"\\_S2_",
"\\_S3_",
"\\_S4_",
"\\_S5_"};
const char *acpi_gbl_highest_dstate_names[4] = {
"_S1D",
"_S2D",
"_S3D",
"_S4D"};
const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] =
{
"\\_S0_",
"\\_S1_",
"\\_S2_",
"\\_S3_",
"\\_S4_",
"\\_S5_"
};
/* Strings supported by the _OSI predefined (internal) method */
const char *acpi_gbl_highest_dstate_names[4] =
{
"_S1D",
"_S2D",
"_S3D",
"_S4D"
};
const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
"Linux",
"Windows 2000",
"Windows 2001",
"Windows 2001.1"};
/*
* Strings supported by the _OSI predefined (internal) method.
* When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
*/
const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
{
"Linux",
"Windows 2000",
"Windows 2001",
"Windows 2001.1",
"Windows 2001 SP0",
"Windows 2001 SP1",
"Windows 2001 SP2",
"Windows 2001 SP3",
"Windows 2001 SP4"
};
/******************************************************************************
......@@ -887,6 +900,7 @@ acpi_ut_init_globals (
/* Hardware oriented */
acpi_gbl_events_initialized = FALSE;
acpi_gbl_system_awake_and_running = TRUE;
/* Namespace */
......
......@@ -157,9 +157,8 @@ acpi_enable_subsystem (
}
}
/*
* Enable ACPI mode
*/
/* Enable ACPI mode */
if (!(flags & ACPI_NO_ACPI_ENABLE)) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n"));
......@@ -173,7 +172,21 @@ acpi_enable_subsystem (
}
/*
* Initialize ACPI Event handling
* Install the default op_region handlers. These are installed unless
* other handlers have already been installed via the
* install_address_space_handler interface.
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
status = acpi_ev_install_region_handlers ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
/*
* Initialize ACPI Event handling (Fixed and General Purpose)
*
* NOTE: We must have the hardware AND events initialized before we can execute
* ANY control methods SAFELY. Any control method can require ACPI hardware
......@@ -182,18 +195,18 @@ acpi_enable_subsystem (
if (!(flags & ACPI_NO_EVENT_INIT)) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI events\n"));
status = acpi_ev_initialize ();
status = acpi_ev_initialize_events ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
}
/* Install the SCI handler, Global Lock handler, and GPE handlers */
/* Install the SCI handler and Global Lock handler */
if (!(flags & ACPI_NO_HANDLER_INIT)) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL/GPE handlers\n"));
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL handlers\n"));
status = acpi_ev_handler_initialize ();
status = acpi_ev_install_xrupt_handlers ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
......@@ -226,18 +239,16 @@ acpi_initialize_objects (
/*
* Install the default op_region handlers. These are installed unless
* other handlers have already been installed via the
* install_address_space_handler interface.
* Run all _REG methods
*
* NOTE: This will cause _REG methods to be run. Any objects accessed
* NOTE: Any objects accessed
* by the _REG methods will be automatically initialized, even if they
* contain executable AML (see call to acpi_ns_initialize_objects below).
*/
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n"));
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Executing _REG op_region methods\n"));
status = acpi_ev_init_address_spaces ();
status = acpi_ev_initialize_op_regions ();
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
......@@ -249,7 +260,7 @@ acpi_initialize_objects (
* objects: operation_regions, buffer_fields, Buffers, and Packages.
*/
if (!(flags & ACPI_NO_OBJECT_INIT)) {
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n"));
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Completing Initialization of ACPI Objects\n"));
status = acpi_ns_initialize_objects ();
if (ACPI_FAILURE (status)) {
......
......@@ -64,7 +64,7 @@
/* Version string */
#define ACPI_CA_VERSION 0x20040402
#define ACPI_CA_VERSION 0x20040427
/* Maximum objects in the various object caches */
......@@ -187,7 +187,7 @@
/* Number of strings associated with the _OSI reserved method */
#define ACPI_NUM_OSI_STRINGS 4
#define ACPI_NUM_OSI_STRINGS 9
/******************************************************************************
......
......@@ -437,8 +437,7 @@ acpi_ds_init_aml_walk (
struct acpi_namespace_node *method_node,
u8 *aml_start,
u32 aml_length,
union acpi_operand_object **params,
union acpi_operand_object **return_obj_desc,
struct acpi_parameter_info *info,
u32 pass_number);
acpi_status
......
......@@ -46,11 +46,11 @@
acpi_status
acpi_ev_initialize (
acpi_ev_initialize_events (
void);
acpi_status
acpi_ev_handler_initialize (
acpi_ev_install_xrupt_handlers (
void);
......@@ -117,6 +117,20 @@ u8
acpi_ev_valid_gpe_event (
struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_ev_update_gpe_enable_masks (
struct acpi_gpe_event_info *gpe_event_info,
u8 type);
acpi_status
acpi_ev_enable_gpe (
struct acpi_gpe_event_info *gpe_event_info,
u8 write_to_hardware);
acpi_status
acpi_ev_disable_gpe (
struct acpi_gpe_event_info *gpe_event_info);
struct acpi_gpe_event_info *
acpi_ev_get_gpe_event_info (
acpi_handle gpe_device,
......@@ -139,6 +153,11 @@ acpi_status
acpi_ev_delete_gpe_block (
struct acpi_gpe_block_info *gpe_block);
acpi_status
acpi_ev_delete_gpe_handlers (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
u32
acpi_ev_gpe_dispatch (
struct acpi_gpe_event_info *gpe_event_info,
......@@ -148,12 +167,25 @@ u32
acpi_ev_gpe_detect (
struct acpi_gpe_xrupt_info *gpe_xrupt_list);
acpi_status
acpi_ev_set_gpe_type (
struct acpi_gpe_event_info *gpe_event_info,
u8 type);
acpi_status
acpi_ev_check_for_wake_only_gpe (
struct acpi_gpe_event_info *gpe_event_info);
/*
* Evregion - Address Space handling
*/
acpi_status
acpi_ev_init_address_spaces (
acpi_ev_install_region_handlers (
void);
acpi_status
acpi_ev_initialize_op_regions (
void);
acpi_status
......@@ -182,6 +214,19 @@ acpi_ev_detach_region (
union acpi_operand_object *region_obj,
u8 acpi_ns_is_locked);
acpi_status
acpi_ev_install_space_handler (
struct acpi_namespace_node *node,
acpi_adr_space_type space_id,
acpi_adr_space_handler handler,
acpi_adr_space_setup setup,
void *context);
acpi_status
acpi_ev_execute_reg_methods (
struct acpi_namespace_node *node,
acpi_adr_space_type space_id);
acpi_status
acpi_ev_execute_reg_method (
union acpi_operand_object *region_obj,
......
......@@ -95,8 +95,9 @@
#define AE_LOGICAL_ADDRESS (acpi_status) (0x001B | AE_CODE_ENVIRONMENTAL)
#define AE_ABORT_METHOD (acpi_status) (0x001C | AE_CODE_ENVIRONMENTAL)
#define AE_SAME_HANDLER (acpi_status) (0x001D | AE_CODE_ENVIRONMENTAL)
#define AE_WAKE_ONLY_GPE (acpi_status) (0x001E | AE_CODE_ENVIRONMENTAL)
#define AE_CODE_ENV_MAX 0x001D
#define AE_CODE_ENV_MAX 0x001E
/*
* Programmer exceptions
......@@ -222,7 +223,8 @@ char const *acpi_gbl_exception_names_env[] =
"AE_NO_GLOBAL_LOCK",
"AE_LOGICAL_ADDRESS",
"AE_ABORT_METHOD",
"AE_SAME_HANDLER"
"AE_SAME_HANDLER",
"AE_WAKE_ONLY_GPE"
};
char const *acpi_gbl_exception_names_pgm[] =
......
......@@ -192,6 +192,7 @@ ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
ACPI_EXTERN u8 acpi_gbl_global_lock_present;
ACPI_EXTERN u8 acpi_gbl_events_initialized;
ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
extern u8 acpi_gbl_shutdown;
extern u32 acpi_gbl_startup_flags;
......
......@@ -117,10 +117,6 @@ acpi_status
acpi_hw_enable_gpe (
struct acpi_gpe_event_info *gpe_event_info);
void
acpi_hw_enable_gpe_for_wakeup (
struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_disable_gpe (
struct acpi_gpe_event_info *gpe_event_info);
......@@ -130,10 +126,6 @@ acpi_hw_disable_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
void
acpi_hw_disable_gpe_for_wakeup (
struct acpi_gpe_event_info *gpe_event_info);
acpi_status
acpi_hw_clear_gpe (
struct acpi_gpe_event_info *gpe_event_info);
......@@ -149,13 +141,22 @@ acpi_hw_get_gpe_status (
acpi_event_status *event_status);
acpi_status
acpi_hw_prepare_gpes_for_sleep (
acpi_hw_disable_all_gpes (
void);
acpi_status
acpi_hw_restore_gpes_on_wake (
acpi_hw_enable_all_runtime_gpes (
void);
acpi_status
acpi_hw_enable_all_wakeup_gpes (
void);
acpi_status
acpi_hw_enable_runtime_gpe_block (
struct acpi_gpe_xrupt_info *gpe_xrupt_info,
struct acpi_gpe_block_info *gpe_block);
/* ACPI Timer prototypes */
......
......@@ -189,8 +189,6 @@ struct acpi_namespace_node
u8 type; /* Type associated with this name */
u16 owner_id;
union acpi_name_union name; /* ACPI Name, always 4 chars per ACPI spec */
union acpi_operand_object *object; /* Pointer to attached ACPI object (optional) */
struct acpi_namespace_node *child; /* First child */
struct acpi_namespace_node *peer; /* Next peer*/
......@@ -211,10 +209,8 @@ struct acpi_namespace_node
#define ANOBJ_METHOD_LOCAL 0x10
#define ANOBJ_METHOD_NO_RETVAL 0x20
#define ANOBJ_METHOD_SOME_NO_RETVAL 0x40
#define ANOBJ_IS_BIT_OFFSET 0x80
/*
* ACPI Table Descriptor. One per ACPI table
*/
......@@ -309,16 +305,31 @@ struct acpi_create_field_info
*
****************************************************************************/
/* Information about a GPE, one per each GPE in an array */
/* Dispatch info for each GPE -- either a method or handler, cannot be both */
struct acpi_gpe_event_info
struct acpi_handler_info
{
struct acpi_namespace_node *method_node; /* Method node for this GPE level */
acpi_gpe_handler handler; /* Address of handler, if any */
acpi_event_handler address; /* Address of handler, if any */
void *context; /* Context to be passed to handler */
struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
};
union acpi_gpe_dispatch_info
{
struct acpi_namespace_node *method_node; /* Method node for this GPE level */
struct acpi_handler_info *handler;
};
/*
* Information about a GPE, one per each GPE in an array.
* NOTE: Important to keep this struct as small as possible.
*/
struct acpi_gpe_event_info
{
union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
u8 flags; /* Level or Edge */
u8 bit_mask; /* This GPE within the register */
u8 flags; /* Misc info about this GPE */
u8 register_bit; /* This GPE bit within the register */
};
/* Information about a GPE register pair, one per each status/enable pair in an array */
......@@ -327,9 +338,8 @@ struct acpi_gpe_register_info
{
struct acpi_generic_address status_address; /* Address of status reg */
struct acpi_generic_address enable_address; /* Address of enable reg */
u8 status; /* Current value of status reg */
u8 enable; /* Current value of enable reg */
u8 wake_enable; /* Mask of bits to keep enabled when sleeping */
u8 enable_for_wake; /* GPEs to keep enabled when sleeping */
u8 enable_for_run; /* GPEs to keep enabled when running */
u8 base_gpe_number; /* Base GPE number for this register */
};
......@@ -339,6 +349,7 @@ struct acpi_gpe_register_info
*/
struct acpi_gpe_block_info
{
struct acpi_namespace_node *node;
struct acpi_gpe_block_info *previous;
struct acpi_gpe_block_info *next;
struct acpi_gpe_xrupt_info *xrupt_block; /* Backpointer to interrupt block */
......@@ -502,7 +513,7 @@ struct acpi_thread_state
struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */
union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */
u32 thread_id; /* Running thread ID */
u16 current_sync_level; /* Mutex Sync (nested acquire) level */
u8 current_sync_level; /* Mutex Sync (nested acquire) level */
};
......
......@@ -278,33 +278,25 @@ acpi_ns_dump_objects (
acpi_status
acpi_ns_evaluate_by_handle (
struct acpi_namespace_node *prefix_node,
union acpi_operand_object **params,
union acpi_operand_object **return_object);
struct acpi_parameter_info *info);
acpi_status
acpi_ns_evaluate_by_name (
char *pathname,
union acpi_operand_object **params,
union acpi_operand_object **return_object);
struct acpi_parameter_info *info);
acpi_status
acpi_ns_evaluate_relative (
struct acpi_namespace_node *prefix_node,
char *pathname,
union acpi_operand_object **params,
union acpi_operand_object **return_object);
struct acpi_parameter_info *info);
acpi_status
acpi_ns_execute_control_method (
struct acpi_namespace_node *method_node,
union acpi_operand_object **params,
union acpi_operand_object **return_obj_desc);
struct acpi_parameter_info *info);
acpi_status
acpi_ns_get_object_value (
struct acpi_namespace_node *object_node,
union acpi_operand_object **return_obj_desc);
struct acpi_parameter_info *info);
/*
......
......@@ -204,13 +204,14 @@ struct acpi_object_method
struct acpi_object_mutex
{
ACPI_OBJECT_COMMON_HEADER
u16 sync_level;
u16 acquisition_depth;
struct acpi_thread_state *owner_thread;
void *semaphore;
u8 sync_level; /* 0-15, specified in Mutex() call */
u16 acquisition_depth; /* Allow multiple Acquires, same thread */
struct acpi_thread_state *owner_thread; /* Current owner of the mutex */
void *semaphore; /* Actual OS synchronization object */
union acpi_operand_object *prev; /* Link for list of acquired mutexes */
union acpi_operand_object *next; /* Link for list of acquired mutexes */
struct acpi_namespace_node *node; /* containing object */
struct acpi_namespace_node *node; /* Containing namespace node */
u8 original_sync_level; /* Owner's original sync level (0-15) */
};
......@@ -220,7 +221,7 @@ struct acpi_object_region
u8 space_id;
union acpi_operand_object *handler; /* Handler for region access */
struct acpi_namespace_node *node; /* containing object */
struct acpi_namespace_node *node; /* Containing namespace node */
union acpi_operand_object *next;
u32 length;
acpi_physical_address address;
......
......@@ -73,9 +73,7 @@ acpi_psx_load_table (
acpi_status
acpi_psx_execute (
struct acpi_namespace_node *method_node,
union acpi_operand_object **params,
union acpi_operand_object **return_obj_desc);
struct acpi_parameter_info *info);
/******************************************************************************
......
......@@ -296,7 +296,7 @@ acpi_install_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
u32 type,
acpi_gpe_handler handler,
acpi_event_handler address,
void *context);
acpi_status
......@@ -312,7 +312,7 @@ acpi_status
acpi_remove_gpe_handler (
acpi_handle gpe_device,
u32 gpe_number,
acpi_gpe_handler handler);
acpi_event_handler address);
acpi_status
acpi_enable_event (
......@@ -333,6 +333,12 @@ acpi_get_event_status (
u32 event,
acpi_event_status *event_status);
acpi_status
acpi_set_gpe_type (
acpi_handle gpe_device,
u32 gpe_number,
u8 type);
acpi_status
acpi_enable_gpe (
acpi_handle gpe_device,
......
......@@ -69,13 +69,14 @@
struct acpi_walk_state
{
u8 data_type; /* To differentiate various internal objs MUST BE FIRST!*/\
u8 walk_type;
acpi_owner_id owner_id; /* Owner of objects created during the walk */
u8 last_predicate; /* Result of last predicate */
u8 reserved; /* For alignment */
u8 current_result; /* */
u8 next_op_info; /* Info about next_op */
u8 num_operands; /* Stack pointer for Operands[] array */
u8 return_used;
u8 walk_type;
u16 opcode; /* Current AML opcode */
u8 scope_depth;
u8 reserved1;
......@@ -91,7 +92,8 @@ struct acpi_walk_state
struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS]; /* Control method arguments */
union acpi_operand_object **caller_return_desc;
union acpi_generic_state *control_state; /* List of control states (nested IFs) */
struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */
struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
struct acpi_namespace_node *method_call_node; /* Called method Node*/
union acpi_parse_object *method_call_op; /* method_call Op if running a method */
......@@ -200,4 +202,21 @@ union acpi_aml_operands
};
/* Internal method parameter list */
struct acpi_parameter_info
{
struct acpi_namespace_node *node;
union acpi_operand_object **parameters;
union acpi_operand_object *return_object;
u8 parameter_type;
u8 return_object_type;
};
/* Types for parameter_type above */
#define ACPI_PARAM_ARGS 0
#define ACPI_PARAM_GPE 1
#endif
......@@ -288,19 +288,6 @@ struct smart_battery_table
};
/*
* High performance timer
*/
struct hpet_table
{
ACPI_TABLE_HEADER_DEF
u32 hardware_id;
u32 base_address [3];
u8 hpet_number;
u16 clock_tick;
u8 attributes;
};
#pragma pack()
......@@ -344,4 +331,20 @@ struct acpi_table_support
#include "actbl2.h" /* Acpi 2.0 table definitions */
#pragma pack(1)
/*
* High performance timer
*/
struct hpet_table
{
ACPI_TABLE_HEADER_DEF
u32 hardware_id;
struct acpi_generic_address base_address;
u8 hpet_number;
u16 clock_tick;
u8 attributes;
};
#pragma pack()
#endif /* __ACTBL_H__ */
......@@ -557,34 +557,56 @@ typedef u32 acpi_event_status;
#define ACPI_GPE_MAX 0xFF
#define ACPI_NUM_GPE 256
#define ACPI_GPE_ENABLE 0
#define ACPI_GPE_DISABLE 1
/*
* GPE info flags - Per GPE
* +---------+-+-+-+
* |Bits 8:3 |2|1|0|
* +---------+-+-+-+
* | | | |
* | | | +- Edge or Level Triggered
* | | +--- Type: Wake or Runtime
* | +----- Enabled for wake?
* +--------<Reserved>
* +-+-+-+---+---+-+
* |7|6|5|4:3|2:1|0|
* +-+-+-+---+---+-+
* | | | | | |
* | | | | | +--- Interrupt type: Edge or Level Triggered
* | | | | +--- Type: Wake-only, Runtime-only, or wake/runtime
* | | | +--- Type of dispatch -- to method, handler, or none
* | | +--- Enabled for runtime?
* | +--- Enabled for wake?
* +--- System state when GPE ocurred (running/waking)
*/
#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 1
#define ACPI_GPE_LEVEL_TRIGGERED (u8) 1
#define ACPI_GPE_EDGE_TRIGGERED (u8) 0
#define ACPI_GPE_XRUPT_TYPE_MASK (u8) 0x01
#define ACPI_GPE_LEVEL_TRIGGERED (u8) 0x01
#define ACPI_GPE_EDGE_TRIGGERED (u8) 0x00
#define ACPI_GPE_TYPE_MASK (u8) 0x06
#define ACPI_GPE_TYPE_WAKE_RUN (u8) 0x06
#define ACPI_GPE_TYPE_WAKE (u8) 0x02
#define ACPI_GPE_TYPE_RUNTIME (u8) 0x04 /* Default */
#define ACPI_GPE_DISPATCH_MASK (u8) 0x18
#define ACPI_GPE_DISPATCH_HANDLER (u8) 0x08
#define ACPI_GPE_DISPATCH_METHOD (u8) 0x10
#define ACPI_GPE_DISPATCH_NOT_USED (u8) 0x00 /* Default */
#define ACPI_GPE_RUN_ENABLE_MASK (u8) 0x20
#define ACPI_GPE_RUN_ENABLED (u8) 0x20
#define ACPI_GPE_RUN_DISABLED (u8) 0x00 /* Default */
#define ACPI_GPE_TYPE_MASK (u8) 2
#define ACPI_GPE_TYPE_WAKE (u8) 2
#define ACPI_GPE_TYPE_RUNTIME (u8) 0 /* Default */
#define ACPI_GPE_WAKE_ENABLE_MASK (u8) 0x40
#define ACPI_GPE_WAKE_ENABLED (u8) 0x40
#define ACPI_GPE_WAKE_DISABLED (u8) 0x00 /* Default */
#define ACPI_GPE_ENABLE_MASK (u8) 4
#define ACPI_GPE_ENABLED (u8) 4
#define ACPI_GPE_DISABLED (u8) 0 /* Default */
#define ACPI_GPE_ENABLE_MASK (u8) 0x60 /* Both run/wake */
#define ACPI_GPE_SYSTEM_MASK (u8) 0x80
#define ACPI_GPE_SYSTEM_RUNNING (u8) 0x80
#define ACPI_GPE_SYSTEM_WAKING (u8) 0x00
/*
* Flags for GPE and Lock interfaces
*/
#define ACPI_EVENT_WAKE_ENABLE 0x2
#define ACPI_EVENT_WAKE_DISABLE 0x2
#define ACPI_EVENT_WAKE_ENABLE 0x2 /* acpi_gpe_enable */
#define ACPI_EVENT_WAKE_DISABLE 0x2 /* acpi_gpe_disable */
#define ACPI_NOT_ISR 0x1
#define ACPI_ISR 0x0
......@@ -789,10 +811,6 @@ typedef
u32 (*acpi_event_handler) (
void *context);
typedef
void (*acpi_gpe_handler) (
void *context);
typedef
void (*acpi_notify_handler) (
acpi_handle device,
......@@ -880,6 +898,7 @@ struct acpi_compatible_id_list
#define ACPI_VALID_HID 0x0004
#define ACPI_VALID_UID 0x0008
#define ACPI_VALID_CID 0x0010
#define ACPI_VALID_SXDS 0x0020
#define ACPI_COMMON_OBJ_INFO \
......@@ -899,12 +918,12 @@ struct acpi_device_info
{
ACPI_COMMON_OBJ_INFO;
u8 highest_dstates[4]; /* _sx_d values 0xFF indicates not valid */
u32 valid; /* Indicates which fields below are valid */
u32 current_status; /* _STA value */
acpi_integer address; /* _ADR value if any */
struct acpi_device_id hardware_id; /* _HID value if any */
struct acpi_device_id unique_id; /* _UID value if any */
u8 highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
struct acpi_compatible_id_list compatibility_id; /* List of _CIDs if any */
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment