*****************************************************************************/
/*
- * Copyright (C) 2000 - 2004, R. Byron Moore
+ * Copyright (C) 2000 - 2006, R. Byron Moore
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* POSSIBILITY OF SUCH DAMAGES.
*/
-
#include <acpi/acpi.h>
#include <acpi/acevents.h>
#include <acpi/acnamesp.h>
#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- ACPI_MODULE_NAME ("evregion")
-
+ACPI_MODULE_NAME("evregion")
#define ACPI_NUM_DEFAULT_SPACES 4
+static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
+ ACPI_ADR_SPACE_SYSTEM_MEMORY,
+ ACPI_ADR_SPACE_SYSTEM_IO,
+ ACPI_ADR_SPACE_PCI_CONFIG,
+ ACPI_ADR_SPACE_DATA_TABLE
+};
+
+/* Local prototypes */
-static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
- ACPI_ADR_SPACE_SYSTEM_MEMORY,
- ACPI_ADR_SPACE_SYSTEM_IO,
- ACPI_ADR_SPACE_PCI_CONFIG,
- ACPI_ADR_SPACE_DATA_TABLE};
+static acpi_status
+acpi_ev_reg_run(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
+static acpi_status
+acpi_ev_install_handler(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value);
/*******************************************************************************
*
- * FUNCTION: acpi_ev_init_address_spaces
+ * FUNCTION: acpi_ev_install_region_handlers
*
* PARAMETERS: None
*
*
******************************************************************************/
-acpi_status
-acpi_ev_init_address_spaces (
- void) {
- acpi_status status;
- acpi_native_uint i;
-
+acpi_status 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
* 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,
- acpi_gbl_default_address_spaces[i],
- ACPI_DEFAULT_HANDLER, NULL, NULL);
+ status = acpi_ev_install_space_handler(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i],
+ ACPI_DEFAULT_HANDLER,
+ NULL, NULL);
switch (status) {
case AE_OK:
case AE_SAME_HANDLER:
/* 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);
+}
/*******************************************************************************
*
* FUNCTION: acpi_ev_execute_reg_method
*
- * PARAMETERS: region_obj - Object structure
- * Function - On (1) or Off (0)
+ * PARAMETERS: region_obj - Region object
+ * Function - Passed to _REG: On (1) or Off (0)
*
* RETURN: Status
*
******************************************************************************/
acpi_status
-acpi_ev_execute_reg_method (
- union acpi_operand_object *region_obj,
- u32 function)
+acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
{
- union acpi_operand_object *params[3];
- union acpi_operand_object *region_obj2;
- acpi_status status;
+ struct acpi_parameter_info info;
+ union acpi_operand_object *params[3];
+ union acpi_operand_object *region_obj2;
+ acpi_status status;
+ ACPI_FUNCTION_TRACE("ev_execute_reg_method");
- ACPI_FUNCTION_TRACE ("ev_execute_reg_method");
-
-
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
if (region_obj2->extra.method_REG == NULL) {
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
/*
- * _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
*/
- params[0] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!params[0]) {
- return_ACPI_STATUS (AE_NO_MEMORY);
+ return_ACPI_STATUS(AE_NO_MEMORY);
}
- params[1] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
if (!params[1]) {
status = AE_NO_MEMORY;
goto cleanup;
}
- /* Set up the parameter objects */
+ /* Setup the parameter objects */
params[0]->integer.value = region_obj->region.space_id;
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]);
+ acpi_ut_remove_reference(params[1]);
-cleanup:
- acpi_ut_remove_reference (params[0]);
+ cleanup:
+ acpi_ut_remove_reference(params[0]);
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_address_space_dispatch
*
* PARAMETERS: region_obj - Internal region object
- * space_id - ID of the address space (0-255)
* Function - Read or Write operation
* Address - Where in the space to read or write
* bit_width - Field width in bits (8, 16, 32, or 64)
******************************************************************************/
acpi_status
-acpi_ev_address_space_dispatch (
- union acpi_operand_object *region_obj,
- u32 function,
- acpi_physical_address address,
- u32 bit_width,
- void *value)
+acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
+ u32 function,
+ acpi_physical_address address,
+ u32 bit_width, void *value)
{
- acpi_status status;
- acpi_status status2;
- acpi_adr_space_handler handler;
- acpi_adr_space_setup region_setup;
- union acpi_operand_object *handler_desc;
- union acpi_operand_object *region_obj2;
- void *region_context = NULL;
+ acpi_status status;
+ acpi_status status2;
+ acpi_adr_space_handler handler;
+ acpi_adr_space_setup region_setup;
+ union acpi_operand_object *handler_desc;
+ union acpi_operand_object *region_obj2;
+ void *region_context = NULL;
+ ACPI_FUNCTION_TRACE("ev_address_space_dispatch");
- ACPI_FUNCTION_TRACE ("ev_address_space_dispatch");
-
-
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
- return_ACPI_STATUS (AE_NOT_EXIST);
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Ensure that there is a handler associated with this region */
handler_desc = region_obj->region.handler;
if (!handler_desc) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "No handler for Region [%4.4s] (%p) [%s]\n",
- acpi_ut_get_node_name (region_obj->region.node),
- region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
-
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_ERROR((AE_INFO,
+ "No handler for Region [%4.4s] (%p) [%s]",
+ acpi_ut_get_node_name(region_obj->region.node),
+ region_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
+
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
if (!region_setup) {
/* No initialization routine, exit with error */
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
- region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
- return_ACPI_STATUS (AE_NOT_EXIST);
+ ACPI_ERROR((AE_INFO,
+ "No init routine for region(%p) [%s]",
+ region_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
+ return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
- * We must exit the interpreter because the region setup will potentially
- * execute control methods (e.g., _REG method for this region)
+ * We must exit the interpreter because the region
+ * setup will potentially execute control methods
+ * (e.g., _REG method for this region)
*/
- acpi_ex_exit_interpreter ();
+ acpi_ex_exit_interpreter();
- status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
- handler_desc->address_space.context, ®ion_context);
+ status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
+ handler_desc->address_space.context,
+ ®ion_context);
/* Re-enter the interpreter */
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
- return_ACPI_STATUS (status2);
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
}
/* Check for failure of the Region Setup */
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
- return_ACPI_STATUS (status);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During region initialization: [%s]",
+ acpi_ut_get_region_name(region_obj->
+ region.
+ space_id)));
+ return_ACPI_STATUS(status);
}
/*
if (region_obj2->extra.region_context) {
/* The handler for this region was already installed */
- ACPI_MEM_FREE (region_context);
- }
- else {
+ ACPI_MEM_FREE(region_context);
+ } else {
/*
* Save the returned context for use in all accesses to
* this particular region
*/
- region_obj2->extra.region_context = region_context;
+ region_obj2->extra.region_context =
+ region_context;
}
}
}
handler = handler_desc->address_space.handler;
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
- ®ion_obj->region.handler->address_space, handler,
- ACPI_FORMAT_UINT64 (address),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+ ®ion_obj->region.handler->address_space, handler,
+ 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
/* Call the handler */
- status = handler (function, address, bit_width, value,
+ status = handler(function, address, bit_width, value,
handler_desc->address_space.context,
region_obj2->extra.region_context);
- if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
- acpi_ut_get_region_name (region_obj->region.space_id),
- acpi_format_exception (status)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
+ 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)) {
/*
* We just returned from a non-default handler, we must re-enter the
* interpreter
*/
- status2 = acpi_ex_enter_interpreter ();
- if (ACPI_FAILURE (status2)) {
- return_ACPI_STATUS (status2);
+ status2 = acpi_ex_enter_interpreter();
+ if (ACPI_FAILURE(status2)) {
+ return_ACPI_STATUS(status2);
}
}
- return_ACPI_STATUS (status);
+ return_ACPI_STATUS(status);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_detach_region
*
- * PARAMETERS: region_obj - Region Object
- * acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS: region_obj - Region Object
+ * acpi_ns_is_locked - Namespace Region Already Locked?
*
* RETURN: None
*
******************************************************************************/
void
-acpi_ev_detach_region(
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked)
+acpi_ev_detach_region(union acpi_operand_object *region_obj,
+ u8 acpi_ns_is_locked)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *obj_desc;
- union acpi_operand_object **last_obj_ptr;
- acpi_adr_space_setup region_setup;
- void **region_context;
- union acpi_operand_object *region_obj2;
- acpi_status status;
-
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object **last_obj_ptr;
+ acpi_adr_space_setup region_setup;
+ void **region_context;
+ union acpi_operand_object *region_obj2;
+ acpi_status status;
- ACPI_FUNCTION_TRACE ("ev_detach_region");
+ ACPI_FUNCTION_TRACE("ev_detach_region");
-
- region_obj2 = acpi_ns_get_secondary_object (region_obj);
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
if (!region_obj2) {
return_VOID;
}
/* Is this the correct Region? */
if (obj_desc == region_obj) {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Removing Region %p from address handler %p\n",
- region_obj, handler_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Removing Region %p from address handler %p\n",
+ region_obj, handler_obj));
/* This is it, remove it from the handler's list */
*last_obj_ptr = obj_desc->region.next;
- obj_desc->region.next = NULL; /* Must clear field */
+ obj_desc->region.next = NULL; /* Must clear field */
if (acpi_ns_is_locked) {
- status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Now stop region accesses by executing the _REG method */
- status = acpi_ev_execute_reg_method (region_obj, 0);
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ status = acpi_ev_execute_reg_method(region_obj, 0);
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "from region _REG, [%s]",
+ acpi_ut_get_region_name
+ (region_obj->region.space_id)));
}
if (acpi_ns_is_locked) {
- status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE (status)) {
+ status =
+ acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
return_VOID;
}
}
/* Call the setup handler with the deactivate notification */
region_setup = handler_obj->address_space.setup;
- status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
- handler_obj->address_space.context, region_context);
+ status =
+ region_setup(region_obj, ACPI_REGION_DEACTIVATE,
+ handler_obj->address_space.context,
+ region_context);
/* Init routine may fail, Just ignore errors */
- if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
- acpi_format_exception (status),
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "from region init, [%s]",
+ acpi_ut_get_region_name
+ (region_obj->region.space_id)));
}
region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
* this better be the region's handler
*/
region_obj->region.handler = NULL;
- acpi_ut_remove_reference (handler_obj);
+ acpi_ut_remove_reference(handler_obj);
return_VOID;
}
/* If we get here, the region was not in the handler's region list */
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Cannot remove region %p from address handler %p\n",
- region_obj, handler_obj));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Cannot remove region %p from address handler %p\n",
+ region_obj, handler_obj));
return_VOID;
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_attach_region
*
- * PARAMETERS: handler_obj - Handler Object
- * region_obj - Region Object
- * acpi_ns_is_locked - Namespace Region Already Locked?
+ * PARAMETERS: handler_obj - Handler Object
+ * region_obj - Region Object
+ * acpi_ns_is_locked - Namespace Region Already Locked?
*
* RETURN: None
*
******************************************************************************/
acpi_status
-acpi_ev_attach_region (
- union acpi_operand_object *handler_obj,
- union acpi_operand_object *region_obj,
- u8 acpi_ns_is_locked)
+acpi_ev_attach_region(union acpi_operand_object *handler_obj,
+ union acpi_operand_object *region_obj,
+ u8 acpi_ns_is_locked)
{
- ACPI_FUNCTION_TRACE ("ev_attach_region");
+ ACPI_FUNCTION_TRACE("ev_attach_region");
-
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Adding Region [%4.4s] %p to address handler %p [%s]\n",
- acpi_ut_get_node_name (region_obj->region.node),
- region_obj, handler_obj,
- acpi_ut_get_region_name (region_obj->region.space_id)));
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Adding Region [%4.4s] %p to address handler %p [%s]\n",
+ acpi_ut_get_node_name(region_obj->region.node),
+ region_obj, handler_obj,
+ acpi_ut_get_region_name(region_obj->region.
+ space_id)));
/* Link this region to the front of the handler's list */
/* Install the region's handler */
if (region_obj->region.handler) {
- return_ACPI_STATUS (AE_ALREADY_EXISTS);
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
region_obj->region.handler = handler_obj;
- acpi_ut_add_reference (handler_obj);
+ acpi_ut_add_reference(handler_obj);
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS(AE_OK);
}
-
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_handler
*
******************************************************************************/
-acpi_status
-acpi_ev_install_handler (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+static acpi_status
+acpi_ev_install_handler(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
{
- union acpi_operand_object *handler_obj;
- union acpi_operand_object *next_handler_obj;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
-
-
- ACPI_FUNCTION_NAME ("ev_install_handler");
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *next_handler_obj;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ ACPI_FUNCTION_NAME("ev_install_handler");
- handler_obj = (union acpi_operand_object *) context;
+ handler_obj = (union acpi_operand_object *)context;
/* Parameter validation */
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
* that are allowed to have address space handlers
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
- (node->type != ACPI_TYPE_REGION) &&
- (node != acpi_gbl_root_node)) {
+ (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
/* Devices are handled different than regions */
- if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) {
+ if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) {
/* Check if this Device already has a handler for this address space */
next_handler_obj = obj_desc->device.handler;
while (next_handler_obj) {
/* Found a handler, is it for the same address space? */
- if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) {
- ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Found handler for region [%s] in device %p(%p) handler %p\n",
- acpi_ut_get_region_name (handler_obj->address_space.space_id),
- obj_desc, next_handler_obj, handler_obj));
+ if (next_handler_obj->address_space.space_id ==
+ handler_obj->address_space.space_id) {
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Found handler for region [%s] in device %p(%p) handler %p\n",
+ acpi_ut_get_region_name
+ (handler_obj->address_space.
+ space_id), obj_desc,
+ next_handler_obj,
+ handler_obj));
/*
* Since the object we found it on was a device, then it
*
* First disconnect region for any previous handler (if any)
*/
- acpi_ev_detach_region (obj_desc, FALSE);
+ acpi_ev_detach_region(obj_desc, FALSE);
/* Connect the region to the new handler */
- status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE);
+ status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE);
return (status);
}
/*******************************************************************************
*
- * FUNCTION: acpi_ev_reg_run
+ * FUNCTION: acpi_ev_install_space_handler
*
- * PARAMETERS: walk_namespace callback
+ * 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
*
- * DESCRIPTION: Run _REg method for region objects of the requested space_iD
+ * RETURN: Status
+ *
+ * DESCRIPTION: Install a handler for all op_regions of a given space_id.
+ * Assumes namespace is locked
*
******************************************************************************/
acpi_status
-acpi_ev_reg_run (
- acpi_handle obj_handle,
- u32 level,
- void *context,
- void **return_value)
+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 *handler_obj;
- union acpi_operand_object *obj_desc;
- struct acpi_namespace_node *node;
- acpi_status status;
+ 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");
- handler_obj = (union acpi_operand_object *) context;
+ /*
+ * 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;
+ }
- /* Parameter validation */
+ 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) {
- return (AE_OK);
+ 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 all _REG methods for the input 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
+ *
+ * PARAMETERS: walk_namespace callback
+ *
+ * DESCRIPTION: Run _REg method for region objects of the requested space_iD
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ev_reg_run(acpi_handle obj_handle,
+ u32 level, void *context, void **return_value)
+{
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ acpi_adr_space_type space_id;
+ acpi_status status;
+
+ space_id = *ACPI_CAST_PTR(acpi_adr_space_type, context);
+
/* Convert and validate the device handle */
- node = acpi_ns_map_handle_to_node (obj_handle);
+ node = acpi_ns_map_handle_to_node(obj_handle);
if (!node) {
return (AE_BAD_PARAMETER);
}
* We only care about regions.and objects
* that are allowed to have address space handlers
*/
- if ((node->type != ACPI_TYPE_REGION) &&
- (node != acpi_gbl_root_node)) {
+ if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
return (AE_OK);
}
/* Check for an existing internal object */
- obj_desc = acpi_ns_get_attached_object (node);
+ obj_desc = acpi_ns_get_attached_object(node);
if (!obj_desc) {
/* No object, just exit */
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
return (AE_OK);
}
- status = acpi_ev_execute_reg_method (obj_desc, 1);
+ status = acpi_ev_execute_reg_method(obj_desc, 1);
return (status);
}
-