1 /******************************************************************************
3 * Module Name: evxface - External interfaces for ACPI events
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2004, R. Byron Moore
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
45 #include <acpi/acpi.h>
46 #include <acpi/acnamesp.h>
47 #include <acpi/acevents.h>
48 #include <acpi/acinterp.h>
50 #define _COMPONENT ACPI_EVENTS
51 ACPI_MODULE_NAME ("evxface")
54 /*******************************************************************************
56 * FUNCTION: acpi_install_fixed_event_handler
58 * PARAMETERS: Event - Event type to enable.
59 * Handler - Pointer to the handler function for the
61 * Context - Value passed to the handler on each GPE
65 * DESCRIPTION: Saves the pointer to the handler function and then enables the
68 ******************************************************************************/
71 acpi_install_fixed_event_handler (
73 acpi_event_handler handler,
79 ACPI_FUNCTION_TRACE ("acpi_install_fixed_event_handler");
82 /* Parameter validation */
84 if (event > ACPI_EVENT_MAX) {
85 return_ACPI_STATUS (AE_BAD_PARAMETER);
88 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
89 if (ACPI_FAILURE (status)) {
90 return_ACPI_STATUS (status);
93 /* Don't allow two handlers. */
95 if (NULL != acpi_gbl_fixed_event_handlers[event].handler) {
96 status = AE_ALREADY_EXISTS;
100 /* Install the handler before enabling the event */
102 acpi_gbl_fixed_event_handlers[event].handler = handler;
103 acpi_gbl_fixed_event_handlers[event].context = context;
105 status = acpi_enable_event (event, 0);
106 if (ACPI_FAILURE (status)) {
107 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
109 /* Remove the handler */
111 acpi_gbl_fixed_event_handlers[event].handler = NULL;
112 acpi_gbl_fixed_event_handlers[event].context = NULL;
115 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
116 "Enabled fixed event %X, Handler=%p\n", event, handler));
121 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
122 return_ACPI_STATUS (status);
126 /*******************************************************************************
128 * FUNCTION: acpi_remove_fixed_event_handler
130 * PARAMETERS: Event - Event type to disable.
131 * Handler - Address of the handler
135 * DESCRIPTION: Disables the event and unregisters the event handler.
137 ******************************************************************************/
140 acpi_remove_fixed_event_handler (
142 acpi_event_handler handler)
144 acpi_status status = AE_OK;
147 ACPI_FUNCTION_TRACE ("acpi_remove_fixed_event_handler");
150 /* Parameter validation */
152 if (event > ACPI_EVENT_MAX) {
153 return_ACPI_STATUS (AE_BAD_PARAMETER);
156 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
157 if (ACPI_FAILURE (status)) {
158 return_ACPI_STATUS (status);
161 /* Disable the event before removing the handler */
163 status = acpi_disable_event (event, 0);
165 /* Always Remove the handler */
167 acpi_gbl_fixed_event_handlers[event].handler = NULL;
168 acpi_gbl_fixed_event_handlers[event].context = NULL;
170 if (ACPI_FAILURE (status)) {
171 ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
172 "Could not write to fixed event enable register.\n"));
175 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", event));
178 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
179 return_ACPI_STATUS (status);
183 /*******************************************************************************
185 * FUNCTION: acpi_install_notify_handler
187 * PARAMETERS: Device - The device for which notifies will be handled
188 * handler_type - The type of handler:
189 * ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
190 * ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
191 * Handler - Address of the handler
192 * Context - Value passed to the handler on each GPE
196 * DESCRIPTION: Install a handler for notifies on an ACPI device
198 ******************************************************************************/
201 acpi_install_notify_handler (
204 acpi_notify_handler handler,
207 union acpi_operand_object *obj_desc;
208 union acpi_operand_object *notify_obj;
209 struct acpi_namespace_node *node;
213 ACPI_FUNCTION_TRACE ("acpi_install_notify_handler");
216 /* Parameter validation */
220 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
221 return_ACPI_STATUS (AE_BAD_PARAMETER);
224 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
225 if (ACPI_FAILURE (status)) {
226 return_ACPI_STATUS (status);
229 /* Convert and validate the device handle */
231 node = acpi_ns_map_handle_to_node (device);
233 status = AE_BAD_PARAMETER;
234 goto unlock_and_exit;
239 * Registering a notify handler on the root object indicates that the
240 * caller wishes to receive notifications for all objects. Note that
241 * only one <external> global handler can be regsitered (per notify type).
243 if (device == ACPI_ROOT_OBJECT) {
244 /* Make sure the handler is not already installed */
246 if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
247 acpi_gbl_system_notify.handler) ||
248 ((handler_type == ACPI_DEVICE_NOTIFY) &&
249 acpi_gbl_device_notify.handler)) {
250 status = AE_ALREADY_EXISTS;
251 goto unlock_and_exit;
254 if (handler_type == ACPI_SYSTEM_NOTIFY) {
255 acpi_gbl_system_notify.node = node;
256 acpi_gbl_system_notify.handler = handler;
257 acpi_gbl_system_notify.context = context;
259 else /* ACPI_DEVICE_NOTIFY */ {
260 acpi_gbl_device_notify.node = node;
261 acpi_gbl_device_notify.handler = handler;
262 acpi_gbl_device_notify.context = context;
265 /* Global notify handler installed */
270 * Caller will only receive notifications specific to the target object.
271 * Note that only certain object types can receive notifications.
274 /* Notifies allowed on this object? */
276 if (!acpi_ev_is_notify_object (node)) {
278 goto unlock_and_exit;
281 /* Check for an existing internal object */
283 obj_desc = acpi_ns_get_attached_object (node);
285 /* Object exists - make sure there's no handler */
287 if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
288 obj_desc->common_notify.system_notify) ||
289 ((handler_type == ACPI_DEVICE_NOTIFY) &&
290 obj_desc->common_notify.device_notify)) {
291 status = AE_ALREADY_EXISTS;
292 goto unlock_and_exit;
296 /* Create a new object */
298 obj_desc = acpi_ut_create_internal_object (node->type);
300 status = AE_NO_MEMORY;
301 goto unlock_and_exit;
304 /* Attach new object to the Node */
306 status = acpi_ns_attach_object (device, obj_desc, node->type);
308 /* Remove local reference to the object */
310 acpi_ut_remove_reference (obj_desc);
312 if (ACPI_FAILURE (status)) {
313 goto unlock_and_exit;
317 /* Install the handler */
319 notify_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_NOTIFY);
321 status = AE_NO_MEMORY;
322 goto unlock_and_exit;
325 notify_obj->notify.node = node;
326 notify_obj->notify.handler = handler;
327 notify_obj->notify.context = context;
329 if (handler_type == ACPI_SYSTEM_NOTIFY) {
330 obj_desc->common_notify.system_notify = notify_obj;
332 else /* ACPI_DEVICE_NOTIFY */ {
333 obj_desc->common_notify.device_notify = notify_obj;
339 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
340 return_ACPI_STATUS (status);
344 /*******************************************************************************
346 * FUNCTION: acpi_remove_notify_handler
348 * PARAMETERS: Device - The device for which notifies will be handled
349 * handler_type - The type of handler:
350 * ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
351 * ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
352 * Handler - Address of the handler
355 * DESCRIPTION: Remove a handler for notifies on an ACPI device
357 ******************************************************************************/
360 acpi_remove_notify_handler (
363 acpi_notify_handler handler)
365 union acpi_operand_object *notify_obj;
366 union acpi_operand_object *obj_desc;
367 struct acpi_namespace_node *node;
371 ACPI_FUNCTION_TRACE ("acpi_remove_notify_handler");
374 /* Parameter validation */
378 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
379 return_ACPI_STATUS (AE_BAD_PARAMETER);
382 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
383 if (ACPI_FAILURE (status)) {
384 return_ACPI_STATUS (status);
387 /* Convert and validate the device handle */
389 node = acpi_ns_map_handle_to_node (device);
391 status = AE_BAD_PARAMETER;
392 goto unlock_and_exit;
398 if (device == ACPI_ROOT_OBJECT) {
399 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n"));
401 if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
402 !acpi_gbl_system_notify.handler) ||
403 ((handler_type == ACPI_DEVICE_NOTIFY) &&
404 !acpi_gbl_device_notify.handler)) {
405 status = AE_NOT_EXIST;
406 goto unlock_and_exit;
409 /* Make sure all deferred tasks are completed */
411 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
412 acpi_os_wait_events_complete(NULL);
413 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
414 if (ACPI_FAILURE (status)) {
415 return_ACPI_STATUS (status);
418 if (handler_type == ACPI_SYSTEM_NOTIFY) {
419 acpi_gbl_system_notify.node = NULL;
420 acpi_gbl_system_notify.handler = NULL;
421 acpi_gbl_system_notify.context = NULL;
424 acpi_gbl_device_notify.node = NULL;
425 acpi_gbl_device_notify.handler = NULL;
426 acpi_gbl_device_notify.context = NULL;
434 /* Notifies allowed on this object? */
436 if (!acpi_ev_is_notify_object (node)) {
438 goto unlock_and_exit;
441 /* Check for an existing internal object */
443 obj_desc = acpi_ns_get_attached_object (node);
445 status = AE_NOT_EXIST;
446 goto unlock_and_exit;
449 /* Object exists - make sure there's an existing handler */
451 if (handler_type == ACPI_SYSTEM_NOTIFY) {
452 notify_obj = obj_desc->common_notify.system_notify;
455 notify_obj = obj_desc->common_notify.device_notify;
459 (notify_obj->notify.handler != handler)) {
460 status = AE_BAD_PARAMETER;
461 goto unlock_and_exit;
464 /* Make sure all deferred tasks are completed */
466 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
467 acpi_os_wait_events_complete(NULL);
468 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
469 if (ACPI_FAILURE (status)) {
470 return_ACPI_STATUS (status);
473 /* Remove the handler */
475 if (handler_type == ACPI_SYSTEM_NOTIFY) {
476 obj_desc->common_notify.system_notify = NULL;
479 obj_desc->common_notify.device_notify = NULL;
482 acpi_ut_remove_reference (notify_obj);
487 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
488 return_ACPI_STATUS (status);
492 /*******************************************************************************
494 * FUNCTION: acpi_install_gpe_handler
496 * PARAMETERS: gpe_number - The GPE number within the GPE block
497 * gpe_block - GPE block (NULL == FADT GPEs)
498 * Type - Whether this GPE should be treated as an
499 * edge- or level-triggered interrupt.
500 * Handler - Address of the handler
501 * Context - Value passed to the handler on each GPE
505 * DESCRIPTION: Install a handler for a General Purpose Event.
507 ******************************************************************************/
510 acpi_install_gpe_handler (
511 acpi_handle gpe_device,
514 acpi_gpe_handler handler,
518 struct acpi_gpe_event_info *gpe_event_info;
521 ACPI_FUNCTION_TRACE ("acpi_install_gpe_handler");
524 /* Parameter validation */
527 return_ACPI_STATUS (AE_BAD_PARAMETER);
530 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
531 if (ACPI_FAILURE (status)) {
532 return_ACPI_STATUS (status);
535 /* Ensure that we have a valid GPE number */
537 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
538 if (!gpe_event_info) {
539 status = AE_BAD_PARAMETER;
540 goto unlock_and_exit;
543 /* Make sure that there isn't a handler there already */
545 if (gpe_event_info->handler) {
546 status = AE_ALREADY_EXISTS;
547 goto unlock_and_exit;
550 /* Install the handler */
552 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
553 gpe_event_info->handler = handler;
554 gpe_event_info->context = context;
555 gpe_event_info->flags = (u8) type;
556 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
558 /* Clear the GPE (of stale events), the enable it */
560 status = acpi_hw_clear_gpe (gpe_event_info);
561 if (ACPI_FAILURE (status)) {
562 goto unlock_and_exit;
565 status = acpi_hw_enable_gpe (gpe_event_info);
569 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
570 return_ACPI_STATUS (status);
574 /*******************************************************************************
576 * FUNCTION: acpi_remove_gpe_handler
578 * PARAMETERS: gpe_number - The event to remove a handler
579 * gpe_block - GPE block (NULL == FADT GPEs)
580 * Handler - Address of the handler
584 * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
586 ******************************************************************************/
589 acpi_remove_gpe_handler (
590 acpi_handle gpe_device,
592 acpi_gpe_handler handler)
595 struct acpi_gpe_event_info *gpe_event_info;
598 ACPI_FUNCTION_TRACE ("acpi_remove_gpe_handler");
601 /* Parameter validation */
604 return_ACPI_STATUS (AE_BAD_PARAMETER);
607 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
608 if (ACPI_FAILURE (status)) {
609 return_ACPI_STATUS (status);
612 /* Ensure that we have a valid GPE number */
614 gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
615 if (!gpe_event_info) {
616 status = AE_BAD_PARAMETER;
617 goto unlock_and_exit;
620 /* Disable the GPE before removing the handler */
622 status = acpi_hw_disable_gpe (gpe_event_info);
623 if (ACPI_FAILURE (status)) {
624 goto unlock_and_exit;
627 /* Make sure that the installed handler is the same */
629 if (gpe_event_info->handler != handler) {
630 (void) acpi_hw_enable_gpe (gpe_event_info);
631 status = AE_BAD_PARAMETER;
632 goto unlock_and_exit;
635 /* Make sure all deferred tasks are completed */
637 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
638 acpi_os_wait_events_complete(NULL);
639 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
640 if (ACPI_FAILURE (status)) {
641 return_ACPI_STATUS (status);
644 /* Remove the handler */
646 acpi_os_acquire_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
647 gpe_event_info->handler = NULL;
648 gpe_event_info->context = NULL;
649 acpi_os_release_lock (acpi_gbl_gpe_lock, ACPI_NOT_ISR);
653 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
654 return_ACPI_STATUS (status);
658 /*******************************************************************************
660 * FUNCTION: acpi_acquire_global_lock
662 * PARAMETERS: Timeout - How long the caller is willing to wait
663 * out_handle - A handle to the lock if acquired
667 * DESCRIPTION: Acquire the ACPI Global Lock
669 ******************************************************************************/
672 acpi_acquire_global_lock (
680 return (AE_BAD_PARAMETER);
683 status = acpi_ex_enter_interpreter ();
684 if (ACPI_FAILURE (status)) {
688 status = acpi_ev_acquire_global_lock (timeout);
689 acpi_ex_exit_interpreter ();
691 if (ACPI_SUCCESS (status)) {
692 acpi_gbl_global_lock_handle++;
693 *handle = acpi_gbl_global_lock_handle;
700 /*******************************************************************************
702 * FUNCTION: acpi_release_global_lock
704 * PARAMETERS: Handle - Returned from acpi_acquire_global_lock
708 * DESCRIPTION: Release the ACPI Global Lock
710 ******************************************************************************/
713 acpi_release_global_lock (
719 if (handle != acpi_gbl_global_lock_handle) {
720 return (AE_NOT_ACQUIRED);
723 status = acpi_ev_release_global_lock ();