- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / events / evxface.c
blobc3bbad0ffbc23d48c054ebb36e49e87f4b26f503
1 /******************************************************************************
3 * Module Name: evxface - External interfaces for ACPI events
4 * $Revision: 97 $
6 *****************************************************************************/
8 /*
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
27 #include "acpi.h"
28 #include "achware.h"
29 #include "acnamesp.h"
30 #include "acevents.h"
31 #include "amlcode.h"
32 #include "acinterp.h"
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
44 * event
45 * Context - Value passed to the handler on each GPE
47 * RETURN: Status
49 * DESCRIPTION: Saves the pointer to the handler function and then enables the
50 * event.
52 ******************************************************************************/
54 ACPI_STATUS
55 acpi_install_fixed_event_handler (
56 u32 event,
57 FIXED_EVENT_HANDLER handler,
58 void *context)
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) {
74 status = AE_EXIST;
75 goto cleanup;
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;
92 status = AE_ERROR;
93 goto cleanup;
97 cleanup:
98 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
99 return (status);
103 /******************************************************************************
105 * FUNCTION: Acpi_remove_fixed_event_handler
107 * PARAMETERS: Event - Event type to disable.
108 * Handler - Address of the handler
110 * RETURN: Status
112 * DESCRIPTION: Disables the event and unregisters the event handler.
114 ******************************************************************************/
116 ACPI_STATUS
117 acpi_remove_fixed_event_handler (
118 u32 event,
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)) {
137 status = AE_ERROR;
138 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
139 return (status);
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);
148 return (status);
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
163 * RETURN: Status
165 * DESCRIPTION: Install a handler for notifies on an ACPI device
167 ******************************************************************************/
169 ACPI_STATUS
170 acpi_install_notify_handler (
171 ACPI_HANDLE device,
172 u32 handler_type,
173 NOTIFY_HANDLER handler,
174 void *context)
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 */
184 if ((!handler) ||
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);
195 if (!device_node) {
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))
216 status = AE_EXIST;
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;
226 else {
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);
255 if (obj_desc) {
257 * The object exists.
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))
266 status = AE_EXIST;
267 goto unlock_and_exit;
271 else {
272 /* Create a new object */
274 obj_desc = acpi_cm_create_internal_object (device_node->type);
275 if (!obj_desc) {
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
292 * so let's party
294 notify_obj = acpi_cm_create_internal_object (INTERNAL_TYPE_NOTIFY);
295 if (!notify_obj) {
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;
309 else {
310 obj_desc->device.drv_handler = notify_obj;
314 unlock_and_exit:
315 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
316 return (status);
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
329 * RETURN: Status
331 * DESCRIPTION: Remove a handler for notifies on an ACPI device
333 ******************************************************************************/
335 ACPI_STATUS
336 acpi_remove_notify_handler (
337 ACPI_HANDLE device,
338 u32 handler_type,
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 */
349 if ((!handler) ||
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);
360 if (!device_node) {
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);
381 if (!obj_desc) {
382 status = AE_NOT_EXIST;
383 goto unlock_and_exit;
387 * The object exists.
389 * Make sure the handler is installed.
392 if (handler_type == ACPI_SYSTEM_NOTIFY) {
393 notify_obj = obj_desc->device.sys_handler;
395 else {
396 notify_obj = obj_desc->device.drv_handler;
399 if ((!notify_obj) ||
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;
412 else {
413 obj_desc->device.drv_handler = NULL;
416 acpi_cm_remove_reference (notify_obj);
418 unlock_and_exit:
419 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
420 return (status);
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
434 * RETURN: Status
436 * DESCRIPTION: Install a handler for a General Purpose Event.
438 ******************************************************************************/
440 ACPI_STATUS
441 acpi_install_gpe_handler (
442 u32 gpe_number,
443 u32 type,
444 GPE_HANDLER handler,
445 void *context)
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) {
466 status = AE_EXIST;
467 goto cleanup;
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);
481 cleanup:
482 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
483 return (status);
487 /******************************************************************************
489 * FUNCTION: Acpi_remove_gpe_handler
491 * PARAMETERS: Gpe_number - The event to remove a handler
492 * Handler - Address of the handler
494 * RETURN: Status
496 * DESCRIPTION: Remove a handler for a General Purpose Acpi_event.
498 ******************************************************************************/
500 ACPI_STATUS
501 acpi_remove_gpe_handler (
502 u32 gpe_number,
503 GPE_HANDLER 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;
531 goto cleanup;
534 /* Remove the handler */
536 acpi_gbl_gpe_info[gpe_number].handler = NULL;
537 acpi_gbl_gpe_info[gpe_number].context = NULL;
539 cleanup:
540 acpi_cm_release_mutex (ACPI_MTX_EVENTS);
541 return (status);
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
552 * RETURN: Status
554 * DESCRIPTION: Acquire the ACPI Global Lock
556 ******************************************************************************/
557 ACPI_STATUS
558 acpi_acquire_global_lock (
559 void)
561 ACPI_STATUS status;
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 ();
574 return (status);
578 /******************************************************************************
580 * FUNCTION: Acpi_release_global_lock
582 * PARAMETERS: Handle - Returned from Acpi_acquire_global_lock
584 * RETURN: Status
586 * DESCRIPTION: Release the ACPI Global Lock
588 ******************************************************************************/
590 ACPI_STATUS
591 acpi_release_global_lock (
592 void)
594 acpi_ev_release_global_lock ();
595 return (AE_OK);