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
30 #define _COMPONENT ACPI_EVENTS
31 MODULE_NAME ("evxfregn")
34 /******************************************************************************
36 * FUNCTION: Acpi_install_address_space_handler
38 * PARAMETERS: Device - Handle for the device
39 * Space_id - The address space ID
40 * Handler - Address of the handler
41 * Setup - Address of the setup function
42 * Context - Value passed to the handler on each access
46 * DESCRIPTION: Install a handler for all Op_regions of a given Space_id.
48 ******************************************************************************/
51 acpi_install_address_space_handler (
53 ACPI_ADDRESS_SPACE_TYPE space_id
,
54 ADDRESS_SPACE_HANDLER handler
,
55 ADDRESS_SPACE_SETUP setup
,
58 ACPI_OPERAND_OBJECT
*obj_desc
;
59 ACPI_OPERAND_OBJECT
*handler_obj
;
60 ACPI_NAMESPACE_NODE
*node
;
61 ACPI_STATUS status
= AE_OK
;
62 OBJECT_TYPE_INTERNAL type
;
66 /* Parameter validation */
69 ((!handler
) && (handler
!= ACPI_DEFAULT_HANDLER
))) {
70 return (AE_BAD_PARAMETER
);
73 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
75 /* Convert and validate the device handle */
77 node
= acpi_ns_convert_handle_to_entry (device
);
79 status
= AE_BAD_PARAMETER
;
84 * This registration is valid for only the types below
85 * and the root. This is where the default handlers
89 if ((node
->type
!= ACPI_TYPE_DEVICE
) &&
90 (node
->type
!= ACPI_TYPE_PROCESSOR
) &&
91 (node
->type
!= ACPI_TYPE_THERMAL
) &&
92 (node
!= acpi_gbl_root_node
)) {
93 status
= AE_BAD_PARAMETER
;
97 if (handler
== ACPI_DEFAULT_HANDLER
) {
98 flags
= ADDR_HANDLER_DEFAULT_INSTALLED
;
101 case ADDRESS_SPACE_SYSTEM_MEMORY
:
102 handler
= acpi_aml_system_memory_space_handler
;
103 setup
= acpi_ev_system_memory_region_setup
;
106 case ADDRESS_SPACE_SYSTEM_IO
:
107 handler
= acpi_aml_system_io_space_handler
;
108 setup
= acpi_ev_io_space_region_setup
;
111 case ADDRESS_SPACE_PCI_CONFIG
:
112 handler
= acpi_aml_pci_config_space_handler
;
113 setup
= acpi_ev_pci_config_region_setup
;
117 status
= AE_NOT_EXIST
;
118 goto unlock_and_exit
;
124 * If the caller hasn't specified a setup routine, use the default
127 setup
= acpi_ev_default_region_setup
;
131 * Check for an existing internal object
134 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
138 * Make sure the handler is not already installed.
141 /* check the address handler the user requested */
143 handler_obj
= obj_desc
->device
.addr_handler
;
144 while (handler_obj
) {
146 * We have an Address handler, see if user requested this
149 if(handler_obj
->addr_handler
.space_id
== space_id
) {
151 goto unlock_and_exit
;
155 * Move through the linked list of handlers
157 handler_obj
= handler_obj
->addr_handler
.next
;
162 /* Obj_desc does not exist, create one */
164 if (node
->type
== ACPI_TYPE_ANY
) {
165 type
= ACPI_TYPE_DEVICE
;
172 obj_desc
= acpi_cm_create_internal_object (type
);
174 status
= AE_NO_MEMORY
;
175 goto unlock_and_exit
;
178 /* Init new descriptor */
180 obj_desc
->common
.type
= (u8
) type
;
182 /* Attach the new object to the Node */
184 status
= acpi_ns_attach_object (node
, obj_desc
, (u8
) type
);
185 if (ACPI_FAILURE (status
)) {
186 acpi_cm_remove_reference (obj_desc
);
187 goto unlock_and_exit
;
192 * Now we can install the handler
194 * At this point we know that there is no existing handler.
195 * So, we just allocate the object for the handler and link it
198 handler_obj
= acpi_cm_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER
);
200 status
= AE_NO_MEMORY
;
201 goto unlock_and_exit
;
204 handler_obj
->addr_handler
.space_id
= (u8
) space_id
;
205 handler_obj
->addr_handler
.hflags
= flags
;
206 handler_obj
->addr_handler
.next
= obj_desc
->device
.addr_handler
;
207 handler_obj
->addr_handler
.region_list
= NULL
;
208 handler_obj
->addr_handler
.node
= node
;
209 handler_obj
->addr_handler
.handler
= handler
;
210 handler_obj
->addr_handler
.context
= context
;
211 handler_obj
->addr_handler
.setup
= setup
;
214 * Now walk the namespace finding all of the regions this
215 * handler will manage.
217 * We start at the device and search the branch toward
218 * the leaf nodes until either the leaf is encountered or
219 * a device is detected that has an address handler of the
222 * In either case we back up and search down the remainder
225 status
= acpi_ns_walk_namespace (ACPI_TYPE_ANY
, device
,
226 ACPI_UINT32_MAX
, NS_WALK_UNLOCK
,
227 acpi_ev_addr_handler_helper
,
231 * Place this handler 1st on the list
234 handler_obj
->common
.reference_count
=
235 (u16
) (handler_obj
->common
.reference_count
+
236 obj_desc
->common
.reference_count
- 1);
237 obj_desc
->device
.addr_handler
= handler_obj
;
241 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
246 /******************************************************************************
248 * FUNCTION: Acpi_remove_address_space_handler
250 * PARAMETERS: Space_id - The address space ID
251 * Handler - Address of the handler
255 * DESCRIPTION: Install a handler for accesses on an Operation Region
257 ******************************************************************************/
260 acpi_remove_address_space_handler (
262 ACPI_ADDRESS_SPACE_TYPE space_id
,
263 ADDRESS_SPACE_HANDLER handler
)
265 ACPI_OPERAND_OBJECT
*obj_desc
;
266 ACPI_OPERAND_OBJECT
*handler_obj
;
267 ACPI_OPERAND_OBJECT
*region_obj
;
268 ACPI_OPERAND_OBJECT
**last_obj_ptr
;
269 ACPI_NAMESPACE_NODE
*node
;
270 ACPI_STATUS status
= AE_OK
;
273 /* Parameter validation */
276 ((!handler
) && (handler
!= ACPI_DEFAULT_HANDLER
))) {
277 return (AE_BAD_PARAMETER
);
280 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
282 /* Convert and validate the device handle */
284 node
= acpi_ns_convert_handle_to_entry (device
);
286 status
= AE_BAD_PARAMETER
;
287 goto unlock_and_exit
;
291 /* Make sure the internal object exists */
293 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
298 status
= AE_NOT_EXIST
;
299 goto unlock_and_exit
;
303 * find the address handler the user requested
306 handler_obj
= obj_desc
->device
.addr_handler
;
307 last_obj_ptr
= &obj_desc
->device
.addr_handler
;
308 while (handler_obj
) {
310 * We have a handler, see if user requested this one
313 if(handler_obj
->addr_handler
.space_id
== space_id
) {
315 * Got it, first dereference this in the Regions
317 region_obj
= handler_obj
->addr_handler
.region_list
;
319 /* Walk the handler's region list */
323 * First disassociate the handler from the region.
325 * NOTE: this doesn't mean that the region goes away
326 * The region is just inaccessible as indicated to
329 acpi_ev_disassociate_region_from_handler(region_obj
, FALSE
);
332 * Walk the list, since we took the first region and it
333 * was removed from the list by the dissassociate call
334 * we just get the first item on the list again
336 region_obj
= handler_obj
->addr_handler
.region_list
;
341 * Remove this Handler object from the list
343 *last_obj_ptr
= handler_obj
->addr_handler
.next
;
346 * Now we can delete the handler object
348 acpi_cm_remove_reference (handler_obj
);
349 acpi_cm_remove_reference (handler_obj
);
351 goto unlock_and_exit
;
355 * Move through the linked list of handlers
357 last_obj_ptr
= &handler_obj
->addr_handler
.next
;
358 handler_obj
= handler_obj
->addr_handler
.next
;
363 * The handler does not exist
365 status
= AE_NOT_EXIST
;
369 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);