1 /******************************************************************************
3 * Module Name: evregion - ACPI address_space (op_region) handler dispatch
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2004, R. Byron Moore
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
45 #include <acpi/acpi.h>
46 #include <acpi/acevents.h>
47 #include <acpi/acnamesp.h>
48 #include <acpi/acinterp.h>
50 #define _COMPONENT ACPI_EVENTS
51 ACPI_MODULE_NAME ("evregion")
53 #define ACPI_NUM_DEFAULT_SPACES 4
55 static u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = {
56 ACPI_ADR_SPACE_SYSTEM_MEMORY,
57 ACPI_ADR_SPACE_SYSTEM_IO,
58 ACPI_ADR_SPACE_PCI_CONFIG,
59 ACPI_ADR_SPACE_DATA_TABLE};
62 /*******************************************************************************
64 * FUNCTION: acpi_ev_init_address_spaces
70 * DESCRIPTION: Installs the core subsystem default address space handlers.
72 ******************************************************************************/
75 acpi_ev_init_address_spaces (
81 ACPI_FUNCTION_TRACE ("ev_init_address_spaces");
85 * All address spaces (PCI Config, EC, SMBus) are scope dependent
86 * and registration must occur for a specific device.
88 * In the case of the system memory and IO address spaces there is currently
89 * no device associated with the address space. For these we use the root.
91 * We install the default PCI config space handler at the root so
92 * that this space is immediately available even though the we have
93 * not enumerated all the PCI Root Buses yet. This is to conform
94 * to the ACPI specification which states that the PCI config
95 * space must be always available -- even though we are nowhere
96 * near ready to find the PCI root buses at this point.
98 * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
99 * has already been installed (via acpi_install_address_space_handler).
100 * Similar for AE_SAME_HANDLER.
103 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
104 status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node,
105 acpi_gbl_default_address_spaces[i],
106 ACPI_DEFAULT_HANDLER, NULL, NULL);
109 case AE_SAME_HANDLER:
110 case AE_ALREADY_EXISTS:
112 /* These exceptions are all OK */
118 return_ACPI_STATUS (status);
122 return_ACPI_STATUS (AE_OK);
126 /*******************************************************************************
128 * FUNCTION: acpi_ev_execute_reg_method
130 * PARAMETERS: region_obj - Object structure
131 * Function - On (1) or Off (0)
135 * DESCRIPTION: Execute _REG method for a region
137 ******************************************************************************/
140 acpi_ev_execute_reg_method (
141 union acpi_operand_object *region_obj,
144 union acpi_operand_object *params[3];
145 union acpi_operand_object *region_obj2;
149 ACPI_FUNCTION_TRACE ("ev_execute_reg_method");
152 region_obj2 = acpi_ns_get_secondary_object (region_obj);
154 return_ACPI_STATUS (AE_NOT_EXIST);
157 if (region_obj2->extra.method_REG == NULL) {
158 return_ACPI_STATUS (AE_OK);
162 * _REG method has two arguments
163 * Arg0: Integer: Operation region space ID
164 * Same value as region_obj->Region.space_id
165 * Arg1: Integer: connection status
166 * 1 for connecting the handler,
167 * 0 for disconnecting the handler
168 * Passed as a parameter
170 params[0] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
172 return_ACPI_STATUS (AE_NO_MEMORY);
175 params[1] = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
177 status = AE_NO_MEMORY;
181 /* Set up the parameter objects */
183 params[0]->integer.value = region_obj->region.space_id;
184 params[1]->integer.value = function;
187 /* Execute the method, no return value */
189 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL));
190 status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL);
192 acpi_ut_remove_reference (params[1]);
195 acpi_ut_remove_reference (params[0]);
197 return_ACPI_STATUS (status);
201 /*******************************************************************************
203 * FUNCTION: acpi_ev_address_space_dispatch
205 * PARAMETERS: region_obj - Internal region object
206 * space_id - ID of the address space (0-255)
207 * Function - Read or Write operation
208 * Address - Where in the space to read or write
209 * bit_width - Field width in bits (8, 16, 32, or 64)
210 * Value - Pointer to in or out value
214 * DESCRIPTION: Dispatch an address space or operation region access to
215 * a previously installed handler.
217 ******************************************************************************/
220 acpi_ev_address_space_dispatch (
221 union acpi_operand_object *region_obj,
223 acpi_physical_address address,
229 acpi_adr_space_handler handler;
230 acpi_adr_space_setup region_setup;
231 union acpi_operand_object *handler_desc;
232 union acpi_operand_object *region_obj2;
233 void *region_context = NULL;
236 ACPI_FUNCTION_TRACE ("ev_address_space_dispatch");
239 region_obj2 = acpi_ns_get_secondary_object (region_obj);
241 return_ACPI_STATUS (AE_NOT_EXIST);
244 /* Ensure that there is a handler associated with this region */
246 handler_desc = region_obj->region.handler;
248 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
249 "No handler for Region [%4.4s] (%p) [%s]\n",
250 acpi_ut_get_node_name (region_obj->region.node),
251 region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
253 return_ACPI_STATUS (AE_NOT_EXIST);
257 * It may be the case that the region has never been initialized
258 * Some types of regions require special init code
260 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
262 * This region has not been initialized yet, do it
264 region_setup = handler_desc->address_space.setup;
266 /* No initialization routine, exit with error */
268 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
269 region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
270 return_ACPI_STATUS (AE_NOT_EXIST);
274 * We must exit the interpreter because the region setup will potentially
275 * execute control methods (e.g., _REG method for this region)
277 acpi_ex_exit_interpreter ();
279 status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
280 handler_desc->address_space.context, ®ion_context);
282 /* Re-enter the interpreter */
284 status2 = acpi_ex_enter_interpreter ();
285 if (ACPI_FAILURE (status2)) {
286 return_ACPI_STATUS (status2);
289 /* Check for failure of the Region Setup */
291 if (ACPI_FAILURE (status)) {
292 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
293 acpi_format_exception (status),
294 acpi_ut_get_region_name (region_obj->region.space_id)));
295 return_ACPI_STATUS (status);
299 * Region initialization may have been completed by region_setup
301 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
302 region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
304 if (region_obj2->extra.region_context) {
305 /* The handler for this region was already installed */
307 ACPI_MEM_FREE (region_context);
311 * Save the returned context for use in all accesses to
312 * this particular region
314 region_obj2->extra.region_context = region_context;
319 /* We have everything we need, we can invoke the address space handler */
321 handler = handler_desc->address_space.handler;
323 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
324 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
325 ®ion_obj->region.handler->address_space, handler,
326 ACPI_FORMAT_UINT64 (address),
327 acpi_ut_get_region_name (region_obj->region.space_id)));
329 if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
331 * For handlers other than the default (supplied) handlers, we must
332 * exit the interpreter because the handler *might* block -- we don't
333 * know what it will do, so we can't hold the lock on the intepreter.
335 acpi_ex_exit_interpreter();
338 /* Call the handler */
340 status = handler (function, address, bit_width, value,
341 handler_desc->address_space.context,
342 region_obj2->extra.region_context);
344 if (ACPI_FAILURE (status)) {
345 ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
346 acpi_ut_get_region_name (region_obj->region.space_id),
347 acpi_format_exception (status)));
350 if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
352 * We just returned from a non-default handler, we must re-enter the
355 status2 = acpi_ex_enter_interpreter ();
356 if (ACPI_FAILURE (status2)) {
357 return_ACPI_STATUS (status2);
361 return_ACPI_STATUS (status);
365 /*******************************************************************************
367 * FUNCTION: acpi_ev_detach_region
369 * PARAMETERS: region_obj - Region Object
370 * acpi_ns_is_locked - Namespace Region Already Locked?
374 * DESCRIPTION: Break the association between the handler and the region
375 * this is a two way association.
377 ******************************************************************************/
380 acpi_ev_detach_region(
381 union acpi_operand_object *region_obj,
382 u8 acpi_ns_is_locked)
384 union acpi_operand_object *handler_obj;
385 union acpi_operand_object *obj_desc;
386 union acpi_operand_object **last_obj_ptr;
387 acpi_adr_space_setup region_setup;
388 void **region_context;
389 union acpi_operand_object *region_obj2;
393 ACPI_FUNCTION_TRACE ("ev_detach_region");
396 region_obj2 = acpi_ns_get_secondary_object (region_obj);
400 region_context = ®ion_obj2->extra.region_context;
402 /* Get the address handler from the region object */
404 handler_obj = region_obj->region.handler;
406 /* This region has no handler, all done */
411 /* Find this region in the handler's list */
413 obj_desc = handler_obj->address_space.region_list;
414 last_obj_ptr = &handler_obj->address_space.region_list;
417 /* Is this the correct Region? */
419 if (obj_desc == region_obj) {
420 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
421 "Removing Region %p from address handler %p\n",
422 region_obj, handler_obj));
424 /* This is it, remove it from the handler's list */
426 *last_obj_ptr = obj_desc->region.next;
427 obj_desc->region.next = NULL; /* Must clear field */
429 if (acpi_ns_is_locked) {
430 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
431 if (ACPI_FAILURE (status)) {
436 /* Now stop region accesses by executing the _REG method */
438 status = acpi_ev_execute_reg_method (region_obj, 0);
439 if (ACPI_FAILURE (status)) {
440 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n",
441 acpi_format_exception (status),
442 acpi_ut_get_region_name (region_obj->region.space_id)));
445 if (acpi_ns_is_locked) {
446 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
447 if (ACPI_FAILURE (status)) {
452 /* Call the setup handler with the deactivate notification */
454 region_setup = handler_obj->address_space.setup;
455 status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
456 handler_obj->address_space.context, region_context);
458 /* Init routine may fail, Just ignore errors */
460 if (ACPI_FAILURE (status)) {
461 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n",
462 acpi_format_exception (status),
463 acpi_ut_get_region_name (region_obj->region.space_id)));
466 region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE);
469 * Remove handler reference in the region
471 * NOTE: this doesn't mean that the region goes away
472 * The region is just inaccessible as indicated to
475 * If the region is on the handler's list
476 * this better be the region's handler
478 region_obj->region.handler = NULL;
479 acpi_ut_remove_reference (handler_obj);
484 /* Walk the linked list of handlers */
486 last_obj_ptr = &obj_desc->region.next;
487 obj_desc = obj_desc->region.next;
490 /* If we get here, the region was not in the handler's region list */
492 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
493 "Cannot remove region %p from address handler %p\n",
494 region_obj, handler_obj));
500 /*******************************************************************************
502 * FUNCTION: acpi_ev_attach_region
504 * PARAMETERS: handler_obj - Handler Object
505 * region_obj - Region Object
506 * acpi_ns_is_locked - Namespace Region Already Locked?
510 * DESCRIPTION: Create the association between the handler and the region
511 * this is a two way association.
513 ******************************************************************************/
516 acpi_ev_attach_region (
517 union acpi_operand_object *handler_obj,
518 union acpi_operand_object *region_obj,
519 u8 acpi_ns_is_locked)
522 ACPI_FUNCTION_TRACE ("ev_attach_region");
525 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
526 "Adding Region [%4.4s] %p to address handler %p [%s]\n",
527 acpi_ut_get_node_name (region_obj->region.node),
528 region_obj, handler_obj,
529 acpi_ut_get_region_name (region_obj->region.space_id)));
531 /* Link this region to the front of the handler's list */
533 region_obj->region.next = handler_obj->address_space.region_list;
534 handler_obj->address_space.region_list = region_obj;
536 /* Install the region's handler */
538 if (region_obj->region.handler) {
539 return_ACPI_STATUS (AE_ALREADY_EXISTS);
542 region_obj->region.handler = handler_obj;
543 acpi_ut_add_reference (handler_obj);
545 return_ACPI_STATUS (AE_OK);
549 /*******************************************************************************
551 * FUNCTION: acpi_ev_install_handler
553 * PARAMETERS: walk_namespace callback
555 * DESCRIPTION: This routine installs an address handler into objects that are
556 * of type Region or Device.
558 * If the Object is a Device, and the device has a handler of
559 * the same type then the search is terminated in that branch.
561 * This is because the existing handler is closer in proximity
562 * to any more regions than the one we are trying to install.
564 ******************************************************************************/
567 acpi_ev_install_handler (
568 acpi_handle obj_handle,
573 union acpi_operand_object *handler_obj;
574 union acpi_operand_object *next_handler_obj;
575 union acpi_operand_object *obj_desc;
576 struct acpi_namespace_node *node;
580 ACPI_FUNCTION_NAME ("ev_install_handler");
583 handler_obj = (union acpi_operand_object *) context;
585 /* Parameter validation */
591 /* Convert and validate the device handle */
593 node = acpi_ns_map_handle_to_node (obj_handle);
595 return (AE_BAD_PARAMETER);
599 * We only care about regions.and objects
600 * that are allowed to have address space handlers
602 if ((node->type != ACPI_TYPE_DEVICE) &&
603 (node->type != ACPI_TYPE_REGION) &&
604 (node != acpi_gbl_root_node)) {
608 /* Check for an existing internal object */
610 obj_desc = acpi_ns_get_attached_object (node);
612 /* No object, just exit */
617 /* Devices are handled different than regions */
619 if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) {
620 /* Check if this Device already has a handler for this address space */
622 next_handler_obj = obj_desc->device.handler;
623 while (next_handler_obj) {
624 /* Found a handler, is it for the same address space? */
626 if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) {
627 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
628 "Found handler for region [%s] in device %p(%p) handler %p\n",
629 acpi_ut_get_region_name (handler_obj->address_space.space_id),
630 obj_desc, next_handler_obj, handler_obj));
633 * Since the object we found it on was a device, then it
634 * means that someone has already installed a handler for
635 * the branch of the namespace from this device on. Just
636 * bail out telling the walk routine to not traverse this
637 * branch. This preserves the scoping rule for handlers.
639 return (AE_CTRL_DEPTH);
642 /* Walk the linked list of handlers attached to this device */
644 next_handler_obj = next_handler_obj->address_space.next;
648 * As long as the device didn't have a handler for this
649 * space we don't care about it. We just ignore it and
655 /* Object is a Region */
657 if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
659 * This region is for a different address space
666 * Now we have a region and it is for the handler's address
669 * First disconnect region for any previous handler (if any)
671 acpi_ev_detach_region (obj_desc, FALSE);
673 /* Connect the region to the new handler */
675 status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE);
679 /*******************************************************************************
681 * FUNCTION: acpi_ev_reg_run
683 * PARAMETERS: walk_namespace callback
685 * DESCRIPTION: Run _REg method for region objects of the requested space_iD
687 ******************************************************************************/
691 acpi_handle obj_handle,
696 union acpi_operand_object *handler_obj;
697 union acpi_operand_object *obj_desc;
698 struct acpi_namespace_node *node;
702 handler_obj = (union acpi_operand_object *) context;
704 /* Parameter validation */
710 /* Convert and validate the device handle */
712 node = acpi_ns_map_handle_to_node (obj_handle);
714 return (AE_BAD_PARAMETER);
718 * We only care about regions.and objects
719 * that are allowed to have address space handlers
721 if ((node->type != ACPI_TYPE_REGION) &&
722 (node != acpi_gbl_root_node)) {
726 /* Check for an existing internal object */
728 obj_desc = acpi_ns_get_attached_object (node);
730 /* No object, just exit */
736 /* Object is a Region */
738 if (obj_desc->region.space_id != handler_obj->address_space.space_id) {
740 * This region is for a different address space
746 status = acpi_ev_execute_reg_method (obj_desc, 1);