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 return (AE_BAD_PARAMETER
);
78 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
80 /* Convert and validate the device handle */
82 node
= acpi_ns_convert_handle_to_entry (device
);
84 status
= AE_BAD_PARAMETER
;
89 * This registration is valid for only the types below
90 * and the root. This is where the default handlers
94 if ((node
->type
!= ACPI_TYPE_DEVICE
) &&
95 (node
->type
!= ACPI_TYPE_PROCESSOR
) &&
96 (node
->type
!= ACPI_TYPE_THERMAL
) &&
97 (node
!= acpi_gbl_root_node
)) {
98 status
= AE_BAD_PARAMETER
;
102 if (handler
== ACPI_DEFAULT_HANDLER
) {
103 flags
= ADDR_HANDLER_DEFAULT_INSTALLED
;
106 case ADDRESS_SPACE_SYSTEM_MEMORY
:
107 handler
= acpi_aml_system_memory_space_handler
;
108 setup
= acpi_ev_system_memory_region_setup
;
111 case ADDRESS_SPACE_SYSTEM_IO
:
112 handler
= acpi_aml_system_io_space_handler
;
113 setup
= acpi_ev_io_space_region_setup
;
116 case ADDRESS_SPACE_PCI_CONFIG
:
117 handler
= acpi_aml_pci_config_space_handler
;
118 setup
= acpi_ev_pci_config_region_setup
;
122 status
= AE_NOT_EXIST
;
123 goto unlock_and_exit
;
129 * If the caller hasn't specified a setup routine, use the default
132 setup
= acpi_ev_default_region_setup
;
136 * Check for an existing internal object
139 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
143 * Make sure the handler is not already installed.
146 /* check the address handler the user requested */
148 handler_obj
= obj_desc
->device
.addr_handler
;
149 while (handler_obj
) {
151 * We have an Address handler, see if user requested this
154 if(handler_obj
->addr_handler
.space_id
== space_id
) {
156 goto unlock_and_exit
;
160 * Move through the linked list of handlers
162 handler_obj
= handler_obj
->addr_handler
.next
;
167 /* Obj_desc does not exist, create one */
169 if (node
->type
== ACPI_TYPE_ANY
) {
170 type
= ACPI_TYPE_DEVICE
;
177 obj_desc
= acpi_cm_create_internal_object (type
);
179 status
= AE_NO_MEMORY
;
180 goto unlock_and_exit
;
183 /* Init new descriptor */
185 obj_desc
->common
.type
= (u8
) type
;
187 /* Attach the new object to the Node */
189 status
= acpi_ns_attach_object (node
, obj_desc
, (u8
) type
);
190 if (ACPI_FAILURE (status
)) {
191 acpi_cm_remove_reference (obj_desc
);
192 goto unlock_and_exit
;
197 * Now we can install the handler
199 * At this point we know that there is no existing handler.
200 * So, we just allocate the object for the handler and link it
203 handler_obj
= acpi_cm_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER
);
205 status
= AE_NO_MEMORY
;
206 goto unlock_and_exit
;
209 handler_obj
->addr_handler
.space_id
= (u8
) space_id
;
210 handler_obj
->addr_handler
.hflags
= flags
;
211 handler_obj
->addr_handler
.next
= obj_desc
->device
.addr_handler
;
212 handler_obj
->addr_handler
.region_list
= NULL
;
213 handler_obj
->addr_handler
.node
= node
;
214 handler_obj
->addr_handler
.handler
= handler
;
215 handler_obj
->addr_handler
.context
= context
;
216 handler_obj
->addr_handler
.setup
= setup
;
219 * Now walk the namespace finding all of the regions this
220 * handler will manage.
222 * We start at the device and search the branch toward
223 * the leaf nodes until either the leaf is encountered or
224 * a device is detected that has an address handler of the
227 * In either case we back up and search down the remainder
230 status
= acpi_ns_walk_namespace (ACPI_TYPE_ANY
, device
,
231 ACPI_UINT32_MAX
, NS_WALK_UNLOCK
,
232 acpi_ev_addr_handler_helper
,
236 * Place this handler 1st on the list
239 handler_obj
->common
.reference_count
=
240 (u16
) (handler_obj
->common
.reference_count
+
241 obj_desc
->common
.reference_count
- 1);
242 obj_desc
->device
.addr_handler
= handler_obj
;
246 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
251 /******************************************************************************
253 * FUNCTION: Acpi_remove_address_space_handler
255 * PARAMETERS: Space_id - The address space ID
256 * Handler - Address of the handler
260 * DESCRIPTION: Install a handler for accesses on an Operation Region
262 ******************************************************************************/
265 acpi_remove_address_space_handler (
267 ACPI_ADDRESS_SPACE_TYPE space_id
,
268 ADDRESS_SPACE_HANDLER handler
)
270 ACPI_OPERAND_OBJECT
*obj_desc
;
271 ACPI_OPERAND_OBJECT
*handler_obj
;
272 ACPI_OPERAND_OBJECT
*region_obj
;
273 ACPI_OPERAND_OBJECT
**last_obj_ptr
;
274 ACPI_NAMESPACE_NODE
*node
;
275 ACPI_STATUS status
= AE_OK
;
278 /* Parameter validation */
281 ((!handler
) && (handler
!= ACPI_DEFAULT_HANDLER
))) {
282 return (AE_BAD_PARAMETER
);
285 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
287 /* Convert and validate the device handle */
289 node
= acpi_ns_convert_handle_to_entry (device
);
291 status
= AE_BAD_PARAMETER
;
292 goto unlock_and_exit
;
296 /* Make sure the internal object exists */
298 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
303 status
= AE_NOT_EXIST
;
304 goto unlock_and_exit
;
308 * find the address handler the user requested
311 handler_obj
= obj_desc
->device
.addr_handler
;
312 last_obj_ptr
= &obj_desc
->device
.addr_handler
;
313 while (handler_obj
) {
315 * We have a handler, see if user requested this one
318 if(handler_obj
->addr_handler
.space_id
== space_id
) {
320 * Got it, first dereference this in the Regions
322 region_obj
= handler_obj
->addr_handler
.region_list
;
324 /* Walk the handler's region list */
328 * First disassociate the handler from the region.
330 * NOTE: this doesn't mean that the region goes away
331 * The region is just inaccessible as indicated to
334 acpi_ev_disassociate_region_from_handler(region_obj
, FALSE
);
337 * Walk the list, since we took the first region and it
338 * was removed from the list by the dissassociate call
339 * we just get the first item on the list again
341 region_obj
= handler_obj
->addr_handler
.region_list
;
346 * Remove this Handler object from the list
348 *last_obj_ptr
= handler_obj
->addr_handler
.next
;
351 * Now we can delete the handler object
353 acpi_cm_remove_reference (handler_obj
);
354 acpi_cm_remove_reference (handler_obj
);
356 goto unlock_and_exit
;
360 * Move through the linked list of handlers
362 last_obj_ptr
= &handler_obj
->addr_handler
.next
;
363 handler_obj
= handler_obj
->addr_handler
.next
;
368 * The handler does not exist
370 status
= AE_NOT_EXIST
;
374 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);