1 /******************************************************************************
3 * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
7 *****************************************************************************/
10 * Copyright (C) 2000 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 EVENT_HANDLING
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
))
77 return (AE_BAD_PARAMETER
);
80 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
82 /* Convert and validate the device handle */
84 node
= acpi_ns_convert_handle_to_entry (device
);
86 status
= AE_BAD_PARAMETER
;
91 * This registration is valid for only the types below
92 * and the root. This is where the default handlers
96 if ((node
->type
!= ACPI_TYPE_DEVICE
) &&
97 (node
->type
!= ACPI_TYPE_PROCESSOR
) &&
98 (node
->type
!= ACPI_TYPE_THERMAL
) &&
99 (node
!= acpi_gbl_root_node
))
101 status
= AE_BAD_PARAMETER
;
102 goto unlock_and_exit
;
105 if (handler
== ACPI_DEFAULT_HANDLER
) {
106 flags
= ADDR_HANDLER_DEFAULT_INSTALLED
;
110 case ADDRESS_SPACE_SYSTEM_MEMORY
:
111 handler
= acpi_aml_system_memory_space_handler
;
112 setup
= acpi_ev_system_memory_region_setup
;
115 case ADDRESS_SPACE_SYSTEM_IO
:
116 handler
= acpi_aml_system_io_space_handler
;
117 setup
= acpi_ev_io_space_region_setup
;
120 case ADDRESS_SPACE_PCI_CONFIG
:
121 handler
= acpi_aml_pci_config_space_handler
;
122 setup
= acpi_ev_pci_config_region_setup
;
126 status
= AE_NOT_EXIST
;
127 goto unlock_and_exit
;
133 * If the caller hasn't specified a setup routine, use the default
136 setup
= acpi_ev_default_region_setup
;
140 * Check for an existing internal object
143 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
147 * Make sure the handler is not already installed.
150 /* check the address handler the user requested */
152 handler_obj
= obj_desc
->device
.addr_handler
;
153 while (handler_obj
) {
155 * We have an Address handler, see if user requested this
158 if(handler_obj
->addr_handler
.space_id
== space_id
) {
160 goto unlock_and_exit
;
164 * Move through the linked list of handlers
166 handler_obj
= handler_obj
->addr_handler
.next
;
171 /* Obj_desc does not exist, create one */
173 if (node
->type
== ACPI_TYPE_ANY
) {
174 type
= ACPI_TYPE_DEVICE
;
181 obj_desc
= acpi_cm_create_internal_object (type
);
183 status
= AE_NO_MEMORY
;
184 goto unlock_and_exit
;
187 /* Init new descriptor */
189 obj_desc
->common
.type
= (u8
) type
;
191 /* Attach the new object to the Node */
193 status
= acpi_ns_attach_object (node
, obj_desc
, (u8
) type
);
194 if (ACPI_FAILURE (status
)) {
195 acpi_cm_remove_reference (obj_desc
);
196 goto unlock_and_exit
;
201 * Now we can install the handler
203 * At this point we know that there is no existing handler.
204 * So, we just allocate the object for the handler and link it
207 handler_obj
= acpi_cm_create_internal_object (INTERNAL_TYPE_ADDRESS_HANDLER
);
209 status
= AE_NO_MEMORY
;
210 goto unlock_and_exit
;
213 handler_obj
->addr_handler
.space_id
= (u8
) space_id
;
214 handler_obj
->addr_handler
.hflags
= flags
;
215 handler_obj
->addr_handler
.next
= obj_desc
->device
.addr_handler
;
216 handler_obj
->addr_handler
.region_list
= NULL
;
217 handler_obj
->addr_handler
.node
= node
;
218 handler_obj
->addr_handler
.handler
= handler
;
219 handler_obj
->addr_handler
.context
= context
;
220 handler_obj
->addr_handler
.setup
= setup
;
223 * Now walk the namespace finding all of the regions this
224 * handler will manage.
226 * We start at the device and search the branch toward
227 * the leaf nodes until either the leaf is encountered or
228 * a device is detected that has an address handler of the
231 * In either case we back up and search down the remainder
234 status
= acpi_ns_walk_namespace (ACPI_TYPE_ANY
, device
,
235 ACPI_UINT32_MAX
, NS_WALK_UNLOCK
,
236 acpi_ev_addr_handler_helper
,
240 * Place this handler 1st on the list
243 handler_obj
->common
.reference_count
=
244 (u16
) (handler_obj
->common
.reference_count
+
245 obj_desc
->common
.reference_count
- 1);
246 obj_desc
->device
.addr_handler
= handler_obj
;
250 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
255 /******************************************************************************
257 * FUNCTION: Acpi_remove_address_space_handler
259 * PARAMETERS: Space_id - The address space ID
260 * Handler - Address of the handler
264 * DESCRIPTION: Install a handler for accesses on an Operation Region
266 ******************************************************************************/
269 acpi_remove_address_space_handler (
271 ACPI_ADDRESS_SPACE_TYPE space_id
,
272 ADDRESS_SPACE_HANDLER handler
)
274 ACPI_OPERAND_OBJECT
*obj_desc
;
275 ACPI_OPERAND_OBJECT
*handler_obj
;
276 ACPI_OPERAND_OBJECT
*region_obj
;
277 ACPI_OPERAND_OBJECT
**last_obj_ptr
;
278 ACPI_NAMESPACE_NODE
*node
;
279 ACPI_STATUS status
= AE_OK
;
282 /* Parameter validation */
285 ((!handler
) && (handler
!= ACPI_DEFAULT_HANDLER
)) ||
286 (space_id
> ACPI_MAX_ADDRESS_SPACE
))
288 return (AE_BAD_PARAMETER
);
291 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
293 /* Convert and validate the device handle */
295 node
= acpi_ns_convert_handle_to_entry (device
);
297 status
= AE_BAD_PARAMETER
;
298 goto unlock_and_exit
;
302 /* Make sure the internal object exists */
304 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) node
);
309 status
= AE_NOT_EXIST
;
310 goto unlock_and_exit
;
314 * find the address handler the user requested
317 handler_obj
= obj_desc
->device
.addr_handler
;
318 last_obj_ptr
= &obj_desc
->device
.addr_handler
;
319 while (handler_obj
) {
321 * We have a handler, see if user requested this one
324 if(handler_obj
->addr_handler
.space_id
== space_id
) {
326 * Got it, first dereference this in the Regions
328 region_obj
= handler_obj
->addr_handler
.region_list
;
330 /* Walk the handler's region list */
334 * First disassociate the handler from the region.
336 * NOTE: this doesn't mean that the region goes away
337 * The region is just inaccessible as indicated to
340 acpi_ev_disassociate_region_from_handler(region_obj
);
343 * Walk the list, since we took the first region and it
344 * was removed from the list by the dissassociate call
345 * we just get the first item on the list again
347 region_obj
= handler_obj
->addr_handler
.region_list
;
352 * Remove this Handler object from the list
354 *last_obj_ptr
= handler_obj
->addr_handler
.next
;
357 * Now we can delete the handler object
359 acpi_cm_remove_reference (handler_obj
);
360 acpi_cm_remove_reference (handler_obj
);
362 goto unlock_and_exit
;
366 * Move through the linked list of handlers
368 last_obj_ptr
= &handler_obj
->addr_handler
.next
;
369 handler_obj
= handler_obj
->addr_handler
.next
;
374 * The handler does not exist
376 status
= AE_NOT_EXIST
;
380 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);