1 /******************************************************************************
3 * Module Name: evxface - External interfaces for ACPI events
6 *****************************************************************************/
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
34 #define _COMPONENT EVENT_HANDLING
35 MODULE_NAME ("evxface")
38 /******************************************************************************
40 * FUNCTION: Acpi_install_fixed_event_handler
42 * PARAMETERS: Event - Event type to enable.
43 * Handler - Pointer to the handler function for the
45 * Context - Value passed to the handler on each GPE
49 * DESCRIPTION: Saves the pointer to the handler function and then enables the
52 ******************************************************************************/
55 acpi_install_fixed_event_handler (
57 FIXED_EVENT_HANDLER handler
,
60 ACPI_STATUS status
= AE_OK
;
63 /* Sanity check the parameters. */
65 if (event
>= NUM_FIXED_EVENTS
) {
66 return (AE_BAD_PARAMETER
);
69 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
71 /* Don't allow two handlers. */
73 if (NULL
!= acpi_gbl_fixed_event_handlers
[event
].handler
) {
79 /* Install the handler before enabling the event - just in case... */
81 acpi_gbl_fixed_event_handlers
[event
].handler
= handler
;
82 acpi_gbl_fixed_event_handlers
[event
].context
= context
;
84 status
= acpi_enable_event(event
, ACPI_EVENT_FIXED
);
86 if (!ACPI_SUCCESS(status
)) {
87 /* Remove the handler */
89 acpi_gbl_fixed_event_handlers
[event
].handler
= NULL
;
90 acpi_gbl_fixed_event_handlers
[event
].context
= NULL
;
98 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
103 /******************************************************************************
105 * FUNCTION: Acpi_remove_fixed_event_handler
107 * PARAMETERS: Event - Event type to disable.
108 * Handler - Address of the handler
112 * DESCRIPTION: Disables the event and unregisters the event handler.
114 ******************************************************************************/
117 acpi_remove_fixed_event_handler (
119 FIXED_EVENT_HANDLER handler
)
121 ACPI_STATUS status
= AE_OK
;
124 /* Sanity check the parameters. */
126 if (event
>= NUM_FIXED_EVENTS
) {
127 return (AE_BAD_PARAMETER
);
130 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
132 /* Disable the event before removing the handler - just in case... */
134 status
= acpi_disable_event(event
, ACPI_EVENT_FIXED
);
136 if (!ACPI_SUCCESS(status
)) {
138 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
142 /* Remove the handler */
144 acpi_gbl_fixed_event_handlers
[event
].handler
= NULL
;
145 acpi_gbl_fixed_event_handlers
[event
].context
= NULL
;
147 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
152 /******************************************************************************
154 * FUNCTION: Acpi_install_notify_handler
156 * PARAMETERS: Device - The device for which notifies will be handled
157 * Handler_type - The type of handler:
158 * ACPI_SYSTEM_NOTIFY: System_handler (00-7f)
159 * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff)
160 * Handler - Address of the handler
161 * Context - Value passed to the handler on each GPE
165 * DESCRIPTION: Install a handler for notifies on an ACPI device
167 ******************************************************************************/
170 acpi_install_notify_handler (
173 NOTIFY_HANDLER handler
,
176 ACPI_OPERAND_OBJECT
*obj_desc
;
177 ACPI_OPERAND_OBJECT
*notify_obj
;
178 ACPI_NAMESPACE_NODE
*device_node
;
179 ACPI_STATUS status
= AE_OK
;
182 /* Parameter validation */
185 (handler_type
> ACPI_MAX_NOTIFY_HANDLER_TYPE
))
187 return (AE_BAD_PARAMETER
);
190 /* Convert and validate the device handle */
192 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
194 device_node
= acpi_ns_convert_handle_to_entry (device
);
196 status
= AE_BAD_PARAMETER
;
197 goto unlock_and_exit
;
202 * Support for global notify handlers. These handlers are invoked for
203 * every notifiy of the type specifiec
206 if (device
== ACPI_ROOT_OBJECT
) {
208 * Make sure the handler is not already installed.
211 if (((handler_type
== ACPI_SYSTEM_NOTIFY
) &&
212 acpi_gbl_sys_notify
.handler
) ||
213 ((handler_type
== ACPI_DEVICE_NOTIFY
) &&
214 acpi_gbl_drv_notify
.handler
))
217 goto unlock_and_exit
;
220 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
221 acpi_gbl_sys_notify
.node
= device_node
;
222 acpi_gbl_sys_notify
.handler
= handler
;
223 acpi_gbl_sys_notify
.context
= context
;
227 acpi_gbl_drv_notify
.node
= device_node
;
228 acpi_gbl_drv_notify
.handler
= handler
;
229 acpi_gbl_drv_notify
.context
= context
;
233 /* Global notify handler installed */
235 goto unlock_and_exit
;
240 * These are the ONLY objects that can receive ACPI notifications
243 if ((device_node
->type
!= ACPI_TYPE_DEVICE
) &&
244 (device_node
->type
!= ACPI_TYPE_PROCESSOR
) &&
245 (device_node
->type
!= ACPI_TYPE_POWER
) &&
246 (device_node
->type
!= ACPI_TYPE_THERMAL
))
248 status
= AE_BAD_PARAMETER
;
249 goto unlock_and_exit
;
252 /* Check for an existing internal object */
254 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) device_node
);
258 * Make sure the handler is not already installed.
261 if (((handler_type
== ACPI_SYSTEM_NOTIFY
) &&
262 obj_desc
->device
.sys_handler
) ||
263 ((handler_type
== ACPI_DEVICE_NOTIFY
) &&
264 obj_desc
->device
.drv_handler
))
267 goto unlock_and_exit
;
272 /* Create a new object */
274 obj_desc
= acpi_cm_create_internal_object (device_node
->type
);
276 status
= AE_NO_MEMORY
;
277 goto unlock_and_exit
;
280 /* Attach new object to the Node */
282 status
= acpi_ns_attach_object (device
, obj_desc
, (u8
) device_node
->type
);
284 if (ACPI_FAILURE (status
)) {
285 goto unlock_and_exit
;
291 * If we get here, we know that there is no handler installed
294 notify_obj
= acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY
);
296 status
= AE_NO_MEMORY
;
297 goto unlock_and_exit
;
300 notify_obj
->notify_handler
.node
= device_node
;
301 notify_obj
->notify_handler
.handler
= handler
;
302 notify_obj
->notify_handler
.context
= context
;
305 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
306 obj_desc
->device
.sys_handler
= notify_obj
;
310 obj_desc
->device
.drv_handler
= notify_obj
;
315 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
320 /*****************************************************************************
322 * FUNCTION: Acpi_remove_notify_handler
324 * PARAMETERS: Device - The device for which notifies will be handled
325 * Handler_type - The type of handler:
326 * ACPI_SYSTEM_NOTIFY: System_handler (00-7f)
327 * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff)
328 * Handler - Address of the handler
331 * DESCRIPTION: Remove a handler for notifies on an ACPI device
333 ******************************************************************************/
336 acpi_remove_notify_handler (
339 NOTIFY_HANDLER handler
)
341 ACPI_OPERAND_OBJECT
*notify_obj
;
342 ACPI_OPERAND_OBJECT
*obj_desc
;
343 ACPI_NAMESPACE_NODE
*device_node
;
344 ACPI_STATUS status
= AE_OK
;
347 /* Parameter validation */
350 (handler_type
> ACPI_MAX_NOTIFY_HANDLER_TYPE
))
352 return (AE_BAD_PARAMETER
);
355 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
357 /* Convert and validate the device handle */
359 device_node
= acpi_ns_convert_handle_to_entry (device
);
361 status
= AE_BAD_PARAMETER
;
362 goto unlock_and_exit
;
366 * These are the ONLY objects that can receive ACPI notifications
369 if ((device_node
->type
!= ACPI_TYPE_DEVICE
) &&
370 (device_node
->type
!= ACPI_TYPE_PROCESSOR
) &&
371 (device_node
->type
!= ACPI_TYPE_POWER
) &&
372 (device_node
->type
!= ACPI_TYPE_THERMAL
))
374 status
= AE_BAD_PARAMETER
;
375 goto unlock_and_exit
;
378 /* Check for an existing internal object */
380 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) device_node
);
382 status
= AE_NOT_EXIST
;
383 goto unlock_and_exit
;
389 * Make sure the handler is installed.
392 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
393 notify_obj
= obj_desc
->device
.sys_handler
;
396 notify_obj
= obj_desc
->device
.drv_handler
;
400 (notify_obj
->notify_handler
.handler
!= handler
))
402 status
= AE_BAD_PARAMETER
;
403 goto unlock_and_exit
;
407 * Now we can remove the handler
409 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
410 obj_desc
->device
.sys_handler
= NULL
;
413 obj_desc
->device
.drv_handler
= NULL
;
416 acpi_cm_remove_reference (notify_obj
);
419 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
423 /******************************************************************************
425 * FUNCTION: Acpi_install_gpe_handler
427 * PARAMETERS: Gpe_number - The GPE number. The numbering scheme is
428 * bank 0 first, then bank 1.
429 * Type - Whether this GPE should be treated as an
430 * edge- or level-triggered interrupt.
431 * Handler - Address of the handler
432 * Context - Value passed to the handler on each GPE
436 * DESCRIPTION: Install a handler for a General Purpose Event.
438 ******************************************************************************/
441 acpi_install_gpe_handler (
447 ACPI_STATUS status
= AE_OK
;
449 /* Parameter validation */
451 if (!handler
|| (gpe_number
> NUM_GPE
)) {
452 return (AE_BAD_PARAMETER
);
455 /* Ensure that we have a valid GPE number */
457 if (acpi_gbl_gpe_valid
[gpe_number
] == ACPI_GPE_INVALID
) {
458 return (AE_BAD_PARAMETER
);
461 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
463 /* Make sure that there isn't a handler there already */
465 if (acpi_gbl_gpe_info
[gpe_number
].handler
) {
470 /* Install the handler */
472 acpi_gbl_gpe_info
[gpe_number
].handler
= handler
;
473 acpi_gbl_gpe_info
[gpe_number
].context
= context
;
474 acpi_gbl_gpe_info
[gpe_number
].type
= (u8
) type
;
476 /* Clear the GPE (of stale events), the enable it */
478 acpi_hw_clear_gpe (gpe_number
);
479 acpi_hw_enable_gpe (gpe_number
);
482 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
487 /******************************************************************************
489 * FUNCTION: Acpi_remove_gpe_handler
491 * PARAMETERS: Gpe_number - The event to remove a handler
492 * Handler - Address of the handler
496 * DESCRIPTION: Remove a handler for a General Purpose Acpi_event.
498 ******************************************************************************/
501 acpi_remove_gpe_handler (
505 ACPI_STATUS status
= AE_OK
;
508 /* Parameter validation */
510 if (!handler
|| (gpe_number
> NUM_GPE
)) {
511 return (AE_BAD_PARAMETER
);
514 /* Ensure that we have a valid GPE number */
516 if (acpi_gbl_gpe_valid
[gpe_number
] == ACPI_GPE_INVALID
) {
517 return (AE_BAD_PARAMETER
);
520 /* Disable the GPE before removing the handler */
522 acpi_hw_disable_gpe (gpe_number
);
524 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
526 /* Make sure that the installed handler is the same */
528 if (acpi_gbl_gpe_info
[gpe_number
].handler
!= handler
) {
529 acpi_hw_enable_gpe (gpe_number
);
530 status
= AE_BAD_PARAMETER
;
534 /* Remove the handler */
536 acpi_gbl_gpe_info
[gpe_number
].handler
= NULL
;
537 acpi_gbl_gpe_info
[gpe_number
].context
= NULL
;
540 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
545 /******************************************************************************
547 * FUNCTION: Acpi_acquire_global_lock
549 * PARAMETERS: Timeout - How long the caller is willing to wait
550 * Out_handle - A handle to the lock if acquired
554 * DESCRIPTION: Acquire the ACPI Global Lock
556 ******************************************************************************/
558 acpi_acquire_global_lock (
564 acpi_aml_enter_interpreter ();
567 * TBD: [Restructure] add timeout param to internal interface, and
568 * perhaps INTERPRETER_LOCKED
571 status
= acpi_ev_acquire_global_lock ();
572 acpi_aml_exit_interpreter ();
578 /******************************************************************************
580 * FUNCTION: Acpi_release_global_lock
582 * PARAMETERS: Handle - Returned from Acpi_acquire_global_lock
586 * DESCRIPTION: Release the ACPI Global Lock
588 ******************************************************************************/
591 acpi_release_global_lock (
594 acpi_ev_release_global_lock ();