xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evxface.c (revision a085e81e62d7a860f809b4fb7c7bf5654c396985)
1 /******************************************************************************
2  *
3  * Module Name: evxface - External interfaces for ACPI events
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2012, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 
117 #define __EVXFACE_C__
118 
119 #include "acpi.h"
120 #include "accommon.h"
121 #include "acnamesp.h"
122 #include "acevents.h"
123 #include "acinterp.h"
124 
125 #define _COMPONENT          ACPI_EVENTS
126         ACPI_MODULE_NAME    ("evxface")
127 
128 
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiInstallNotifyHandler
132  *
133  * PARAMETERS:  Device          - The device for which notifies will be handled
134  *              HandlerType     - The type of handler:
135  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
136  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
137  *                                  ACPI_ALL_NOTIFY:    Both System and Device
138  *              Handler         - Address of the handler
139  *              Context         - Value passed to the handler on each GPE
140  *
141  * RETURN:      Status
142  *
143  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
144  *              ThermalZone, or Processor object.
145  *
146  * NOTES:       The Root namespace object may have only one handler for each
147  *              type of notify (System/Device). Device/Thermal/Processor objects
148  *              may have one device notify handler, and multiple system notify
149  *              handlers.
150  *
151  ******************************************************************************/
152 
153 ACPI_STATUS
154 AcpiInstallNotifyHandler (
155     ACPI_HANDLE             Device,
156     UINT32                  HandlerType,
157     ACPI_NOTIFY_HANDLER     Handler,
158     void                    *Context)
159 {
160     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
161     ACPI_OPERAND_OBJECT     *ObjDesc;
162     ACPI_OPERAND_OBJECT     *HandlerObj;
163     ACPI_STATUS             Status;
164     UINT32                  i;
165 
166 
167     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
168 
169 
170     /* Parameter validation */
171 
172     if ((!Device) || (!Handler) || (!HandlerType) ||
173         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
174     {
175         return_ACPI_STATUS (AE_BAD_PARAMETER);
176     }
177 
178     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
179     if (ACPI_FAILURE (Status))
180     {
181         return_ACPI_STATUS (Status);
182     }
183 
184     /*
185      * Root Object:
186      * Registering a notify handler on the root object indicates that the
187      * caller wishes to receive notifications for all objects. Note that
188      * only one global handler can be registered per notify type.
189      * Ensure that a handler is not already installed.
190      */
191     if (Device == ACPI_ROOT_OBJECT)
192     {
193         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
194         {
195             if (HandlerType & (i+1))
196             {
197                 if (AcpiGbl_GlobalNotify[i].Handler)
198                 {
199                     Status = AE_ALREADY_EXISTS;
200                     goto UnlockAndExit;
201                 }
202 
203                 AcpiGbl_GlobalNotify[i].Handler = Handler;
204                 AcpiGbl_GlobalNotify[i].Context = Context;
205             }
206         }
207 
208         goto UnlockAndExit; /* Global notify handler installed, all done */
209     }
210 
211     /*
212      * All Other Objects:
213      * Caller will only receive notifications specific to the target
214      * object. Note that only certain object types are allowed to
215      * receive notifications.
216      */
217 
218     /* Are Notifies allowed on this object? */
219 
220     if (!AcpiEvIsNotifyObject (Node))
221     {
222         Status = AE_TYPE;
223         goto UnlockAndExit;
224     }
225 
226     /* Check for an existing internal object, might not exist */
227 
228     ObjDesc = AcpiNsGetAttachedObject (Node);
229     if (!ObjDesc)
230     {
231         /* Create a new object */
232 
233         ObjDesc = AcpiUtCreateInternalObject (Node->Type);
234         if (!ObjDesc)
235         {
236             Status = AE_NO_MEMORY;
237             goto UnlockAndExit;
238         }
239 
240         /* Attach new object to the Node, remove local reference */
241 
242         Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
243         AcpiUtRemoveReference (ObjDesc);
244         if (ACPI_FAILURE (Status))
245         {
246             goto UnlockAndExit;
247         }
248     }
249 
250     /* Ensure that the handler is not already installed in the lists */
251 
252     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
253     {
254         if (HandlerType & (i+1))
255         {
256             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
257             while (HandlerObj)
258             {
259                 if (HandlerObj->Notify.Handler == Handler)
260                 {
261                     Status = AE_ALREADY_EXISTS;
262                     goto UnlockAndExit;
263                 }
264 
265                 HandlerObj = HandlerObj->Notify.Next[i];
266             }
267         }
268     }
269 
270     /* Create and populate a new notify handler object */
271 
272     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
273     if (!HandlerObj)
274     {
275         Status = AE_NO_MEMORY;
276         goto UnlockAndExit;
277     }
278 
279     HandlerObj->Notify.Node = Node;
280     HandlerObj->Notify.HandlerType = HandlerType;
281     HandlerObj->Notify.Handler = Handler;
282     HandlerObj->Notify.Context = Context;
283 
284     /* Install the handler at the list head(s) */
285 
286     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
287     {
288         if (HandlerType & (i+1))
289         {
290             HandlerObj->Notify.Next[i] =
291                 ObjDesc->CommonNotify.NotifyList[i];
292 
293             ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
294         }
295     }
296 
297     /* Add an extra reference if handler was installed in both lists */
298 
299     if (HandlerType == ACPI_ALL_NOTIFY)
300     {
301         AcpiUtAddReference (HandlerObj);
302     }
303 
304 
305 UnlockAndExit:
306     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
307     return_ACPI_STATUS (Status);
308 }
309 
310 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
311 
312 
313 /*******************************************************************************
314  *
315  * FUNCTION:    AcpiRemoveNotifyHandler
316  *
317  * PARAMETERS:  Device          - The device for which the handler is installed
318  *              HandlerType     - The type of handler:
319  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
320  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
321  *                                  ACPI_ALL_NOTIFY:    Both System and Device
322  *              Handler         - Address of the handler
323  *
324  * RETURN:      Status
325  *
326  * DESCRIPTION: Remove a handler for notifies on an ACPI device
327  *
328  ******************************************************************************/
329 
330 ACPI_STATUS
331 AcpiRemoveNotifyHandler (
332     ACPI_HANDLE             Device,
333     UINT32                  HandlerType,
334     ACPI_NOTIFY_HANDLER     Handler)
335 {
336     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
337     ACPI_OPERAND_OBJECT     *ObjDesc;
338     ACPI_OPERAND_OBJECT     *HandlerObj;
339     ACPI_OPERAND_OBJECT     *PreviousHandlerObj;
340     ACPI_STATUS             Status;
341     UINT32                  i;
342 
343 
344     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
345 
346 
347     /* Parameter validation */
348 
349     if ((!Device) || (!Handler) || (!HandlerType) ||
350         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
351     {
352         return_ACPI_STATUS (AE_BAD_PARAMETER);
353     }
354 
355     /* Make sure all deferred notify tasks are completed */
356 
357     AcpiOsWaitEventsComplete ();
358 
359     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
360     if (ACPI_FAILURE (Status))
361     {
362         return_ACPI_STATUS (Status);
363     }
364 
365     /* Root Object. Global handlers are removed here */
366 
367     if (Device == ACPI_ROOT_OBJECT)
368     {
369         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
370         {
371             if (HandlerType & (i+1))
372             {
373                 if (!AcpiGbl_GlobalNotify[i].Handler ||
374                     (AcpiGbl_GlobalNotify[i].Handler != Handler))
375                 {
376                     Status = AE_NOT_EXIST;
377                     goto UnlockAndExit;
378                 }
379 
380                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
381                     "Removing global notify handler\n"));
382 
383                 AcpiGbl_GlobalNotify[i].Handler = NULL;
384                 AcpiGbl_GlobalNotify[i].Context = NULL;
385             }
386         }
387 
388         goto UnlockAndExit;
389     }
390 
391     /* All other objects: Are Notifies allowed on this object? */
392 
393     if (!AcpiEvIsNotifyObject (Node))
394     {
395         Status = AE_TYPE;
396         goto UnlockAndExit;
397     }
398 
399     /* Must have an existing internal object */
400 
401     ObjDesc = AcpiNsGetAttachedObject (Node);
402     if (!ObjDesc)
403     {
404         Status = AE_NOT_EXIST;
405         goto UnlockAndExit;
406     }
407 
408     /* Internal object exists. Find the handler and remove it */
409 
410     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
411     {
412         if (HandlerType & (i+1))
413         {
414             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
415             PreviousHandlerObj = NULL;
416 
417             /* Attempt to find the handler in the handler list */
418 
419             while (HandlerObj &&
420                   (HandlerObj->Notify.Handler != Handler))
421             {
422                 PreviousHandlerObj = HandlerObj;
423                 HandlerObj = HandlerObj->Notify.Next[i];
424             }
425 
426             if (!HandlerObj)
427             {
428                 Status = AE_NOT_EXIST;
429                 goto UnlockAndExit;
430             }
431 
432             /* Remove the handler object from the list */
433 
434             if (PreviousHandlerObj) /* Handler is not at the list head */
435             {
436                 PreviousHandlerObj->Notify.Next[i] =
437                     HandlerObj->Notify.Next[i];
438             }
439             else /* Handler is at the list head */
440             {
441                 ObjDesc->CommonNotify.NotifyList[i] =
442                     HandlerObj->Notify.Next[i];
443             }
444 
445             AcpiUtRemoveReference (HandlerObj);
446         }
447     }
448 
449 
450 UnlockAndExit:
451     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
452     return_ACPI_STATUS (Status);
453 }
454 
455 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
456 
457 
458 /*******************************************************************************
459  *
460  * FUNCTION:    AcpiInstallExceptionHandler
461  *
462  * PARAMETERS:  Handler         - Pointer to the handler function for the
463  *                                event
464  *
465  * RETURN:      Status
466  *
467  * DESCRIPTION: Saves the pointer to the handler function
468  *
469  ******************************************************************************/
470 
471 ACPI_STATUS
472 AcpiInstallExceptionHandler (
473     ACPI_EXCEPTION_HANDLER  Handler)
474 {
475     ACPI_STATUS             Status;
476 
477 
478     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
479 
480 
481     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
482     if (ACPI_FAILURE (Status))
483     {
484         return_ACPI_STATUS (Status);
485     }
486 
487     /* Don't allow two handlers. */
488 
489     if (AcpiGbl_ExceptionHandler)
490     {
491         Status = AE_ALREADY_EXISTS;
492         goto Cleanup;
493     }
494 
495     /* Install the handler */
496 
497     AcpiGbl_ExceptionHandler = Handler;
498 
499 Cleanup:
500     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
501     return_ACPI_STATUS (Status);
502 }
503 
504 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
505 
506 
507 #if (!ACPI_REDUCED_HARDWARE)
508 /*******************************************************************************
509  *
510  * FUNCTION:    AcpiInstallGlobalEventHandler
511  *
512  * PARAMETERS:  Handler         - Pointer to the global event handler function
513  *              Context         - Value passed to the handler on each event
514  *
515  * RETURN:      Status
516  *
517  * DESCRIPTION: Saves the pointer to the handler function. The global handler
518  *              is invoked upon each incoming GPE and Fixed Event. It is
519  *              invoked at interrupt level at the time of the event dispatch.
520  *              Can be used to update event counters, etc.
521  *
522  ******************************************************************************/
523 
524 ACPI_STATUS
525 AcpiInstallGlobalEventHandler (
526     ACPI_GBL_EVENT_HANDLER  Handler,
527     void                    *Context)
528 {
529     ACPI_STATUS             Status;
530 
531 
532     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
533 
534 
535     /* Parameter validation */
536 
537     if (!Handler)
538     {
539         return_ACPI_STATUS (AE_BAD_PARAMETER);
540     }
541 
542     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
543     if (ACPI_FAILURE (Status))
544     {
545         return_ACPI_STATUS (Status);
546     }
547 
548     /* Don't allow two handlers. */
549 
550     if (AcpiGbl_GlobalEventHandler)
551     {
552         Status = AE_ALREADY_EXISTS;
553         goto Cleanup;
554     }
555 
556     AcpiGbl_GlobalEventHandler = Handler;
557     AcpiGbl_GlobalEventHandlerContext = Context;
558 
559 
560 Cleanup:
561     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
562     return_ACPI_STATUS (Status);
563 }
564 
565 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
566 
567 
568 /*******************************************************************************
569  *
570  * FUNCTION:    AcpiInstallFixedEventHandler
571  *
572  * PARAMETERS:  Event           - Event type to enable.
573  *              Handler         - Pointer to the handler function for the
574  *                                event
575  *              Context         - Value passed to the handler on each GPE
576  *
577  * RETURN:      Status
578  *
579  * DESCRIPTION: Saves the pointer to the handler function and then enables the
580  *              event.
581  *
582  ******************************************************************************/
583 
584 ACPI_STATUS
585 AcpiInstallFixedEventHandler (
586     UINT32                  Event,
587     ACPI_EVENT_HANDLER      Handler,
588     void                    *Context)
589 {
590     ACPI_STATUS             Status;
591 
592 
593     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
594 
595 
596     /* Parameter validation */
597 
598     if (Event > ACPI_EVENT_MAX)
599     {
600         return_ACPI_STATUS (AE_BAD_PARAMETER);
601     }
602 
603     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
604     if (ACPI_FAILURE (Status))
605     {
606         return_ACPI_STATUS (Status);
607     }
608 
609     /* Don't allow two handlers. */
610 
611     if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
612     {
613         Status = AE_ALREADY_EXISTS;
614         goto Cleanup;
615     }
616 
617     /* Install the handler before enabling the event */
618 
619     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
620     AcpiGbl_FixedEventHandlers[Event].Context = Context;
621 
622     Status = AcpiEnableEvent (Event, 0);
623     if (ACPI_FAILURE (Status))
624     {
625         ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
626 
627         /* Remove the handler */
628 
629         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
630         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
631     }
632     else
633     {
634         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
635             "Enabled fixed event %X, Handler=%p\n", Event, Handler));
636     }
637 
638 
639 Cleanup:
640     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
641     return_ACPI_STATUS (Status);
642 }
643 
644 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
645 
646 
647 /*******************************************************************************
648  *
649  * FUNCTION:    AcpiRemoveFixedEventHandler
650  *
651  * PARAMETERS:  Event           - Event type to disable.
652  *              Handler         - Address of the handler
653  *
654  * RETURN:      Status
655  *
656  * DESCRIPTION: Disables the event and unregisters the event handler.
657  *
658  ******************************************************************************/
659 
660 ACPI_STATUS
661 AcpiRemoveFixedEventHandler (
662     UINT32                  Event,
663     ACPI_EVENT_HANDLER      Handler)
664 {
665     ACPI_STATUS             Status = AE_OK;
666 
667 
668     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
669 
670 
671     /* Parameter validation */
672 
673     if (Event > ACPI_EVENT_MAX)
674     {
675         return_ACPI_STATUS (AE_BAD_PARAMETER);
676     }
677 
678     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
679     if (ACPI_FAILURE (Status))
680     {
681         return_ACPI_STATUS (Status);
682     }
683 
684     /* Disable the event before removing the handler */
685 
686     Status = AcpiDisableEvent (Event, 0);
687 
688     /* Always Remove the handler */
689 
690     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
691     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
692 
693     if (ACPI_FAILURE (Status))
694     {
695         ACPI_WARNING ((AE_INFO,
696             "Could not write to fixed event enable register 0x%X", Event));
697     }
698     else
699     {
700         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
701     }
702 
703     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
704     return_ACPI_STATUS (Status);
705 }
706 
707 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
708 
709 
710 /*******************************************************************************
711  *
712  * FUNCTION:    AcpiInstallGpeHandler
713  *
714  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
715  *                                defined GPEs)
716  *              GpeNumber       - The GPE number within the GPE block
717  *              Type            - Whether this GPE should be treated as an
718  *                                edge- or level-triggered interrupt.
719  *              Address         - Address of the handler
720  *              Context         - Value passed to the handler on each GPE
721  *
722  * RETURN:      Status
723  *
724  * DESCRIPTION: Install a handler for a General Purpose Event.
725  *
726  ******************************************************************************/
727 
728 ACPI_STATUS
729 AcpiInstallGpeHandler (
730     ACPI_HANDLE             GpeDevice,
731     UINT32                  GpeNumber,
732     UINT32                  Type,
733     ACPI_GPE_HANDLER        Address,
734     void                    *Context)
735 {
736     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
737     ACPI_GPE_HANDLER_INFO   *Handler;
738     ACPI_STATUS             Status;
739     ACPI_CPU_FLAGS          Flags;
740 
741 
742     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
743 
744 
745     /* Parameter validation */
746 
747     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
748     {
749         return_ACPI_STATUS (AE_BAD_PARAMETER);
750     }
751 
752     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
753     if (ACPI_FAILURE (Status))
754     {
755         return_ACPI_STATUS (Status);
756     }
757 
758     /* Allocate and init handler object (before lock) */
759 
760     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
761     if (!Handler)
762     {
763         Status = AE_NO_MEMORY;
764         goto UnlockAndExit;
765     }
766 
767     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
768 
769     /* Ensure that we have a valid GPE number */
770 
771     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
772     if (!GpeEventInfo)
773     {
774         Status = AE_BAD_PARAMETER;
775         goto FreeAndExit;
776     }
777 
778     /* Make sure that there isn't a handler there already */
779 
780     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
781             ACPI_GPE_DISPATCH_HANDLER)
782     {
783         Status = AE_ALREADY_EXISTS;
784         goto FreeAndExit;
785     }
786 
787     Handler->Address = Address;
788     Handler->Context = Context;
789     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
790     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
791         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
792 
793     /*
794      * If the GPE is associated with a method, it may have been enabled
795      * automatically during initialization, in which case it has to be
796      * disabled now to avoid spurious execution of the handler.
797      */
798     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
799          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
800         GpeEventInfo->RuntimeCount)
801     {
802         Handler->OriginallyEnabled = TRUE;
803         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
804 
805         /* Sanity check of original type against new type */
806 
807         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
808         {
809             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
810         }
811     }
812 
813     /* Install the handler */
814 
815     GpeEventInfo->Dispatch.Handler = Handler;
816 
817     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
818 
819     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
820     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
821 
822     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
823 
824 
825 UnlockAndExit:
826     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
827     return_ACPI_STATUS (Status);
828 
829 FreeAndExit:
830     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
831     ACPI_FREE (Handler);
832     goto UnlockAndExit;
833 }
834 
835 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
836 
837 
838 /*******************************************************************************
839  *
840  * FUNCTION:    AcpiRemoveGpeHandler
841  *
842  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
843  *                                defined GPEs)
844  *              GpeNumber       - The event to remove a handler
845  *              Address         - Address of the handler
846  *
847  * RETURN:      Status
848  *
849  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
850  *
851  ******************************************************************************/
852 
853 ACPI_STATUS
854 AcpiRemoveGpeHandler (
855     ACPI_HANDLE             GpeDevice,
856     UINT32                  GpeNumber,
857     ACPI_GPE_HANDLER        Address)
858 {
859     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
860     ACPI_GPE_HANDLER_INFO   *Handler;
861     ACPI_STATUS             Status;
862     ACPI_CPU_FLAGS          Flags;
863 
864 
865     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
866 
867 
868     /* Parameter validation */
869 
870     if (!Address)
871     {
872         return_ACPI_STATUS (AE_BAD_PARAMETER);
873     }
874 
875     /* Make sure all deferred GPE tasks are completed */
876 
877     AcpiOsWaitEventsComplete ();
878 
879     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
880     if (ACPI_FAILURE (Status))
881     {
882         return_ACPI_STATUS (Status);
883     }
884 
885     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
886 
887     /* Ensure that we have a valid GPE number */
888 
889     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
890     if (!GpeEventInfo)
891     {
892         Status = AE_BAD_PARAMETER;
893         goto UnlockAndExit;
894     }
895 
896     /* Make sure that a handler is indeed installed */
897 
898     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
899             ACPI_GPE_DISPATCH_HANDLER)
900     {
901         Status = AE_NOT_EXIST;
902         goto UnlockAndExit;
903     }
904 
905     /* Make sure that the installed handler is the same */
906 
907     if (GpeEventInfo->Dispatch.Handler->Address != Address)
908     {
909         Status = AE_BAD_PARAMETER;
910         goto UnlockAndExit;
911     }
912 
913     /* Remove the handler */
914 
915     Handler = GpeEventInfo->Dispatch.Handler;
916 
917     /* Restore Method node (if any), set dispatch flags */
918 
919     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
920     GpeEventInfo->Flags &=
921         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
922     GpeEventInfo->Flags |= Handler->OriginalFlags;
923 
924     /*
925      * If the GPE was previously associated with a method and it was
926      * enabled, it should be enabled at this point to restore the
927      * post-initialization configuration.
928      */
929     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
930         Handler->OriginallyEnabled)
931     {
932         (void) AcpiEvAddGpeReference (GpeEventInfo);
933     }
934 
935     /* Now we can free the handler object */
936 
937     ACPI_FREE (Handler);
938 
939 
940 UnlockAndExit:
941     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
942     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
943     return_ACPI_STATUS (Status);
944 }
945 
946 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
947 
948 
949 /*******************************************************************************
950  *
951  * FUNCTION:    AcpiAcquireGlobalLock
952  *
953  * PARAMETERS:  Timeout         - How long the caller is willing to wait
954  *              Handle          - Where the handle to the lock is returned
955  *                                (if acquired)
956  *
957  * RETURN:      Status
958  *
959  * DESCRIPTION: Acquire the ACPI Global Lock
960  *
961  * Note: Allows callers with the same thread ID to acquire the global lock
962  * multiple times. In other words, externally, the behavior of the global lock
963  * is identical to an AML mutex. On the first acquire, a new handle is
964  * returned. On any subsequent calls to acquire by the same thread, the same
965  * handle is returned.
966  *
967  ******************************************************************************/
968 
969 ACPI_STATUS
970 AcpiAcquireGlobalLock (
971     UINT16                  Timeout,
972     UINT32                  *Handle)
973 {
974     ACPI_STATUS             Status;
975 
976 
977     if (!Handle)
978     {
979         return (AE_BAD_PARAMETER);
980     }
981 
982     /* Must lock interpreter to prevent race conditions */
983 
984     AcpiExEnterInterpreter ();
985 
986     Status = AcpiExAcquireMutexObject (Timeout,
987                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
988 
989     if (ACPI_SUCCESS (Status))
990     {
991         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
992 
993         *Handle = AcpiGbl_GlobalLockHandle;
994     }
995 
996     AcpiExExitInterpreter ();
997     return (Status);
998 }
999 
1000 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1001 
1002 
1003 /*******************************************************************************
1004  *
1005  * FUNCTION:    AcpiReleaseGlobalLock
1006  *
1007  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1008  *
1009  * RETURN:      Status
1010  *
1011  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1012  *
1013  ******************************************************************************/
1014 
1015 ACPI_STATUS
1016 AcpiReleaseGlobalLock (
1017     UINT32                  Handle)
1018 {
1019     ACPI_STATUS             Status;
1020 
1021 
1022     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1023     {
1024         return (AE_NOT_ACQUIRED);
1025     }
1026 
1027     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1028     return (Status);
1029 }
1030 
1031 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1032 
1033 #endif /* !ACPI_REDUCED_HARDWARE */
1034