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
34 #define _COMPONENT ACPI_EVENTS
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,
63 /* Parameter validation */
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);
85 if (!ACPI_SUCCESS (status)) {
86 /* Remove the handler */
88 acpi_gbl_fixed_event_handlers[event].handler = NULL;
89 acpi_gbl_fixed_event_handlers[event].context = NULL;
95 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
100 /******************************************************************************
102 * FUNCTION: Acpi_remove_fixed_event_handler
104 * PARAMETERS: Event - Event type to disable.
105 * Handler - Address of the handler
109 * DESCRIPTION: Disables the event and unregisters the event handler.
111 ******************************************************************************/
114 acpi_remove_fixed_event_handler (
116 FIXED_EVENT_HANDLER handler)
118 ACPI_STATUS status = AE_OK;
121 /* Parameter validation */
123 if (event >= NUM_FIXED_EVENTS) {
124 return (AE_BAD_PARAMETER);
127 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS);
129 /* Disable the event before removing the handler - just in case... */
131 status = acpi_disable_event(event, ACPI_EVENT_FIXED);
133 /* Always Remove the handler */
135 acpi_gbl_fixed_event_handlers[event].handler = NULL;
136 acpi_gbl_fixed_event_handlers[event].context = NULL;
141 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
146 /******************************************************************************
148 * FUNCTION: Acpi_install_notify_handler
150 * PARAMETERS: Device - The device for which notifies will be handled
151 * Handler_type - The type of handler:
152 * ACPI_SYSTEM_NOTIFY: System_handler (00-7f)
153 * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff)
154 * Handler - Address of the handler
155 * Context - Value passed to the handler on each GPE
159 * DESCRIPTION: Install a handler for notifies on an ACPI device
161 ******************************************************************************/
164 acpi_install_notify_handler (
167 NOTIFY_HANDLER handler,
170 ACPI_OPERAND_OBJECT *obj_desc;
171 ACPI_OPERAND_OBJECT *notify_obj;
172 ACPI_NAMESPACE_NODE *device_node;
173 ACPI_STATUS status = AE_OK;
176 /* Parameter validation */
179 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
180 return (AE_BAD_PARAMETER);
183 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
185 /* Convert and validate the device handle */
187 device_node = acpi_ns_convert_handle_to_entry (device);
189 status = AE_BAD_PARAMETER;
190 goto unlock_and_exit;
196 * Registering a notify handler on the root object indicates that the
197 * caller wishes to receive notifications for all objects. Note that
198 * only one <external> global handler can be regsitered (per notify type).
200 if (device == ACPI_ROOT_OBJECT) {
201 /* Make sure the handler is not already installed */
203 if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
204 acpi_gbl_sys_notify.handler) ||
205 ((handler_type == ACPI_DEVICE_NOTIFY) &&
206 acpi_gbl_drv_notify.handler)) {
208 goto unlock_and_exit;
211 if (handler_type == ACPI_SYSTEM_NOTIFY) {
212 acpi_gbl_sys_notify.node = device_node;
213 acpi_gbl_sys_notify.handler = handler;
214 acpi_gbl_sys_notify.context = context;
216 else /* ACPI_DEVICE_NOTIFY */ {
217 acpi_gbl_drv_notify.node = device_node;
218 acpi_gbl_drv_notify.handler = handler;
219 acpi_gbl_drv_notify.context = context;
222 /* Global notify handler installed */
228 * Caller will only receive notifications specific to the target object.
229 * Note that only certain object types can receive notifications.
233 * These are the ONLY objects that can receive ACPI notifications
235 if ((device_node->type != ACPI_TYPE_DEVICE) &&
236 (device_node->type != ACPI_TYPE_PROCESSOR) &&
237 (device_node->type != ACPI_TYPE_POWER) &&
238 (device_node->type != ACPI_TYPE_THERMAL)) {
239 status = AE_BAD_PARAMETER;
240 goto unlock_and_exit;
243 /* Check for an existing internal object */
245 obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
248 /* Object exists - make sure there's no handler */
250 if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
251 obj_desc->device.sys_handler) ||
252 ((handler_type == ACPI_DEVICE_NOTIFY) &&
253 obj_desc->device.drv_handler)) {
255 goto unlock_and_exit;
260 /* Create a new object */
262 obj_desc = acpi_cm_create_internal_object (device_node->type);
264 status = AE_NO_MEMORY;
265 goto unlock_and_exit;
268 /* Attach new object to the Node */
270 status = acpi_ns_attach_object (device, obj_desc, (u8) device_node->type);
272 if (ACPI_FAILURE (status)) {
273 goto unlock_and_exit;
277 /* Install the handler */
279 notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY);
281 status = AE_NO_MEMORY;
282 goto unlock_and_exit;
285 notify_obj->notify_handler.node = device_node;
286 notify_obj->notify_handler.handler = handler;
287 notify_obj->notify_handler.context = context;
290 if (handler_type == ACPI_SYSTEM_NOTIFY) {
291 obj_desc->device.sys_handler = notify_obj;
293 else /* ACPI_DEVICE_NOTIFY */ {
294 obj_desc->device.drv_handler = notify_obj;
299 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
304 /*****************************************************************************
306 * FUNCTION: Acpi_remove_notify_handler
308 * PARAMETERS: Device - The device for which notifies will be handled
309 * Handler_type - The type of handler:
310 * ACPI_SYSTEM_NOTIFY: System_handler (00-7f)
311 * ACPI_DEVICE_NOTIFY: Driver_handler (80-ff)
312 * Handler - Address of the handler
315 * DESCRIPTION: Remove a handler for notifies on an ACPI device
317 ******************************************************************************/
320 acpi_remove_notify_handler (
323 NOTIFY_HANDLER handler)
325 ACPI_OPERAND_OBJECT *notify_obj;
326 ACPI_OPERAND_OBJECT *obj_desc;
327 ACPI_NAMESPACE_NODE *device_node;
328 ACPI_STATUS status = AE_OK;
330 /* Parameter validation */
333 (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
334 return (AE_BAD_PARAMETER);
337 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
339 /* Convert and validate the device handle */
341 device_node = acpi_ns_convert_handle_to_entry (device);
343 status = AE_BAD_PARAMETER;
344 goto unlock_and_exit;
351 if (device == ACPI_ROOT_OBJECT) {
353 if (((handler_type == ACPI_SYSTEM_NOTIFY) &&
354 !acpi_gbl_sys_notify.handler) ||
355 ((handler_type == ACPI_DEVICE_NOTIFY) &&
356 !acpi_gbl_drv_notify.handler)) {
357 status = AE_NOT_EXIST;
358 goto unlock_and_exit;
361 if (handler_type == ACPI_SYSTEM_NOTIFY) {
362 acpi_gbl_sys_notify.node = NULL;
363 acpi_gbl_sys_notify.handler = NULL;
364 acpi_gbl_sys_notify.context = NULL;
367 acpi_gbl_drv_notify.node = NULL;
368 acpi_gbl_drv_notify.handler = NULL;
369 acpi_gbl_drv_notify.context = NULL;
379 * These are the ONLY objects that can receive ACPI notifications
381 if ((device_node->type != ACPI_TYPE_DEVICE) &&
382 (device_node->type != ACPI_TYPE_PROCESSOR) &&
383 (device_node->type != ACPI_TYPE_POWER) &&
384 (device_node->type != ACPI_TYPE_THERMAL)) {
385 status = AE_BAD_PARAMETER;
386 goto unlock_and_exit;
389 /* Check for an existing internal object */
391 obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) device_node);
393 status = AE_NOT_EXIST;
394 goto unlock_and_exit;
397 /* Object exists - make sure there's an existing handler */
399 if (handler_type == ACPI_SYSTEM_NOTIFY) {
400 notify_obj = obj_desc->device.sys_handler;
403 notify_obj = obj_desc->device.drv_handler;
407 (notify_obj->notify_handler.handler != handler)) {
408 status = AE_BAD_PARAMETER;
409 goto unlock_and_exit;
412 /* Remove the handler */
414 if (handler_type == ACPI_SYSTEM_NOTIFY) {
415 obj_desc->device.sys_handler = NULL;
418 obj_desc->device.drv_handler = NULL;
421 acpi_cm_remove_reference (notify_obj);
426 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
431 /******************************************************************************
433 * FUNCTION: Acpi_install_gpe_handler
435 * PARAMETERS: Gpe_number - The GPE number. The numbering scheme is
436 * bank 0 first, then bank 1.
437 * Type - Whether this GPE should be treated as an
438 * edge- or level-triggered interrupt.
439 * Handler - Address of the handler
440 * Context - Value passed to the handler on each GPE
444 * DESCRIPTION: Install a handler for a General Purpose Event.
446 ******************************************************************************/
449 acpi_install_gpe_handler (
455 ACPI_STATUS status = AE_OK;
457 /* Parameter validation */
459 if (!handler || (gpe_number > NUM_GPE)) {
460 return (AE_BAD_PARAMETER);
463 /* Ensure that we have a valid GPE number */
465 if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
466 return (AE_BAD_PARAMETER);
469 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS);
471 /* Make sure that there isn't a handler there already */
473 if (acpi_gbl_gpe_info[gpe_number].handler) {
478 /* Install the handler */
480 acpi_gbl_gpe_info[gpe_number].handler = handler;
481 acpi_gbl_gpe_info[gpe_number].context = context;
482 acpi_gbl_gpe_info[gpe_number].type = (u8) type;
484 /* Clear the GPE (of stale events), the enable it */
486 acpi_hw_clear_gpe (gpe_number);
487 acpi_hw_enable_gpe (gpe_number);
490 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
495 /******************************************************************************
497 * FUNCTION: Acpi_remove_gpe_handler
499 * PARAMETERS: Gpe_number - The event to remove a handler
500 * Handler - Address of the handler
504 * DESCRIPTION: Remove a handler for a General Purpose Acpi_event.
506 ******************************************************************************/
509 acpi_remove_gpe_handler (
513 ACPI_STATUS status = AE_OK;
516 /* Parameter validation */
518 if (!handler || (gpe_number > NUM_GPE)) {
519 return (AE_BAD_PARAMETER);
522 /* Ensure that we have a valid GPE number */
524 if (acpi_gbl_gpe_valid[gpe_number] == ACPI_GPE_INVALID) {
525 return (AE_BAD_PARAMETER);
528 /* Disable the GPE before removing the handler */
530 acpi_hw_disable_gpe (gpe_number);
532 acpi_cm_acquire_mutex (ACPI_MTX_EVENTS);
534 /* Make sure that the installed handler is the same */
536 if (acpi_gbl_gpe_info[gpe_number].handler != handler) {
537 acpi_hw_enable_gpe (gpe_number);
538 status = AE_BAD_PARAMETER;
542 /* Remove the handler */
544 acpi_gbl_gpe_info[gpe_number].handler = NULL;
545 acpi_gbl_gpe_info[gpe_number].context = NULL;
548 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
553 /******************************************************************************
555 * FUNCTION: Acpi_acquire_global_lock
557 * PARAMETERS: Timeout - How long the caller is willing to wait
558 * Out_handle - A handle to the lock if acquired
562 * DESCRIPTION: Acquire the ACPI Global Lock
564 ******************************************************************************/
566 acpi_acquire_global_lock (
572 status = acpi_aml_enter_interpreter ();
573 if (ACPI_FAILURE (status)) {
578 * TBD: [Restructure] add timeout param to internal interface, and
579 * perhaps INTERPRETER_LOCKED
582 status = acpi_ev_acquire_global_lock ();
583 acpi_aml_exit_interpreter ();
589 /******************************************************************************
591 * FUNCTION: Acpi_release_global_lock
593 * PARAMETERS: Handle - Returned from Acpi_acquire_global_lock
597 * DESCRIPTION: Release the ACPI Global Lock
599 ******************************************************************************/
602 acpi_release_global_lock (
605 acpi_ev_release_global_lock ();