xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evxface.c (revision 986e4abce4efeccd9418eb8cdc7a710487f093b9)
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 - 2013, 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:    AcpiInstallSciHandler
511  *
512  * PARAMETERS:  Address             - Address of the handler
513  *              Context             - Value passed to the handler on each SCI
514  *
515  * RETURN:      Status
516  *
517  * DESCRIPTION: Install a handler for a System Control Interrupt.
518  *
519  ******************************************************************************/
520 
521 ACPI_STATUS
522 AcpiInstallSciHandler (
523     ACPI_SCI_HANDLER        Address,
524     void                    *Context)
525 {
526     ACPI_SCI_HANDLER_INFO   *NewSciHandler;
527     ACPI_SCI_HANDLER_INFO   *SciHandler;
528     ACPI_CPU_FLAGS          Flags;
529     ACPI_STATUS             Status;
530 
531 
532     ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
533 
534 
535     if (!Address)
536     {
537         return_ACPI_STATUS (AE_BAD_PARAMETER);
538     }
539 
540     /* Allocate and init a handler object */
541 
542     NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
543     if (!NewSciHandler)
544     {
545         return_ACPI_STATUS (AE_NO_MEMORY);
546     }
547 
548     NewSciHandler->Address = Address;
549     NewSciHandler->Context = Context;
550 
551     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
552     if (ACPI_FAILURE (Status))
553     {
554         goto Exit;
555     }
556 
557     /* Lock list during installation */
558 
559     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
560     SciHandler = AcpiGbl_SciHandlerList;
561 
562     /* Ensure handler does not already exist */
563 
564     while (SciHandler)
565     {
566         if (Address == SciHandler->Address)
567         {
568             Status = AE_ALREADY_EXISTS;
569             goto UnlockAndExit;
570         }
571 
572         SciHandler = SciHandler->Next;
573     }
574 
575     /* Install the new handler into the global list (at head) */
576 
577     NewSciHandler->Next = AcpiGbl_SciHandlerList;
578     AcpiGbl_SciHandlerList = NewSciHandler;
579 
580 
581 UnlockAndExit:
582 
583     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
584     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
585 
586 Exit:
587     if (ACPI_FAILURE (Status))
588     {
589         ACPI_FREE (NewSciHandler);
590     }
591     return_ACPI_STATUS (Status);
592 }
593 
594 
595 /*******************************************************************************
596  *
597  * FUNCTION:    AcpiRemoveSciHandler
598  *
599  * PARAMETERS:  Address             - Address of the handler
600  *
601  * RETURN:      Status
602  *
603  * DESCRIPTION: Remove a handler for a System Control Interrupt.
604  *
605  ******************************************************************************/
606 
607 ACPI_STATUS
608 AcpiRemoveSciHandler (
609     ACPI_SCI_HANDLER        Address)
610 {
611     ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
612     ACPI_SCI_HANDLER_INFO   *NextSciHandler;
613     ACPI_CPU_FLAGS          Flags;
614     ACPI_STATUS             Status;
615 
616 
617     ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
618 
619 
620     if (!Address)
621     {
622         return_ACPI_STATUS (AE_BAD_PARAMETER);
623     }
624 
625     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
626     if (ACPI_FAILURE (Status))
627     {
628         return_ACPI_STATUS (Status);
629     }
630 
631     /* Remove the SCI handler with lock */
632 
633     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
634 
635     PrevSciHandler = NULL;
636     NextSciHandler = AcpiGbl_SciHandlerList;
637     while (NextSciHandler)
638     {
639         if (NextSciHandler->Address == Address)
640         {
641             /* Unlink and free the SCI handler info block */
642 
643             if (PrevSciHandler)
644             {
645                 PrevSciHandler->Next = NextSciHandler->Next;
646             }
647             else
648             {
649                 AcpiGbl_SciHandlerList = NextSciHandler->Next;
650             }
651 
652             AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
653             ACPI_FREE (NextSciHandler);
654             goto UnlockAndExit;
655         }
656 
657         PrevSciHandler = NextSciHandler;
658         NextSciHandler = NextSciHandler->Next;
659     }
660 
661     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
662     Status = AE_NOT_EXIST;
663 
664 
665 UnlockAndExit:
666     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
667     return_ACPI_STATUS (Status);
668 }
669 
670 
671 /*******************************************************************************
672  *
673  * FUNCTION:    AcpiInstallGlobalEventHandler
674  *
675  * PARAMETERS:  Handler         - Pointer to the global event handler function
676  *              Context         - Value passed to the handler on each event
677  *
678  * RETURN:      Status
679  *
680  * DESCRIPTION: Saves the pointer to the handler function. The global handler
681  *              is invoked upon each incoming GPE and Fixed Event. It is
682  *              invoked at interrupt level at the time of the event dispatch.
683  *              Can be used to update event counters, etc.
684  *
685  ******************************************************************************/
686 
687 ACPI_STATUS
688 AcpiInstallGlobalEventHandler (
689     ACPI_GBL_EVENT_HANDLER  Handler,
690     void                    *Context)
691 {
692     ACPI_STATUS             Status;
693 
694 
695     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
696 
697 
698     /* Parameter validation */
699 
700     if (!Handler)
701     {
702         return_ACPI_STATUS (AE_BAD_PARAMETER);
703     }
704 
705     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
706     if (ACPI_FAILURE (Status))
707     {
708         return_ACPI_STATUS (Status);
709     }
710 
711     /* Don't allow two handlers. */
712 
713     if (AcpiGbl_GlobalEventHandler)
714     {
715         Status = AE_ALREADY_EXISTS;
716         goto Cleanup;
717     }
718 
719     AcpiGbl_GlobalEventHandler = Handler;
720     AcpiGbl_GlobalEventHandlerContext = Context;
721 
722 
723 Cleanup:
724     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
725     return_ACPI_STATUS (Status);
726 }
727 
728 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
729 
730 
731 /*******************************************************************************
732  *
733  * FUNCTION:    AcpiInstallFixedEventHandler
734  *
735  * PARAMETERS:  Event           - Event type to enable.
736  *              Handler         - Pointer to the handler function for the
737  *                                event
738  *              Context         - Value passed to the handler on each GPE
739  *
740  * RETURN:      Status
741  *
742  * DESCRIPTION: Saves the pointer to the handler function and then enables the
743  *              event.
744  *
745  ******************************************************************************/
746 
747 ACPI_STATUS
748 AcpiInstallFixedEventHandler (
749     UINT32                  Event,
750     ACPI_EVENT_HANDLER      Handler,
751     void                    *Context)
752 {
753     ACPI_STATUS             Status;
754 
755 
756     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
757 
758 
759     /* Parameter validation */
760 
761     if (Event > ACPI_EVENT_MAX)
762     {
763         return_ACPI_STATUS (AE_BAD_PARAMETER);
764     }
765 
766     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
767     if (ACPI_FAILURE (Status))
768     {
769         return_ACPI_STATUS (Status);
770     }
771 
772     /* Do not allow multiple handlers */
773 
774     if (AcpiGbl_FixedEventHandlers[Event].Handler)
775     {
776         Status = AE_ALREADY_EXISTS;
777         goto Cleanup;
778     }
779 
780     /* Install the handler before enabling the event */
781 
782     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
783     AcpiGbl_FixedEventHandlers[Event].Context = Context;
784 
785     Status = AcpiEnableEvent (Event, 0);
786     if (ACPI_FAILURE (Status))
787     {
788         ACPI_WARNING ((AE_INFO,
789             "Could not enable fixed event - %s (%u)",
790             AcpiUtGetEventName (Event), Event));
791 
792         /* Remove the handler */
793 
794         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
795         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
796     }
797     else
798     {
799         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
800             "Enabled fixed event %s (%X), Handler=%p\n",
801             AcpiUtGetEventName (Event), Event, Handler));
802     }
803 
804 
805 Cleanup:
806     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
807     return_ACPI_STATUS (Status);
808 }
809 
810 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
811 
812 
813 /*******************************************************************************
814  *
815  * FUNCTION:    AcpiRemoveFixedEventHandler
816  *
817  * PARAMETERS:  Event           - Event type to disable.
818  *              Handler         - Address of the handler
819  *
820  * RETURN:      Status
821  *
822  * DESCRIPTION: Disables the event and unregisters the event handler.
823  *
824  ******************************************************************************/
825 
826 ACPI_STATUS
827 AcpiRemoveFixedEventHandler (
828     UINT32                  Event,
829     ACPI_EVENT_HANDLER      Handler)
830 {
831     ACPI_STATUS             Status = AE_OK;
832 
833 
834     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
835 
836 
837     /* Parameter validation */
838 
839     if (Event > ACPI_EVENT_MAX)
840     {
841         return_ACPI_STATUS (AE_BAD_PARAMETER);
842     }
843 
844     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
845     if (ACPI_FAILURE (Status))
846     {
847         return_ACPI_STATUS (Status);
848     }
849 
850     /* Disable the event before removing the handler */
851 
852     Status = AcpiDisableEvent (Event, 0);
853 
854     /* Always Remove the handler */
855 
856     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
857     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
858 
859     if (ACPI_FAILURE (Status))
860     {
861         ACPI_WARNING ((AE_INFO,
862             "Could not disable fixed event - %s (%u)",
863             AcpiUtGetEventName (Event), Event));
864     }
865     else
866     {
867         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
868             "Disabled fixed event - %s (%X)\n",
869             AcpiUtGetEventName (Event), Event));
870     }
871 
872     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
873     return_ACPI_STATUS (Status);
874 }
875 
876 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
877 
878 
879 /*******************************************************************************
880  *
881  * FUNCTION:    AcpiInstallGpeHandler
882  *
883  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
884  *                                defined GPEs)
885  *              GpeNumber       - The GPE number within the GPE block
886  *              Type            - Whether this GPE should be treated as an
887  *                                edge- or level-triggered interrupt.
888  *              Address         - Address of the handler
889  *              Context         - Value passed to the handler on each GPE
890  *
891  * RETURN:      Status
892  *
893  * DESCRIPTION: Install a handler for a General Purpose Event.
894  *
895  ******************************************************************************/
896 
897 ACPI_STATUS
898 AcpiInstallGpeHandler (
899     ACPI_HANDLE             GpeDevice,
900     UINT32                  GpeNumber,
901     UINT32                  Type,
902     ACPI_GPE_HANDLER        Address,
903     void                    *Context)
904 {
905     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
906     ACPI_GPE_HANDLER_INFO   *Handler;
907     ACPI_STATUS             Status;
908     ACPI_CPU_FLAGS          Flags;
909 
910 
911     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
912 
913 
914     /* Parameter validation */
915 
916     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
917     {
918         return_ACPI_STATUS (AE_BAD_PARAMETER);
919     }
920 
921     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
922     if (ACPI_FAILURE (Status))
923     {
924         return_ACPI_STATUS (Status);
925     }
926 
927     /* Allocate and init handler object (before lock) */
928 
929     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
930     if (!Handler)
931     {
932         Status = AE_NO_MEMORY;
933         goto UnlockAndExit;
934     }
935 
936     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
937 
938     /* Ensure that we have a valid GPE number */
939 
940     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
941     if (!GpeEventInfo)
942     {
943         Status = AE_BAD_PARAMETER;
944         goto FreeAndExit;
945     }
946 
947     /* Make sure that there isn't a handler there already */
948 
949     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
950             ACPI_GPE_DISPATCH_HANDLER)
951     {
952         Status = AE_ALREADY_EXISTS;
953         goto FreeAndExit;
954     }
955 
956     Handler->Address = Address;
957     Handler->Context = Context;
958     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
959     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
960         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
961 
962     /*
963      * If the GPE is associated with a method, it may have been enabled
964      * automatically during initialization, in which case it has to be
965      * disabled now to avoid spurious execution of the handler.
966      */
967     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
968          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
969         GpeEventInfo->RuntimeCount)
970     {
971         Handler->OriginallyEnabled = TRUE;
972         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
973 
974         /* Sanity check of original type against new type */
975 
976         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
977         {
978             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
979         }
980     }
981 
982     /* Install the handler */
983 
984     GpeEventInfo->Dispatch.Handler = Handler;
985 
986     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
987 
988     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
989     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
990 
991     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
992 
993 
994 UnlockAndExit:
995     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
996     return_ACPI_STATUS (Status);
997 
998 FreeAndExit:
999     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1000     ACPI_FREE (Handler);
1001     goto UnlockAndExit;
1002 }
1003 
1004 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
1005 
1006 
1007 /*******************************************************************************
1008  *
1009  * FUNCTION:    AcpiRemoveGpeHandler
1010  *
1011  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
1012  *                                defined GPEs)
1013  *              GpeNumber       - The event to remove a handler
1014  *              Address         - Address of the handler
1015  *
1016  * RETURN:      Status
1017  *
1018  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
1019  *
1020  ******************************************************************************/
1021 
1022 ACPI_STATUS
1023 AcpiRemoveGpeHandler (
1024     ACPI_HANDLE             GpeDevice,
1025     UINT32                  GpeNumber,
1026     ACPI_GPE_HANDLER        Address)
1027 {
1028     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
1029     ACPI_GPE_HANDLER_INFO   *Handler;
1030     ACPI_STATUS             Status;
1031     ACPI_CPU_FLAGS          Flags;
1032 
1033 
1034     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
1035 
1036 
1037     /* Parameter validation */
1038 
1039     if (!Address)
1040     {
1041         return_ACPI_STATUS (AE_BAD_PARAMETER);
1042     }
1043 
1044     /* Make sure all deferred GPE tasks are completed */
1045 
1046     AcpiOsWaitEventsComplete ();
1047 
1048     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1049     if (ACPI_FAILURE (Status))
1050     {
1051         return_ACPI_STATUS (Status);
1052     }
1053 
1054     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1055 
1056     /* Ensure that we have a valid GPE number */
1057 
1058     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1059     if (!GpeEventInfo)
1060     {
1061         Status = AE_BAD_PARAMETER;
1062         goto UnlockAndExit;
1063     }
1064 
1065     /* Make sure that a handler is indeed installed */
1066 
1067     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
1068             ACPI_GPE_DISPATCH_HANDLER)
1069     {
1070         Status = AE_NOT_EXIST;
1071         goto UnlockAndExit;
1072     }
1073 
1074     /* Make sure that the installed handler is the same */
1075 
1076     if (GpeEventInfo->Dispatch.Handler->Address != Address)
1077     {
1078         Status = AE_BAD_PARAMETER;
1079         goto UnlockAndExit;
1080     }
1081 
1082     /* Remove the handler */
1083 
1084     Handler = GpeEventInfo->Dispatch.Handler;
1085 
1086     /* Restore Method node (if any), set dispatch flags */
1087 
1088     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1089     GpeEventInfo->Flags &=
1090         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1091     GpeEventInfo->Flags |= Handler->OriginalFlags;
1092 
1093     /*
1094      * If the GPE was previously associated with a method and it was
1095      * enabled, it should be enabled at this point to restore the
1096      * post-initialization configuration.
1097      */
1098     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
1099         Handler->OriginallyEnabled)
1100     {
1101         (void) AcpiEvAddGpeReference (GpeEventInfo);
1102     }
1103 
1104     /* Now we can free the handler object */
1105 
1106     ACPI_FREE (Handler);
1107 
1108 
1109 UnlockAndExit:
1110     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1111     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1112     return_ACPI_STATUS (Status);
1113 }
1114 
1115 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1116 
1117 
1118 /*******************************************************************************
1119  *
1120  * FUNCTION:    AcpiAcquireGlobalLock
1121  *
1122  * PARAMETERS:  Timeout         - How long the caller is willing to wait
1123  *              Handle          - Where the handle to the lock is returned
1124  *                                (if acquired)
1125  *
1126  * RETURN:      Status
1127  *
1128  * DESCRIPTION: Acquire the ACPI Global Lock
1129  *
1130  * Note: Allows callers with the same thread ID to acquire the global lock
1131  * multiple times. In other words, externally, the behavior of the global lock
1132  * is identical to an AML mutex. On the first acquire, a new handle is
1133  * returned. On any subsequent calls to acquire by the same thread, the same
1134  * handle is returned.
1135  *
1136  ******************************************************************************/
1137 
1138 ACPI_STATUS
1139 AcpiAcquireGlobalLock (
1140     UINT16                  Timeout,
1141     UINT32                  *Handle)
1142 {
1143     ACPI_STATUS             Status;
1144 
1145 
1146     if (!Handle)
1147     {
1148         return (AE_BAD_PARAMETER);
1149     }
1150 
1151     /* Must lock interpreter to prevent race conditions */
1152 
1153     AcpiExEnterInterpreter ();
1154 
1155     Status = AcpiExAcquireMutexObject (Timeout,
1156                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1157 
1158     if (ACPI_SUCCESS (Status))
1159     {
1160         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1161 
1162         *Handle = AcpiGbl_GlobalLockHandle;
1163     }
1164 
1165     AcpiExExitInterpreter ();
1166     return (Status);
1167 }
1168 
1169 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1170 
1171 
1172 /*******************************************************************************
1173  *
1174  * FUNCTION:    AcpiReleaseGlobalLock
1175  *
1176  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1177  *
1178  * RETURN:      Status
1179  *
1180  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1181  *
1182  ******************************************************************************/
1183 
1184 ACPI_STATUS
1185 AcpiReleaseGlobalLock (
1186     UINT32                  Handle)
1187 {
1188     ACPI_STATUS             Status;
1189 
1190 
1191     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1192     {
1193         return (AE_NOT_ACQUIRED);
1194     }
1195 
1196     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1197     return (Status);
1198 }
1199 
1200 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1201 
1202 #endif /* !ACPI_REDUCED_HARDWARE */
1203