1 /******************************************************************************
3 * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #define _COMPONENT ACPI_EVENTS
36 MODULE_NAME ("evxfregn")
39 /******************************************************************************
41 * FUNCTION: Acpi_install_address_space_handler
43 * PARAMETERS: Device - Handle for the device
44 * Space_id - The address space ID
45 * Handler - Address of the handler
46 * Setup - Address of the setup function
47 * Context - Value passed to the handler on each access
51 * DESCRIPTION: Install a handler for all Op_regions of a given Space_id.
53 ******************************************************************************/
56 acpi_install_address_space_handler (
58 ACPI_ADDRESS_SPACE_TYPE space_id,
59 ADDRESS_SPACE_HANDLER handler,
60 ADDRESS_SPACE_SETUP setup,
63 ACPI_OPERAND_OBJECT *obj_desc;
64 ACPI_OPERAND_OBJECT *handler_obj;
65 ACPI_NAMESPACE_NODE *node;
66 ACPI_STATUS status = AE_OK;
67 OBJECT_TYPE_INTERNAL type;
71 /* Parameter validation */
74 ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) ||
75 (space_id > ACPI_MAX_ADDRESS_SPACE)) {
76 return (AE_BAD_PARAMETER);
79 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
81 /* Convert and validate the device handle */
83 node = acpi_ns_convert_handle_to_entry (device);
85 status = AE_BAD_PARAMETER;
90 * This registration is valid for only the types below
91 * and the root. This is where the default handlers
95 if ((node->type != ACPI_TYPE_DEVICE) &&
96 (node->type != ACPI_TYPE_PROCESSOR) &&
97 (node->type != ACPI_TYPE_THERMAL) &&
98 (node != acpi_gbl_root_node)) {
99 status = AE_BAD_PARAMETER;
100 goto unlock_and_exit;
103 if (handler == ACPI_DEFAULT_HANDLER) {
104 flags = ADDR_HANDLER_DEFAULT_INSTALLED;
107 case ADDRESS_SPACE_SYSTEM_MEMORY:
108 handler = acpi_aml_system_memory_space_handler;
109 setup = acpi_ev_system_memory_region_setup;
112 case ADDRESS_SPACE_SYSTEM_IO:
113 handler = acpi_aml_system_io_space_handler;
114 setup = acpi_ev_io_space_region_setup;
117 case ADDRESS_SPACE_PCI_CONFIG:
118 handler = acpi_aml_pci_config_space_handler;
119 setup = acpi_ev_pci_config_region_setup;
123 status = AE_NOT_EXIST;
124 goto unlock_and_exit;
130 * If the caller hasn't specified a setup routine, use the default
133 setup = acpi_ev_default_region_setup;
137 * Check for an existing internal object
140 obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node);
144 * Make sure the handler is not already installed.
147 /* check the address handler the user requested */
149 handler_obj = obj_desc->device.addr_handler;
150 while (handler_obj) {
152 * We have an Address handler, see if user requested this
155 if(handler_obj->addr_handler.space_id == space_id) {
157 goto unlock_and_exit;
161 * Move through the linked list of handlers
163 handler_obj = handler_obj->addr_handler.next;
168 /* Obj_desc does not exist, create one */
170 if (node->type == ACPI_TYPE_ANY) {
171 type = ACPI_TYPE_DEVICE;
178 obj_desc = acpi_cm_create_internal_object (type);
180 status = AE_NO_MEMORY;
181 goto unlock_and_exit;
184 /* Init new descriptor */
186 obj_desc->common.type = (u8) type;
188 /* Attach the new object to the Node */
190 status = acpi_ns_attach_object (node, obj_desc, (u8) type);
191 if (ACPI_FAILURE (status)) {
192 acpi_cm_remove_reference (obj_desc);
193 goto unlock_and_exit;
198 * Now we can install the handler
200 * At this point we know that there is no existing handler.
201 * So, we just allocate the object for the handler and link it
204 handler_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER);
206 status = AE_NO_MEMORY;
207 goto unlock_and_exit;
210 handler_obj->addr_handler.space_id = (u8) space_id;
211 handler_obj->addr_handler.hflags = flags;
212 handler_obj->addr_handler.next = obj_desc->device.addr_handler;
213 handler_obj->addr_handler.region_list = NULL;
214 handler_obj->addr_handler.node = node;
215 handler_obj->addr_handler.handler = handler;
216 handler_obj->addr_handler.context = context;
217 handler_obj->addr_handler.setup = setup;
220 * Now walk the namespace finding all of the regions this
221 * handler will manage.
223 * We start at the device and search the branch toward
224 * the leaf nodes until either the leaf is encountered or
225 * a device is detected that has an address handler of the
228 * In either case we back up and search down the remainder
231 status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device,
232 ACPI_UINT32_MAX, NS_WALK_UNLOCK,
233 acpi_ev_addr_handler_helper,
237 * Place this handler 1st on the list
240 handler_obj->common.reference_count =
241 (u16) (handler_obj->common.reference_count +
242 obj_desc->common.reference_count - 1);
243 obj_desc->device.addr_handler = handler_obj;
247 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
252 /******************************************************************************
254 * FUNCTION: Acpi_remove_address_space_handler
256 * PARAMETERS: Space_id - The address space ID
257 * Handler - Address of the handler
261 * DESCRIPTION: Install a handler for accesses on an Operation Region
263 ******************************************************************************/
266 acpi_remove_address_space_handler (
268 ACPI_ADDRESS_SPACE_TYPE space_id,
269 ADDRESS_SPACE_HANDLER handler)
271 ACPI_OPERAND_OBJECT *obj_desc;
272 ACPI_OPERAND_OBJECT *handler_obj;
273 ACPI_OPERAND_OBJECT *region_obj;
274 ACPI_OPERAND_OBJECT **last_obj_ptr;
275 ACPI_NAMESPACE_NODE *node;
276 ACPI_STATUS status = AE_OK;
279 /* Parameter validation */
282 ((!handler) && (handler != ACPI_DEFAULT_HANDLER)) ||
283 (space_id > ACPI_MAX_ADDRESS_SPACE)) {
284 return (AE_BAD_PARAMETER);
287 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
289 /* Convert and validate the device handle */
291 node = acpi_ns_convert_handle_to_entry (device);
293 status = AE_BAD_PARAMETER;
294 goto unlock_and_exit;
298 /* Make sure the internal object exists */
300 obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node);
305 status = AE_NOT_EXIST;
306 goto unlock_and_exit;
310 * find the address handler the user requested
313 handler_obj = obj_desc->device.addr_handler;
314 last_obj_ptr = &obj_desc->device.addr_handler;
315 while (handler_obj) {
317 * We have a handler, see if user requested this one
320 if(handler_obj->addr_handler.space_id == space_id) {
322 * Got it, first dereference this in the Regions
324 region_obj = handler_obj->addr_handler.region_list;
326 /* Walk the handler's region list */
330 * First disassociate the handler from the region.
332 * NOTE: this doesn't mean that the region goes away
333 * The region is just inaccessible as indicated to
336 acpi_ev_disassociate_region_from_handler(region_obj, FALSE);
339 * Walk the list, since we took the first region and it
340 * was removed from the list by the dissassociate call
341 * we just get the first item on the list again
343 region_obj = handler_obj->addr_handler.region_list;
348 * Remove this Handler object from the list
350 *last_obj_ptr = handler_obj->addr_handler.next;
353 * Now we can delete the handler object
355 acpi_cm_remove_reference (handler_obj);
356 acpi_cm_remove_reference (handler_obj);
358 goto unlock_and_exit;
362 * Move through the linked list of handlers
364 last_obj_ptr = &handler_obj->addr_handler.next;
365 handler_obj = handler_obj->addr_handler.next;
370 * The handler does not exist
372 status = AE_NOT_EXIST;
376 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);