patch-2.4.22 linux-2.4.22/drivers/acpi/events/evxfregn.c
Next file: linux-2.4.22/drivers/acpi/executer/Makefile
Previous file: linux-2.4.22/drivers/acpi/events/evxfevnt.c
Back to the patch index
Back to the overall index
- Lines: 522
- Date:
2003-08-25 04:44:41.000000000 -0700
- Orig file:
linux-2.4.21/drivers/acpi/events/evxfregn.c
- Orig date:
2001-10-24 14:06:22.000000000 -0700
diff -urN linux-2.4.21/drivers/acpi/events/evxfregn.c linux-2.4.22/drivers/acpi/events/evxfregn.c
@@ -2,84 +2,101 @@
*
* Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
* Address Spaces.
- * $Revision: 40 $
*
*****************************************************************************/
/*
- * Copyright (C) 2000, 2001 R. Byron Moore
+ * Copyright (C) 2000 - 2003, R. Byron Moore
+ * All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
*/
-#include "acpi.h"
-#include "achware.h"
-#include "acnamesp.h"
-#include "acevents.h"
-#include "amlcode.h"
-#include "acinterp.h"
+#include <acpi/acpi.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acevents.h>
+#include <acpi/acinterp.h>
#define _COMPONENT ACPI_EVENTS
- MODULE_NAME ("evxfregn")
+ ACPI_MODULE_NAME ("evxfregn")
/*******************************************************************************
*
- * FUNCTION: Acpi_install_address_space_handler
+ * FUNCTION: acpi_install_address_space_handler
*
* PARAMETERS: Device - Handle for the device
- * Space_id - The address space ID
+ * 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.
+ * DESCRIPTION: Install a handler for all op_regions of a given space_id.
*
******************************************************************************/
acpi_status
acpi_install_address_space_handler (
- acpi_handle device,
- ACPI_ADR_SPACE_TYPE space_id,
- acpi_adr_space_handler handler,
- acpi_adr_space_setup setup,
- void *context)
+ acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler,
+ acpi_adr_space_setup setup,
+ void *context)
{
- acpi_operand_object *obj_desc;
- acpi_operand_object *handler_obj;
- acpi_namespace_node *node;
- acpi_status status = AE_OK;
- acpi_object_type8 type;
- u16 flags = 0;
+ 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;
- FUNCTION_TRACE ("Acpi_install_address_space_handler");
+ ACPI_FUNCTION_TRACE ("acpi_install_address_space_handler");
/* Parameter validation */
- if ((!device) ||
- ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) ||
- (space_id > ACPI_MAX_ADDRESS_SPACE)) {
+ if (!device) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
- acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
/* Convert and validate the device handle */
@@ -103,7 +120,7 @@
}
if (handler == ACPI_DEFAULT_HANDLER) {
- flags = ADDR_HANDLER_DEFAULT_INSTALLED;
+ flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
switch (space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
@@ -131,55 +148,65 @@
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_NOT_EXIST;
+ status = AE_BAD_PARAMETER;
goto unlock_and_exit;
- break;
}
}
- /*
- * If the caller hasn't specified a setup routine, use the default
- */
+ /* 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
- */
+ /* Check for an existing internal object */
+
obj_desc = acpi_ns_get_attached_object (node);
if (obj_desc) {
/*
- * The object exists.
+ * The attached device object already exists.
* Make sure the handler is not already installed.
*/
+ handler_obj = obj_desc->device.address_space;
- /* check the address handler the user requested */
+ /* Walk the handler list for this device */
- handler_obj = obj_desc->device.addr_handler;
while (handler_obj) {
- /*
- * We have an Address handler, see if user requested this
- * address space.
- */
- if(handler_obj->addr_handler.space_id == space_id) {
- status = AE_EXIST;
+ /* 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;
}
- /*
- * Move through the linked list of handlers
- */
- handler_obj = handler_obj->addr_handler.next;
+ /* 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 */
+ /* obj_desc does not exist, create one */
if (node->type == ACPI_TYPE_ANY) {
type = ACPI_TYPE_DEVICE;
@@ -200,110 +227,117 @@
/* Attach the new object to the Node */
- status = acpi_ns_attach_object (node, obj_desc, (u8) type);
+ 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)) {
- acpi_ut_remove_reference (obj_desc);
goto unlock_and_exit;
}
}
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Installing address handler for region %s(%X) on Device %p(%p)\n",
- acpi_ut_get_region_name (space_id), space_id, node, obj_desc));
+ "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+ acpi_ut_get_region_name (space_id), space_id, node->name.ascii, node, obj_desc));
/*
- * Now we can install the handler
+ * Install the handler
*
- * At this point we know that there is no existing handler.
- * So, we just allocate the object for the handler and link it
+ * 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 (INTERNAL_TYPE_ADDRESS_HANDLER);
+ handler_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
if (!handler_obj) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
}
- handler_obj->addr_handler.space_id = (u8) space_id;
- handler_obj->addr_handler.hflags = flags;
- handler_obj->addr_handler.next = obj_desc->device.addr_handler;
- handler_obj->addr_handler.region_list = NULL;
- handler_obj->addr_handler.node = node;
- handler_obj->addr_handler.handler = handler;
- handler_obj->addr_handler.context = context;
- handler_obj->addr_handler.setup = setup;
+ /* 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.address_space;
+
+ /*
+ * The Device object is the first reference on the handler_obj.
+ * Each region that uses the handler adds a reference.
+ */
+ obj_desc->device.address_space = handler_obj;
/*
- * Now walk the namespace finding all of the regions this
+ * Walk the namespace finding all of the regions this
* handler will manage.
*
- * We start at the device and search the branch toward
+ * 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 we back up and search down the remainder
+ * 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, NS_WALK_UNLOCK,
- acpi_ev_addr_handler_helper,
- handler_obj, NULL);
-
- /*
- * Place this handler 1st on the list
- */
- handler_obj->common.reference_count =
- (u16) (handler_obj->common.reference_count +
- obj_desc->common.reference_count - 1);
- obj_desc->device.addr_handler = handler_obj;
-
+ status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler,
+ handler_obj, NULL);
unlock_and_exit:
- acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
- * FUNCTION: Acpi_remove_address_space_handler
+ * FUNCTION: acpi_remove_address_space_handler
*
- * PARAMETERS: Space_id - The address space ID
+ * PARAMETERS: Device - Handle for the device
+ * space_id - The address space ID
* Handler - Address of the handler
*
* RETURN: Status
*
- * DESCRIPTION: Install a handler for accesses on an Operation Region
+ * DESCRIPTION: Remove a previously installed handler.
*
******************************************************************************/
acpi_status
acpi_remove_address_space_handler (
- acpi_handle device,
- ACPI_ADR_SPACE_TYPE space_id,
- acpi_adr_space_handler handler)
+ acpi_handle device,
+ acpi_adr_space_type space_id,
+ acpi_adr_space_handler handler)
{
- acpi_operand_object *obj_desc;
- acpi_operand_object *handler_obj;
- acpi_operand_object *region_obj;
- acpi_operand_object **last_obj_ptr;
- acpi_namespace_node *node;
- acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *handler_obj;
+ union acpi_operand_object *region_obj;
+ union acpi_operand_object **last_obj_ptr;
+ struct acpi_namespace_node *node;
+ acpi_status status;
- FUNCTION_TRACE ("Acpi_remove_address_space_handler");
+ ACPI_FUNCTION_TRACE ("acpi_remove_address_space_handler");
/* Parameter validation */
- if ((!device) ||
- ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) ||
- (space_id > ACPI_MAX_ADDRESS_SPACE)) {
+ if (!device) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
- acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
/* Convert and validate the device handle */
@@ -313,7 +347,6 @@
goto unlock_and_exit;
}
-
/* Make sure the internal object exists */
obj_desc = acpi_ns_get_attached_object (node);
@@ -322,25 +355,22 @@
goto unlock_and_exit;
}
- /*
- * find the address handler the user requested
- */
- handler_obj = obj_desc->device.addr_handler;
- last_obj_ptr = &obj_desc->device.addr_handler;
+ /* Find the address handler the user requested */
+
+ handler_obj = obj_desc->device.address_space;
+ last_obj_ptr = &obj_desc->device.address_space;
while (handler_obj) {
- /*
- * We have a handler, see if user requested this one
- */
- if (handler_obj->addr_handler.space_id == space_id) {
- /*
- * Got it, first dereference this in the Regions
- */
+ /* We have a handler, see if user requested this one */
+
+ if (handler_obj->address_space.space_id == space_id) {
+ /* Matched space_id, first dereference this in the Regions */
+
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
"Removing address handler %p(%p) for region %s on Device %p(%p)\n",
handler_obj, handler, acpi_ut_get_region_name (space_id),
node, obj_desc));
- region_obj = handler_obj->addr_handler.region_list;
+ region_obj = handler_obj->address_space.region_list;
/* Walk the handler's region list */
@@ -352,51 +382,42 @@
* The region is just inaccessible as indicated to
* the _REG method
*/
- acpi_ev_disassociate_region_from_handler(region_obj, TRUE);
+ acpi_ev_detach_region (region_obj, TRUE);
/*
- * Walk the list, since we took the first region and it
- * was removed from the list by the dissassociate call
- * we just get the first item on the list again
+ * Walk the list: Just grab the head because the
+ * detach_region removed the previous head.
*/
- region_obj = handler_obj->addr_handler.region_list;
+ region_obj = handler_obj->address_space.region_list;
}
- /*
- * Remove this Handler object from the list
- */
- *last_obj_ptr = handler_obj->addr_handler.next;
-
- /*
- * Now we can delete the handler object
- */
- acpi_ut_remove_reference (handler_obj);
- acpi_ut_remove_reference (handler_obj);
+ /* Remove this Handler object from the list */
+ *last_obj_ptr = handler_obj->address_space.next;
+
+ /* Now we can delete the handler object */
+
+ acpi_ut_remove_reference (handler_obj);
goto unlock_and_exit;
}
- /*
- * Move through the linked list of handlers
- */
- last_obj_ptr = &handler_obj->addr_handler.next;
- handler_obj = handler_obj->addr_handler.next;
+ /* Walk the linked list of handlers */
+
+ last_obj_ptr = &handler_obj->address_space.next;
+ handler_obj = handler_obj->address_space.next;
}
+ /* The handler does not exist */
- /*
- * The handler does not exist
- */
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
- "Unable to remove address handler %p for %s(%X), Dev_node %p, obj %p\n",
+ "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n",
handler, acpi_ut_get_region_name (space_id), space_id, node, obj_desc));
status = AE_NOT_EXIST;
-
unlock_and_exit:
- acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return_ACPI_STATUS (status);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)