More Makefile cleanups, otherwise mainly noticeable are the netfilter fix
[davej-history.git] / drivers / acpi / events / evregion.c
blob53cae63925aa9e7f31ac57b5525b4ebf96cded04
1 /******************************************************************************
3 * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch
4 * $Revision: 93 $
6 *****************************************************************************/
8 /*
9 * Copyright (C) 2000 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "acpi.h"
28 #include "acevents.h"
29 #include "acnamesp.h"
30 #include "acinterp.h"
31 #include "amlcode.h"
33 #define _COMPONENT EVENT_HANDLING
34 MODULE_NAME ("evregion")
37 /**************************************************************************
39 * FUNCTION: Acpi_ev_install_default_address_space_handlers
41 * PARAMETERS:
43 * RETURN: Status
45 * DESCRIPTION: Installs the core subsystem address space handlers.
47 *************************************************************************/
49 ACPI_STATUS
50 acpi_ev_install_default_address_space_handlers (
51 void)
53 ACPI_STATUS status;
57 * All address spaces (PCI Config, EC, SMBus) are scope dependent
58 * and registration must occur for a specific device. In the case
59 * system memory and IO address spaces there is currently no device
60 * associated with the address space. For these we use the root.
61 * We install the default PCI config space handler at the root so
62 * that this space is immediately available even though the we have
63 * not enumerated all the PCI Root Buses yet. This is to conform
64 * to the ACPI specification which states that the PCI config
65 * space must be always available -- even though we are nowhere
66 * near ready to find the PCI root buses at this point.
68 * NOTE: We ignore AE_EXIST because this means that a handler has
69 * already been installed (via Acpi_install_address_space_handler)
72 status = acpi_install_address_space_handler (acpi_gbl_root_node,
73 ADDRESS_SPACE_SYSTEM_MEMORY,
74 ACPI_DEFAULT_HANDLER, NULL, NULL);
75 if ((ACPI_FAILURE (status)) &&
76 (status != AE_EXIST))
78 return (status);
81 status = acpi_install_address_space_handler (acpi_gbl_root_node,
82 ADDRESS_SPACE_SYSTEM_IO,
83 ACPI_DEFAULT_HANDLER, NULL, NULL);
84 if ((ACPI_FAILURE (status)) &&
85 (status != AE_EXIST))
87 return (status);
90 status = acpi_install_address_space_handler (acpi_gbl_root_node,
91 ADDRESS_SPACE_PCI_CONFIG,
92 ACPI_DEFAULT_HANDLER, NULL, NULL);
93 if ((ACPI_FAILURE (status)) &&
94 (status != AE_EXIST))
96 return (status);
100 return (AE_OK);
104 /* TBD: [Restructure] Move elsewhere */
106 /**************************************************************************
108 * FUNCTION: Acpi_ev_execute_reg_method
110 * PARAMETERS: Region_obj - Object structure
111 * Function - On (1) or Off (0)
113 * RETURN: Status
115 * DESCRIPTION: Execute _REG method for a region
117 *************************************************************************/
119 static ACPI_STATUS
120 acpi_ev_execute_reg_method (
121 ACPI_OPERAND_OBJECT *region_obj,
122 u32 function)
124 ACPI_OPERAND_OBJECT *params[3];
125 ACPI_OPERAND_OBJECT space_iD_obj;
126 ACPI_OPERAND_OBJECT function_obj;
127 ACPI_STATUS status;
130 if (region_obj->region.extra->extra.method_REG == NULL) {
131 return (AE_OK);
135 * _REG method has two arguments
136 * Arg0: Integer: Operation region space ID
137 * Same value as Region_obj->Region.Space_id
138 * Arg1: Integer: connection status
139 * 1 for connecting the handler,
140 * 0 for disconnecting the handler
141 * Passed as a parameter
144 acpi_cm_init_static_object (&space_iD_obj);
145 acpi_cm_init_static_object (&function_obj);
148 * Method requires two parameters.
150 params [0] = &space_iD_obj;
151 params [1] = &function_obj;
152 params [2] = NULL;
155 * Set up the parameter objects
157 space_iD_obj.common.type = ACPI_TYPE_NUMBER;
158 space_iD_obj.number.value = region_obj->region.space_id;
160 function_obj.common.type = ACPI_TYPE_NUMBER;
161 function_obj.number.value = function;
164 * Execute the method, no return value
166 status = acpi_ns_evaluate_by_handle (region_obj->region.extra->extra.method_REG, params, NULL);
167 return (status);
171 /**************************************************************************
173 * FUNCTION: Acpi_ev_address_space_dispatch
175 * PARAMETERS: Region_obj - internal region object
176 * Space_id - ID of the address space (0-255)
177 * Function - Read or Write operation
178 * Address - Where in the space to read or write
179 * Bit_width - Field width in bits (8, 16, or 32)
180 * Value - Pointer to in or out value
182 * RETURN: Status
184 * DESCRIPTION: Dispatch an address space or operation region access to
185 * a previously installed handler.
187 *************************************************************************/
189 ACPI_STATUS
190 acpi_ev_address_space_dispatch (
191 ACPI_OPERAND_OBJECT *region_obj,
192 u32 function,
193 ACPI_PHYSICAL_ADDRESS address,
194 u32 bit_width,
195 u32 *value)
197 ACPI_STATUS status;
198 ADDRESS_SPACE_HANDLER handler;
199 ADDRESS_SPACE_SETUP region_setup;
200 ACPI_OPERAND_OBJECT *handler_desc;
201 void *region_context = NULL;
205 * Check for an installed handler
207 handler_desc = region_obj->region.addr_handler;
209 if (!handler_desc) {
210 return(AE_NOT_EXIST);
214 * It may be the case that the region has never been initialized
215 * Some types of regions require special init code
217 if (!(region_obj->region.flags & AOPOBJ_INITIALIZED)) {
219 * This region has not been initialized yet, do it
221 region_setup = handler_desc->addr_handler.setup;
222 if (!region_setup) {
224 * Bad news, no init routine and not init'd
226 return (AE_UNKNOWN_STATUS);
230 * We must exit the interpreter because the region setup will potentially
231 * execute control methods
233 acpi_aml_exit_interpreter ();
235 status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
236 handler_desc->addr_handler.context,
237 &region_context);
239 /* Re-enter the interpreter */
241 acpi_aml_enter_interpreter ();
244 * Init routine may fail
246 if (ACPI_FAILURE (status)) {
247 return(status);
250 region_obj->region.flags |= AOPOBJ_INITIALIZED;
253 * Save the returned context for use in all accesses to
254 * this particular region.
256 region_obj->region.extra->extra.region_context = region_context;
260 * We have everything we need, begin the process
262 handler = handler_desc->addr_handler.handler;
264 if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) {
266 * For handlers other than the default (supplied) handlers, we must
267 * exit the interpreter because the handler *might* block -- we don't
268 * know what it will do, so we can't hold the lock on the intepreter.
270 acpi_aml_exit_interpreter();
274 * Invoke the handler.
276 status = handler (function, address, bit_width, value,
277 handler_desc->addr_handler.context,
278 region_obj->region.extra->extra.region_context);
281 if (!(handler_desc->addr_handler.flags & ADDR_HANDLER_DEFAULT_INSTALLED)) {
282 /* We just returned from a non-default handler, we must re-enter the
283 interpreter */
285 acpi_aml_enter_interpreter ();
288 return (status);
291 /******************************************************************************
293 * FUNCTION: Acpi_ev_disassociate_region_from_handler
295 * PARAMETERS: Region_obj - Region Object
296 * Acpi_ns_is_locked - Namespace Region Already Locked?
298 * RETURN: None
300 * DESCRIPTION: Break the association between the handler and the region
301 * this is a two way association.
303 ******************************************************************************/
305 void
306 acpi_ev_disassociate_region_from_handler(
307 ACPI_OPERAND_OBJECT *region_obj,
308 u8 acpi_ns_is_locked)
310 ACPI_OPERAND_OBJECT *handler_obj;
311 ACPI_OPERAND_OBJECT *obj_desc;
312 ACPI_OPERAND_OBJECT **last_obj_ptr;
313 ADDRESS_SPACE_SETUP region_setup;
314 void *region_context;
315 ACPI_STATUS status;
318 region_context = region_obj->region.extra->extra.region_context;
321 * Get the address handler from the region object
324 handler_obj = region_obj->region.addr_handler;
325 if (!handler_obj) {
327 * This region has no handler, all done
329 return;
334 * Find this region in the handler's list
337 obj_desc = handler_obj->addr_handler.region_list;
338 last_obj_ptr = &handler_obj->addr_handler.region_list;
340 while (obj_desc) {
342 * See if this is the one
344 if (obj_desc == region_obj) {
346 * This is it, remove it from the handler's list
348 *last_obj_ptr = obj_desc->region.next;
349 obj_desc->region.next = NULL; /* Must clear field */
351 if (acpi_ns_is_locked) {
352 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
356 * Now stop region accesses by executing the _REG method
358 acpi_ev_execute_reg_method (region_obj, 0);
360 if (acpi_ns_is_locked) {
361 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
365 * Call the setup handler with the deactivate notification
367 region_setup = handler_obj->addr_handler.setup;
368 status = region_setup (region_obj, ACPI_REGION_DEACTIVATE,
369 handler_obj->addr_handler.context,
370 &region_context);
373 * Init routine may fail, Just ignore errors
376 region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);
379 * Remove handler reference in the region
381 * NOTE: this doesn't mean that the region goes away
382 * The region is just inaccessible as indicated to
383 * the _REG method
385 * If the region is on the handler's list
386 * this better be the region's handler
388 ACPI_ASSERT (region_obj->region.addr_handler == handler_obj);
390 region_obj->region.addr_handler = NULL;
392 return;
394 } /* found the right handler */
397 * Move through the linked list of handlers
399 last_obj_ptr = &obj_desc->region.next;
400 obj_desc = obj_desc->region.next;
404 * If we get here, the region was not in the handler's region list
406 return;
410 /******************************************************************************
412 * FUNCTION: Acpi_ev_associate_region_and_handler
414 * PARAMETERS: Handler_obj - Handler Object
415 * Region_obj - Region Object
416 * Acpi_ns_is_locked - Namespace Region Already Locked?
418 * RETURN: None
420 * DESCRIPTION: Create the association between the handler and the region
421 * this is a two way association.
423 ******************************************************************************/
425 ACPI_STATUS
426 acpi_ev_associate_region_and_handler (
427 ACPI_OPERAND_OBJECT *handler_obj,
428 ACPI_OPERAND_OBJECT *region_obj,
429 u8 acpi_ns_is_locked)
431 ACPI_STATUS status;
434 ACPI_ASSERT (region_obj->region.space_id == handler_obj->addr_handler.space_id);
435 ACPI_ASSERT (region_obj->region.addr_handler == 0);
438 * Link this region to the front of the handler's list
441 region_obj->region.next = handler_obj->addr_handler.region_list;
442 handler_obj->addr_handler.region_list = region_obj;
445 * set the region's handler
449 Handler_obj->Common.Reference_count =
450 (u16) (Handler_obj->Common.Reference_count +
451 Region_obj->Common.Reference_count - 1);
453 region_obj->region.addr_handler = handler_obj;
456 * Last thing, tell all users that this region is usable
458 if (acpi_ns_is_locked) {
459 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
462 status = acpi_ev_execute_reg_method (region_obj, 1);
464 if (acpi_ns_is_locked) {
465 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
468 return (status);
472 /****************************************************************************
474 * FUNCTION: Acpi_ev_addr_handler_helper
476 * PARAMETERS: Handle - Node to be dumped
477 * Level - Nesting level of the handle
478 * Context - Passed into Acpi_ns_walk_namespace
480 * DESCRIPTION: This routine checks to see if the object is a Region if it
481 * is then the address handler is installed in it.
483 * If the Object is a Device, and the device has a handler of
484 * the same type then the search is terminated in that branch.
486 * This is because the existing handler is closer in proximity
487 * to any more regions than the one we are trying to install.
489 ***************************************************************************/
491 ACPI_STATUS
492 acpi_ev_addr_handler_helper (
493 ACPI_HANDLE obj_handle,
494 u32 level,
495 void *context,
496 void **return_value)
498 ACPI_OPERAND_OBJECT *handler_obj;
499 ACPI_OPERAND_OBJECT *tmp_obj;
500 ACPI_OPERAND_OBJECT *obj_desc;
501 ACPI_NAMESPACE_NODE *node;
502 ACPI_STATUS status;
505 handler_obj = (ACPI_OPERAND_OBJECT *) context;
507 /* Parameter validation */
509 if (!handler_obj) {
510 return (AE_OK);
513 /* Convert and validate the device handle */
515 node = acpi_ns_convert_handle_to_entry (obj_handle);
516 if (!node) {
517 return (AE_BAD_PARAMETER);
521 * We only care about regions.and objects
522 * that can have address handlers
525 if ((node->type != ACPI_TYPE_DEVICE) &&
526 (node->type != ACPI_TYPE_REGION) &&
527 (node != acpi_gbl_root_node))
529 return (AE_OK);
532 /* Check for an existing internal object */
534 obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node);
535 if (!obj_desc) {
537 * The object DNE, we don't care about it
539 return (AE_OK);
543 * Devices are handled different than regions
545 if (IS_THIS_OBJECT_TYPE (obj_desc, ACPI_TYPE_DEVICE)) {
547 * See if this guy has any handlers
549 tmp_obj = obj_desc->device.addr_handler;
550 while (tmp_obj) {
552 * Now let's see if it's for the same address space.
554 if (tmp_obj->addr_handler.space_id == handler_obj->addr_handler.space_id) {
556 * It's for the same address space
560 * Since the object we found it on was a device, then it
561 * means that someone has already installed a handler for
562 * the branch of the namespace from this device on. Just
563 * bail out telling the walk routine to not traverse this
564 * branch. This preserves the scoping rule for handlers.
566 return (AE_CTRL_DEPTH);
570 * Move through the linked list of handlers
572 tmp_obj = tmp_obj->addr_handler.next;
576 * As long as the device didn't have a handler for this
577 * space we don't care about it. We just ignore it and
578 * proceed.
580 return (AE_OK);
584 * Only here if it was a region
586 ACPI_ASSERT (obj_desc->common.type == ACPI_TYPE_REGION);
588 if (obj_desc->region.space_id != handler_obj->addr_handler.space_id) {
590 * This region is for a different address space
591 * ignore it
593 return (AE_OK);
597 * Now we have a region and it is for the handler's address
598 * space type.
600 * First disconnect region for any previous handler (if any)
602 acpi_ev_disassociate_region_from_handler (obj_desc, FALSE);
605 * Then connect the region to the new handler
607 status = acpi_ev_associate_region_and_handler (handler_obj, obj_desc, FALSE);
609 return (status);