1 /******************************************************************************
3 * Module Name: evxface - External interfaces for ACPI events
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 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
29 #define _COMPONENT ACPI_EVENTS
30 MODULE_NAME ("evxface")
33 /******************************************************************************
35 * FUNCTION: Acpi_install_fixed_event_handler
37 * PARAMETERS: Event - Event type to enable.
38 * Handler - Pointer to the handler function for the
40 * Context - Value passed to the handler on each GPE
44 * DESCRIPTION: Saves the pointer to the handler function and then enables the
47 ******************************************************************************/
50 acpi_install_fixed_event_handler (
52 FIXED_EVENT_HANDLER handler
,
58 /* Parameter validation */
60 if (event
>= NUM_FIXED_EVENTS
) {
61 return (AE_BAD_PARAMETER
);
64 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
66 /* Don't allow two handlers. */
68 if (NULL
!= acpi_gbl_fixed_event_handlers
[event
].handler
) {
74 /* Install the handler before enabling the event - just in case... */
76 acpi_gbl_fixed_event_handlers
[event
].handler
= handler
;
77 acpi_gbl_fixed_event_handlers
[event
].context
= context
;
79 status
= acpi_enable_event (event
, ACPI_EVENT_FIXED
);
80 if (!ACPI_SUCCESS (status
)) {
81 /* Remove the handler */
83 acpi_gbl_fixed_event_handlers
[event
].handler
= NULL
;
84 acpi_gbl_fixed_event_handlers
[event
].context
= NULL
;
90 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
95 /******************************************************************************
97 * FUNCTION: Acpi_remove_fixed_event_handler
99 * PARAMETERS: Event - Event type to disable.
100 * Handler - Address of the handler
104 * DESCRIPTION: Disables the event and unregisters the event handler.
106 ******************************************************************************/
109 acpi_remove_fixed_event_handler (
111 FIXED_EVENT_HANDLER handler
)
113 ACPI_STATUS status
= AE_OK
;
116 /* Parameter validation */
118 if (event
>= NUM_FIXED_EVENTS
) {
119 return (AE_BAD_PARAMETER
);
122 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
124 /* Disable the event before removing the handler - just in case... */
126 status
= acpi_disable_event(event
, ACPI_EVENT_FIXED
);
128 /* Always Remove the handler */
130 acpi_gbl_fixed_event_handlers
[event
].handler
= NULL
;
131 acpi_gbl_fixed_event_handlers
[event
].context
= NULL
;
136 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
141 /******************************************************************************
143 * FUNCTION: Acpi_install_notify_handler
145 * PARAMETERS: Device - The device for which notifies will be handled
146 * Handler_type - The type of handler:
147 * ACPI_SYSTEM_NOTIFY: System_handler (00-7f)
148 * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff)
149 * Handler - Address of the handler
150 * Context - Value passed to the handler on each GPE
154 * DESCRIPTION: Install a handler for notifies on an ACPI device
156 ******************************************************************************/
159 acpi_install_notify_handler (
162 NOTIFY_HANDLER handler
,
165 ACPI_OPERAND_OBJECT
*obj_desc
;
166 ACPI_OPERAND_OBJECT
*notify_obj
;
167 ACPI_NAMESPACE_NODE
*device_node
;
168 ACPI_STATUS status
= AE_OK
;
171 /* Parameter validation */
174 (handler_type
> ACPI_MAX_NOTIFY_HANDLER_TYPE
)) {
175 return (AE_BAD_PARAMETER
);
178 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
180 /* Convert and validate the device handle */
182 device_node
= acpi_ns_convert_handle_to_entry (device
);
184 status
= AE_BAD_PARAMETER
;
185 goto unlock_and_exit
;
191 * Registering a notify handler on the root object indicates that the
192 * caller wishes to receive notifications for all objects. Note that
193 * only one <external> global handler can be regsitered (per notify type).
195 if (device
== ACPI_ROOT_OBJECT
) {
196 /* Make sure the handler is not already installed */
198 if (((handler_type
== ACPI_SYSTEM_NOTIFY
) &&
199 acpi_gbl_sys_notify
.handler
) ||
200 ((handler_type
== ACPI_DEVICE_NOTIFY
) &&
201 acpi_gbl_drv_notify
.handler
)) {
203 goto unlock_and_exit
;
206 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
207 acpi_gbl_sys_notify
.node
= device_node
;
208 acpi_gbl_sys_notify
.handler
= handler
;
209 acpi_gbl_sys_notify
.context
= context
;
211 else /* ACPI_DEVICE_NOTIFY */ {
212 acpi_gbl_drv_notify
.node
= device_node
;
213 acpi_gbl_drv_notify
.handler
= handler
;
214 acpi_gbl_drv_notify
.context
= context
;
217 /* Global notify handler installed */
223 * Caller will only receive notifications specific to the target object.
224 * Note that only certain object types can receive notifications.
228 * These are the ONLY objects that can receive ACPI notifications
230 if ((device_node
->type
!= ACPI_TYPE_DEVICE
) &&
231 (device_node
->type
!= ACPI_TYPE_PROCESSOR
) &&
232 (device_node
->type
!= ACPI_TYPE_POWER
) &&
233 (device_node
->type
!= ACPI_TYPE_THERMAL
)) {
234 status
= AE_BAD_PARAMETER
;
235 goto unlock_and_exit
;
238 /* Check for an existing internal object */
240 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) device_node
);
243 /* Object exists - make sure there's no handler */
245 if (((handler_type
== ACPI_SYSTEM_NOTIFY
) &&
246 obj_desc
->device
.sys_handler
) ||
247 ((handler_type
== ACPI_DEVICE_NOTIFY
) &&
248 obj_desc
->device
.drv_handler
)) {
250 goto unlock_and_exit
;
255 /* Create a new object */
257 obj_desc
= acpi_cm_create_internal_object (device_node
->type
);
259 status
= AE_NO_MEMORY
;
260 goto unlock_and_exit
;
263 /* Attach new object to the Node */
265 status
= acpi_ns_attach_object (device
, obj_desc
, (u8
) device_node
->type
);
267 if (ACPI_FAILURE (status
)) {
268 goto unlock_and_exit
;
272 /* Install the handler */
274 notify_obj
= acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY
);
276 status
= AE_NO_MEMORY
;
277 goto unlock_and_exit
;
280 notify_obj
->notify_handler
.node
= device_node
;
281 notify_obj
->notify_handler
.handler
= handler
;
282 notify_obj
->notify_handler
.context
= context
;
285 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
286 obj_desc
->device
.sys_handler
= notify_obj
;
288 else /* ACPI_DEVICE_NOTIFY */ {
289 obj_desc
->device
.drv_handler
= notify_obj
;
294 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
299 /*****************************************************************************
301 * FUNCTION: Acpi_remove_notify_handler
303 * PARAMETERS: Device - The device for which notifies will be handled
304 * Handler_type - The type of handler:
305 * ACPI_SYSTEM_NOTIFY: System_handler (00-7f)
306 * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff)
307 * Handler - Address of the handler
310 * DESCRIPTION: Remove a handler for notifies on an ACPI device
312 ******************************************************************************/
315 acpi_remove_notify_handler (
318 NOTIFY_HANDLER handler
)
320 ACPI_OPERAND_OBJECT
*notify_obj
;
321 ACPI_OPERAND_OBJECT
*obj_desc
;
322 ACPI_NAMESPACE_NODE
*device_node
;
323 ACPI_STATUS status
= AE_OK
;
325 /* Parameter validation */
328 (handler_type
> ACPI_MAX_NOTIFY_HANDLER_TYPE
)) {
329 return (AE_BAD_PARAMETER
);
332 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
334 /* Convert and validate the device handle */
336 device_node
= acpi_ns_convert_handle_to_entry (device
);
338 status
= AE_BAD_PARAMETER
;
339 goto unlock_and_exit
;
346 if (device
== ACPI_ROOT_OBJECT
) {
348 if (((handler_type
== ACPI_SYSTEM_NOTIFY
) &&
349 !acpi_gbl_sys_notify
.handler
) ||
350 ((handler_type
== ACPI_DEVICE_NOTIFY
) &&
351 !acpi_gbl_drv_notify
.handler
)) {
352 status
= AE_NOT_EXIST
;
353 goto unlock_and_exit
;
356 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
357 acpi_gbl_sys_notify
.node
= NULL
;
358 acpi_gbl_sys_notify
.handler
= NULL
;
359 acpi_gbl_sys_notify
.context
= NULL
;
362 acpi_gbl_drv_notify
.node
= NULL
;
363 acpi_gbl_drv_notify
.handler
= NULL
;
364 acpi_gbl_drv_notify
.context
= NULL
;
374 * These are the ONLY objects that can receive ACPI notifications
376 if ((device_node
->type
!= ACPI_TYPE_DEVICE
) &&
377 (device_node
->type
!= ACPI_TYPE_PROCESSOR
) &&
378 (device_node
->type
!= ACPI_TYPE_POWER
) &&
379 (device_node
->type
!= ACPI_TYPE_THERMAL
)) {
380 status
= AE_BAD_PARAMETER
;
381 goto unlock_and_exit
;
384 /* Check for an existing internal object */
386 obj_desc
= acpi_ns_get_attached_object ((ACPI_HANDLE
) device_node
);
388 status
= AE_NOT_EXIST
;
389 goto unlock_and_exit
;
392 /* Object exists - make sure there's an existing handler */
394 if (handler_type
== ACPI_SYSTEM_NOTIFY
) {
395 notify_obj
= obj_desc
->device
.sys_handler
;
398 notify_obj
= obj_desc
->device
.drv_handler
;
402 (notify_obj
->notify_handler
.handler
!= handler
)) {
403 status
= AE_BAD_PARAMETER
;
404 goto unlock_and_exit
;
407 /* 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
);
421 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
426 /******************************************************************************
428 * FUNCTION: Acpi_install_gpe_handler
430 * PARAMETERS: Gpe_number - The GPE number. The numbering scheme is
431 * bank 0 first, then bank 1.
432 * Type - Whether this GPE should be treated as an
433 * edge- or level-triggered interrupt.
434 * Handler - Address of the handler
435 * Context - Value passed to the handler on each GPE
439 * DESCRIPTION: Install a handler for a General Purpose Event.
441 ******************************************************************************/
444 acpi_install_gpe_handler (
450 ACPI_STATUS status
= AE_OK
;
452 /* Parameter validation */
454 if (!handler
|| (gpe_number
>= NUM_GPE
)) {
455 return (AE_BAD_PARAMETER
);
458 /* Ensure that we have a valid GPE number */
460 if (acpi_gbl_gpe_valid
[gpe_number
] == ACPI_GPE_INVALID
) {
461 return (AE_BAD_PARAMETER
);
464 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
466 /* Make sure that there isn't a handler there already */
468 if (acpi_gbl_gpe_info
[gpe_number
].handler
) {
473 /* Install the handler */
475 acpi_gbl_gpe_info
[gpe_number
].handler
= handler
;
476 acpi_gbl_gpe_info
[gpe_number
].context
= context
;
477 acpi_gbl_gpe_info
[gpe_number
].type
= (u8
) type
;
479 /* Clear the GPE (of stale events), the enable it */
481 acpi_hw_clear_gpe (gpe_number
);
482 acpi_hw_enable_gpe (gpe_number
);
485 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
490 /******************************************************************************
492 * FUNCTION: Acpi_remove_gpe_handler
494 * PARAMETERS: Gpe_number - The event to remove a handler
495 * Handler - Address of the handler
499 * DESCRIPTION: Remove a handler for a General Purpose Acpi_event.
501 ******************************************************************************/
504 acpi_remove_gpe_handler (
508 ACPI_STATUS status
= AE_OK
;
511 /* Parameter validation */
513 if (!handler
|| (gpe_number
>= NUM_GPE
)) {
514 return (AE_BAD_PARAMETER
);
517 /* Ensure that we have a valid GPE number */
519 if (acpi_gbl_gpe_valid
[gpe_number
] == ACPI_GPE_INVALID
) {
520 return (AE_BAD_PARAMETER
);
523 /* Disable the GPE before removing the handler */
525 acpi_hw_disable_gpe (gpe_number
);
527 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS
);
529 /* Make sure that the installed handler is the same */
531 if (acpi_gbl_gpe_info
[gpe_number
].handler
!= handler
) {
532 acpi_hw_enable_gpe (gpe_number
);
533 status
= AE_BAD_PARAMETER
;
537 /* Remove the handler */
539 acpi_gbl_gpe_info
[gpe_number
].handler
= NULL
;
540 acpi_gbl_gpe_info
[gpe_number
].context
= NULL
;
543 acpi_cm_release_mutex (ACPI_MTX_EVENTS
);
548 /******************************************************************************
550 * FUNCTION: Acpi_acquire_global_lock
552 * PARAMETERS: Timeout - How long the caller is willing to wait
553 * Out_handle - A handle to the lock if acquired
557 * DESCRIPTION: Acquire the ACPI Global Lock
559 ******************************************************************************/
561 acpi_acquire_global_lock (
567 status
= acpi_aml_enter_interpreter ();
568 if (ACPI_FAILURE (status
)) {
573 * TBD: [Restructure] add timeout param to internal interface, and
574 * perhaps INTERPRETER_LOCKED
577 status
= acpi_ev_acquire_global_lock ();
578 acpi_aml_exit_interpreter ();
584 /******************************************************************************
586 * FUNCTION: Acpi_release_global_lock
588 * PARAMETERS: Handle - Returned from Acpi_acquire_global_lock
592 * DESCRIPTION: Release the ACPI Global Lock
594 ******************************************************************************/
597 acpi_release_global_lock (
600 acpi_ev_release_global_lock ();