xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/events/evxface.c (revision 644fa5a93845dc4a1bc155f1fd0f94ebdf0b47bc)
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 - 2014, 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 #define EXPORT_ACPI_INTERFACES
119 
120 #include "acpi.h"
121 #include "accommon.h"
122 #include "acnamesp.h"
123 #include "acevents.h"
124 #include "acinterp.h"
125 
126 #define _COMPONENT          ACPI_EVENTS
127         ACPI_MODULE_NAME    ("evxface")
128 
129 
130 /*******************************************************************************
131  *
132  * FUNCTION:    AcpiInstallNotifyHandler
133  *
134  * PARAMETERS:  Device          - The device for which notifies will be handled
135  *              HandlerType     - The type of handler:
136  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
137  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
138  *                                  ACPI_ALL_NOTIFY:    Both System and Device
139  *              Handler         - Address of the handler
140  *              Context         - Value passed to the handler on each GPE
141  *
142  * RETURN:      Status
143  *
144  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
145  *              ThermalZone, or Processor object.
146  *
147  * NOTES:       The Root namespace object may have only one handler for each
148  *              type of notify (System/Device). Device/Thermal/Processor objects
149  *              may have one device notify handler, and multiple system notify
150  *              handlers.
151  *
152  ******************************************************************************/
153 
154 ACPI_STATUS
155 AcpiInstallNotifyHandler (
156     ACPI_HANDLE             Device,
157     UINT32                  HandlerType,
158     ACPI_NOTIFY_HANDLER     Handler,
159     void                    *Context)
160 {
161     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
162     ACPI_OPERAND_OBJECT     *ObjDesc;
163     ACPI_OPERAND_OBJECT     *HandlerObj;
164     ACPI_STATUS             Status;
165     UINT32                  i;
166 
167 
168     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
169 
170 
171     /* Parameter validation */
172 
173     if ((!Device) || (!Handler) || (!HandlerType) ||
174         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
175     {
176         return_ACPI_STATUS (AE_BAD_PARAMETER);
177     }
178 
179     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
180     if (ACPI_FAILURE (Status))
181     {
182         return_ACPI_STATUS (Status);
183     }
184 
185     /*
186      * Root Object:
187      * Registering a notify handler on the root object indicates that the
188      * caller wishes to receive notifications for all objects. Note that
189      * only one global handler can be registered per notify type.
190      * Ensure that a handler is not already installed.
191      */
192     if (Device == ACPI_ROOT_OBJECT)
193     {
194         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
195         {
196             if (HandlerType & (i+1))
197             {
198                 if (AcpiGbl_GlobalNotify[i].Handler)
199                 {
200                     Status = AE_ALREADY_EXISTS;
201                     goto UnlockAndExit;
202                 }
203 
204                 AcpiGbl_GlobalNotify[i].Handler = Handler;
205                 AcpiGbl_GlobalNotify[i].Context = Context;
206             }
207         }
208 
209         goto UnlockAndExit; /* Global notify handler installed, all done */
210     }
211 
212     /*
213      * All Other Objects:
214      * Caller will only receive notifications specific to the target
215      * object. Note that only certain object types are allowed to
216      * receive notifications.
217      */
218 
219     /* Are Notifies allowed on this object? */
220 
221     if (!AcpiEvIsNotifyObject (Node))
222     {
223         Status = AE_TYPE;
224         goto UnlockAndExit;
225     }
226 
227     /* Check for an existing internal object, might not exist */
228 
229     ObjDesc = AcpiNsGetAttachedObject (Node);
230     if (!ObjDesc)
231     {
232         /* Create a new object */
233 
234         ObjDesc = AcpiUtCreateInternalObject (Node->Type);
235         if (!ObjDesc)
236         {
237             Status = AE_NO_MEMORY;
238             goto UnlockAndExit;
239         }
240 
241         /* Attach new object to the Node, remove local reference */
242 
243         Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
244         AcpiUtRemoveReference (ObjDesc);
245         if (ACPI_FAILURE (Status))
246         {
247             goto UnlockAndExit;
248         }
249     }
250 
251     /* Ensure that the handler is not already installed in the lists */
252 
253     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
254     {
255         if (HandlerType & (i+1))
256         {
257             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
258             while (HandlerObj)
259             {
260                 if (HandlerObj->Notify.Handler == Handler)
261                 {
262                     Status = AE_ALREADY_EXISTS;
263                     goto UnlockAndExit;
264                 }
265 
266                 HandlerObj = HandlerObj->Notify.Next[i];
267             }
268         }
269     }
270 
271     /* Create and populate a new notify handler object */
272 
273     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
274     if (!HandlerObj)
275     {
276         Status = AE_NO_MEMORY;
277         goto UnlockAndExit;
278     }
279 
280     HandlerObj->Notify.Node = Node;
281     HandlerObj->Notify.HandlerType = HandlerType;
282     HandlerObj->Notify.Handler = Handler;
283     HandlerObj->Notify.Context = Context;
284 
285     /* Install the handler at the list head(s) */
286 
287     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
288     {
289         if (HandlerType & (i+1))
290         {
291             HandlerObj->Notify.Next[i] =
292                 ObjDesc->CommonNotify.NotifyList[i];
293 
294             ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
295         }
296     }
297 
298     /* Add an extra reference if handler was installed in both lists */
299 
300     if (HandlerType == ACPI_ALL_NOTIFY)
301     {
302         AcpiUtAddReference (HandlerObj);
303     }
304 
305 
306 UnlockAndExit:
307     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
308     return_ACPI_STATUS (Status);
309 }
310 
311 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
312 
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    AcpiRemoveNotifyHandler
317  *
318  * PARAMETERS:  Device          - The device for which the handler is installed
319  *              HandlerType     - The type of handler:
320  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
321  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
322  *                                  ACPI_ALL_NOTIFY:    Both System and Device
323  *              Handler         - Address of the handler
324  *
325  * RETURN:      Status
326  *
327  * DESCRIPTION: Remove a handler for notifies on an ACPI device
328  *
329  ******************************************************************************/
330 
331 ACPI_STATUS
332 AcpiRemoveNotifyHandler (
333     ACPI_HANDLE             Device,
334     UINT32                  HandlerType,
335     ACPI_NOTIFY_HANDLER     Handler)
336 {
337     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
338     ACPI_OPERAND_OBJECT     *ObjDesc;
339     ACPI_OPERAND_OBJECT     *HandlerObj;
340     ACPI_OPERAND_OBJECT     *PreviousHandlerObj;
341     ACPI_STATUS             Status = AE_OK;
342     UINT32                  i;
343 
344 
345     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
346 
347 
348     /* Parameter validation */
349 
350     if ((!Device) || (!Handler) || (!HandlerType) ||
351         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
352     {
353         return_ACPI_STATUS (AE_BAD_PARAMETER);
354     }
355 
356     /* Root Object. Global handlers are removed here */
357 
358     if (Device == ACPI_ROOT_OBJECT)
359     {
360         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
361         {
362             if (HandlerType & (i+1))
363             {
364                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
365                 if (ACPI_FAILURE (Status))
366                 {
367                     return_ACPI_STATUS (Status);
368                 }
369 
370                 if (!AcpiGbl_GlobalNotify[i].Handler ||
371                     (AcpiGbl_GlobalNotify[i].Handler != Handler))
372                 {
373                     Status = AE_NOT_EXIST;
374                     goto UnlockAndExit;
375                 }
376 
377                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
378                     "Removing global notify handler\n"));
379 
380                 AcpiGbl_GlobalNotify[i].Handler = NULL;
381                 AcpiGbl_GlobalNotify[i].Context = NULL;
382 
383                 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
384 
385                 /* Make sure all deferred notify tasks are completed */
386 
387                 AcpiOsWaitEventsComplete ();
388             }
389         }
390 
391         return_ACPI_STATUS (AE_OK);
392     }
393 
394     /* All other objects: Are Notifies allowed on this object? */
395 
396     if (!AcpiEvIsNotifyObject (Node))
397     {
398         return_ACPI_STATUS (AE_TYPE);
399     }
400 
401     /* Must have an existing internal object */
402 
403     ObjDesc = AcpiNsGetAttachedObject (Node);
404     if (!ObjDesc)
405     {
406         return_ACPI_STATUS (AE_NOT_EXIST);
407     }
408 
409     /* Internal object exists. Find the handler and remove it */
410 
411     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
412     {
413         if (HandlerType & (i+1))
414         {
415             Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
416             if (ACPI_FAILURE (Status))
417             {
418                 return_ACPI_STATUS (Status);
419             }
420 
421             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
422             PreviousHandlerObj = NULL;
423 
424             /* Attempt to find the handler in the handler list */
425 
426             while (HandlerObj &&
427                   (HandlerObj->Notify.Handler != Handler))
428             {
429                 PreviousHandlerObj = HandlerObj;
430                 HandlerObj = HandlerObj->Notify.Next[i];
431             }
432 
433             if (!HandlerObj)
434             {
435                 Status = AE_NOT_EXIST;
436                 goto UnlockAndExit;
437             }
438 
439             /* Remove the handler object from the list */
440 
441             if (PreviousHandlerObj) /* Handler is not at the list head */
442             {
443                 PreviousHandlerObj->Notify.Next[i] =
444                     HandlerObj->Notify.Next[i];
445             }
446             else /* Handler is at the list head */
447             {
448                 ObjDesc->CommonNotify.NotifyList[i] =
449                     HandlerObj->Notify.Next[i];
450             }
451 
452             (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
453 
454             /* Make sure all deferred notify tasks are completed */
455 
456             AcpiOsWaitEventsComplete ();
457             AcpiUtRemoveReference (HandlerObj);
458         }
459     }
460 
461     return_ACPI_STATUS (Status);
462 
463 
464 UnlockAndExit:
465     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
466     return_ACPI_STATUS (Status);
467 }
468 
469 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
470 
471 
472 /*******************************************************************************
473  *
474  * FUNCTION:    AcpiInstallExceptionHandler
475  *
476  * PARAMETERS:  Handler         - Pointer to the handler function for the
477  *                                event
478  *
479  * RETURN:      Status
480  *
481  * DESCRIPTION: Saves the pointer to the handler function
482  *
483  ******************************************************************************/
484 
485 ACPI_STATUS
486 AcpiInstallExceptionHandler (
487     ACPI_EXCEPTION_HANDLER  Handler)
488 {
489     ACPI_STATUS             Status;
490 
491 
492     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
493 
494 
495     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
496     if (ACPI_FAILURE (Status))
497     {
498         return_ACPI_STATUS (Status);
499     }
500 
501     /* Don't allow two handlers. */
502 
503     if (AcpiGbl_ExceptionHandler)
504     {
505         Status = AE_ALREADY_EXISTS;
506         goto Cleanup;
507     }
508 
509     /* Install the handler */
510 
511     AcpiGbl_ExceptionHandler = Handler;
512 
513 Cleanup:
514     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
515     return_ACPI_STATUS (Status);
516 }
517 
518 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
519 
520 
521 #if (!ACPI_REDUCED_HARDWARE)
522 /*******************************************************************************
523  *
524  * FUNCTION:    AcpiInstallSciHandler
525  *
526  * PARAMETERS:  Address             - Address of the handler
527  *              Context             - Value passed to the handler on each SCI
528  *
529  * RETURN:      Status
530  *
531  * DESCRIPTION: Install a handler for a System Control Interrupt.
532  *
533  ******************************************************************************/
534 
535 ACPI_STATUS
536 AcpiInstallSciHandler (
537     ACPI_SCI_HANDLER        Address,
538     void                    *Context)
539 {
540     ACPI_SCI_HANDLER_INFO   *NewSciHandler;
541     ACPI_SCI_HANDLER_INFO   *SciHandler;
542     ACPI_CPU_FLAGS          Flags;
543     ACPI_STATUS             Status;
544 
545 
546     ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
547 
548 
549     if (!Address)
550     {
551         return_ACPI_STATUS (AE_BAD_PARAMETER);
552     }
553 
554     /* Allocate and init a handler object */
555 
556     NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
557     if (!NewSciHandler)
558     {
559         return_ACPI_STATUS (AE_NO_MEMORY);
560     }
561 
562     NewSciHandler->Address = Address;
563     NewSciHandler->Context = Context;
564 
565     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
566     if (ACPI_FAILURE (Status))
567     {
568         goto Exit;
569     }
570 
571     /* Lock list during installation */
572 
573     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
574     SciHandler = AcpiGbl_SciHandlerList;
575 
576     /* Ensure handler does not already exist */
577 
578     while (SciHandler)
579     {
580         if (Address == SciHandler->Address)
581         {
582             Status = AE_ALREADY_EXISTS;
583             goto UnlockAndExit;
584         }
585 
586         SciHandler = SciHandler->Next;
587     }
588 
589     /* Install the new handler into the global list (at head) */
590 
591     NewSciHandler->Next = AcpiGbl_SciHandlerList;
592     AcpiGbl_SciHandlerList = NewSciHandler;
593 
594 
595 UnlockAndExit:
596 
597     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
598     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
599 
600 Exit:
601     if (ACPI_FAILURE (Status))
602     {
603         ACPI_FREE (NewSciHandler);
604     }
605     return_ACPI_STATUS (Status);
606 }
607 
608 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
609 
610 
611 /*******************************************************************************
612  *
613  * FUNCTION:    AcpiRemoveSciHandler
614  *
615  * PARAMETERS:  Address             - Address of the handler
616  *
617  * RETURN:      Status
618  *
619  * DESCRIPTION: Remove a handler for a System Control Interrupt.
620  *
621  ******************************************************************************/
622 
623 ACPI_STATUS
624 AcpiRemoveSciHandler (
625     ACPI_SCI_HANDLER        Address)
626 {
627     ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
628     ACPI_SCI_HANDLER_INFO   *NextSciHandler;
629     ACPI_CPU_FLAGS          Flags;
630     ACPI_STATUS             Status;
631 
632 
633     ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
634 
635 
636     if (!Address)
637     {
638         return_ACPI_STATUS (AE_BAD_PARAMETER);
639     }
640 
641     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
642     if (ACPI_FAILURE (Status))
643     {
644         return_ACPI_STATUS (Status);
645     }
646 
647     /* Remove the SCI handler with lock */
648 
649     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
650 
651     PrevSciHandler = NULL;
652     NextSciHandler = AcpiGbl_SciHandlerList;
653     while (NextSciHandler)
654     {
655         if (NextSciHandler->Address == Address)
656         {
657             /* Unlink and free the SCI handler info block */
658 
659             if (PrevSciHandler)
660             {
661                 PrevSciHandler->Next = NextSciHandler->Next;
662             }
663             else
664             {
665                 AcpiGbl_SciHandlerList = NextSciHandler->Next;
666             }
667 
668             AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
669             ACPI_FREE (NextSciHandler);
670             goto UnlockAndExit;
671         }
672 
673         PrevSciHandler = NextSciHandler;
674         NextSciHandler = NextSciHandler->Next;
675     }
676 
677     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
678     Status = AE_NOT_EXIST;
679 
680 
681 UnlockAndExit:
682     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
683     return_ACPI_STATUS (Status);
684 }
685 
686 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
687 
688 
689 /*******************************************************************************
690  *
691  * FUNCTION:    AcpiInstallGlobalEventHandler
692  *
693  * PARAMETERS:  Handler         - Pointer to the global event handler function
694  *              Context         - Value passed to the handler on each event
695  *
696  * RETURN:      Status
697  *
698  * DESCRIPTION: Saves the pointer to the handler function. The global handler
699  *              is invoked upon each incoming GPE and Fixed Event. It is
700  *              invoked at interrupt level at the time of the event dispatch.
701  *              Can be used to update event counters, etc.
702  *
703  ******************************************************************************/
704 
705 ACPI_STATUS
706 AcpiInstallGlobalEventHandler (
707     ACPI_GBL_EVENT_HANDLER  Handler,
708     void                    *Context)
709 {
710     ACPI_STATUS             Status;
711 
712 
713     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
714 
715 
716     /* Parameter validation */
717 
718     if (!Handler)
719     {
720         return_ACPI_STATUS (AE_BAD_PARAMETER);
721     }
722 
723     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
724     if (ACPI_FAILURE (Status))
725     {
726         return_ACPI_STATUS (Status);
727     }
728 
729     /* Don't allow two handlers. */
730 
731     if (AcpiGbl_GlobalEventHandler)
732     {
733         Status = AE_ALREADY_EXISTS;
734         goto Cleanup;
735     }
736 
737     AcpiGbl_GlobalEventHandler = Handler;
738     AcpiGbl_GlobalEventHandlerContext = Context;
739 
740 
741 Cleanup:
742     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
743     return_ACPI_STATUS (Status);
744 }
745 
746 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
747 
748 
749 /*******************************************************************************
750  *
751  * FUNCTION:    AcpiInstallFixedEventHandler
752  *
753  * PARAMETERS:  Event           - Event type to enable.
754  *              Handler         - Pointer to the handler function for the
755  *                                event
756  *              Context         - Value passed to the handler on each GPE
757  *
758  * RETURN:      Status
759  *
760  * DESCRIPTION: Saves the pointer to the handler function and then enables the
761  *              event.
762  *
763  ******************************************************************************/
764 
765 ACPI_STATUS
766 AcpiInstallFixedEventHandler (
767     UINT32                  Event,
768     ACPI_EVENT_HANDLER      Handler,
769     void                    *Context)
770 {
771     ACPI_STATUS             Status;
772 
773 
774     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
775 
776 
777     /* Parameter validation */
778 
779     if (Event > ACPI_EVENT_MAX)
780     {
781         return_ACPI_STATUS (AE_BAD_PARAMETER);
782     }
783 
784     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
785     if (ACPI_FAILURE (Status))
786     {
787         return_ACPI_STATUS (Status);
788     }
789 
790     /* Do not allow multiple handlers */
791 
792     if (AcpiGbl_FixedEventHandlers[Event].Handler)
793     {
794         Status = AE_ALREADY_EXISTS;
795         goto Cleanup;
796     }
797 
798     /* Install the handler before enabling the event */
799 
800     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
801     AcpiGbl_FixedEventHandlers[Event].Context = Context;
802 
803     Status = AcpiEnableEvent (Event, 0);
804     if (ACPI_FAILURE (Status))
805     {
806         ACPI_WARNING ((AE_INFO,
807             "Could not enable fixed event - %s (%u)",
808             AcpiUtGetEventName (Event), Event));
809 
810         /* Remove the handler */
811 
812         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
813         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
814     }
815     else
816     {
817         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
818             "Enabled fixed event %s (%X), Handler=%p\n",
819             AcpiUtGetEventName (Event), Event, Handler));
820     }
821 
822 
823 Cleanup:
824     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
825     return_ACPI_STATUS (Status);
826 }
827 
828 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
829 
830 
831 /*******************************************************************************
832  *
833  * FUNCTION:    AcpiRemoveFixedEventHandler
834  *
835  * PARAMETERS:  Event           - Event type to disable.
836  *              Handler         - Address of the handler
837  *
838  * RETURN:      Status
839  *
840  * DESCRIPTION: Disables the event and unregisters the event handler.
841  *
842  ******************************************************************************/
843 
844 ACPI_STATUS
845 AcpiRemoveFixedEventHandler (
846     UINT32                  Event,
847     ACPI_EVENT_HANDLER      Handler)
848 {
849     ACPI_STATUS             Status = AE_OK;
850 
851 
852     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
853 
854 
855     /* Parameter validation */
856 
857     if (Event > ACPI_EVENT_MAX)
858     {
859         return_ACPI_STATUS (AE_BAD_PARAMETER);
860     }
861 
862     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
863     if (ACPI_FAILURE (Status))
864     {
865         return_ACPI_STATUS (Status);
866     }
867 
868     /* Disable the event before removing the handler */
869 
870     Status = AcpiDisableEvent (Event, 0);
871 
872     /* Always Remove the handler */
873 
874     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
875     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
876 
877     if (ACPI_FAILURE (Status))
878     {
879         ACPI_WARNING ((AE_INFO,
880             "Could not disable fixed event - %s (%u)",
881             AcpiUtGetEventName (Event), Event));
882     }
883     else
884     {
885         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
886             "Disabled fixed event - %s (%X)\n",
887             AcpiUtGetEventName (Event), Event));
888     }
889 
890     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
891     return_ACPI_STATUS (Status);
892 }
893 
894 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
895 
896 
897 /*******************************************************************************
898  *
899  * FUNCTION:    AcpiInstallGpeHandler
900  *
901  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
902  *                                defined GPEs)
903  *              GpeNumber       - The GPE number within the GPE block
904  *              Type            - Whether this GPE should be treated as an
905  *                                edge- or level-triggered interrupt.
906  *              Address         - Address of the handler
907  *              Context         - Value passed to the handler on each GPE
908  *
909  * RETURN:      Status
910  *
911  * DESCRIPTION: Install a handler for a General Purpose Event.
912  *
913  ******************************************************************************/
914 
915 ACPI_STATUS
916 AcpiInstallGpeHandler (
917     ACPI_HANDLE             GpeDevice,
918     UINT32                  GpeNumber,
919     UINT32                  Type,
920     ACPI_GPE_HANDLER        Address,
921     void                    *Context)
922 {
923     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
924     ACPI_GPE_HANDLER_INFO   *Handler;
925     ACPI_STATUS             Status;
926     ACPI_CPU_FLAGS          Flags;
927 
928 
929     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
930 
931 
932     /* Parameter validation */
933 
934     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
935     {
936         return_ACPI_STATUS (AE_BAD_PARAMETER);
937     }
938 
939     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
940     if (ACPI_FAILURE (Status))
941     {
942         return_ACPI_STATUS (Status);
943     }
944 
945     /* Allocate and init handler object (before lock) */
946 
947     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
948     if (!Handler)
949     {
950         Status = AE_NO_MEMORY;
951         goto UnlockAndExit;
952     }
953 
954     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
955 
956     /* Ensure that we have a valid GPE number */
957 
958     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
959     if (!GpeEventInfo)
960     {
961         Status = AE_BAD_PARAMETER;
962         goto FreeAndExit;
963     }
964 
965     /* Make sure that there isn't a handler there already */
966 
967     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
968             ACPI_GPE_DISPATCH_HANDLER)
969     {
970         Status = AE_ALREADY_EXISTS;
971         goto FreeAndExit;
972     }
973 
974     Handler->Address = Address;
975     Handler->Context = Context;
976     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
977     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
978         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
979 
980     /*
981      * If the GPE is associated with a method, it may have been enabled
982      * automatically during initialization, in which case it has to be
983      * disabled now to avoid spurious execution of the handler.
984      */
985     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
986          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
987         GpeEventInfo->RuntimeCount)
988     {
989         Handler->OriginallyEnabled = TRUE;
990         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
991 
992         /* Sanity check of original type against new type */
993 
994         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
995         {
996             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
997         }
998     }
999 
1000     /* Install the handler */
1001 
1002     GpeEventInfo->Dispatch.Handler = Handler;
1003 
1004     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
1005 
1006     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1007     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
1008 
1009     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1010 
1011 
1012 UnlockAndExit:
1013     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1014     return_ACPI_STATUS (Status);
1015 
1016 FreeAndExit:
1017     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1018     ACPI_FREE (Handler);
1019     goto UnlockAndExit;
1020 }
1021 
1022 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
1023 
1024 
1025 /*******************************************************************************
1026  *
1027  * FUNCTION:    AcpiRemoveGpeHandler
1028  *
1029  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
1030  *                                defined GPEs)
1031  *              GpeNumber       - The event to remove a handler
1032  *              Address         - Address of the handler
1033  *
1034  * RETURN:      Status
1035  *
1036  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
1037  *
1038  ******************************************************************************/
1039 
1040 ACPI_STATUS
1041 AcpiRemoveGpeHandler (
1042     ACPI_HANDLE             GpeDevice,
1043     UINT32                  GpeNumber,
1044     ACPI_GPE_HANDLER        Address)
1045 {
1046     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
1047     ACPI_GPE_HANDLER_INFO   *Handler;
1048     ACPI_STATUS             Status;
1049     ACPI_CPU_FLAGS          Flags;
1050 
1051 
1052     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
1053 
1054 
1055     /* Parameter validation */
1056 
1057     if (!Address)
1058     {
1059         return_ACPI_STATUS (AE_BAD_PARAMETER);
1060     }
1061 
1062     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1063     if (ACPI_FAILURE (Status))
1064     {
1065         return_ACPI_STATUS (Status);
1066     }
1067 
1068     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1069 
1070     /* Ensure that we have a valid GPE number */
1071 
1072     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1073     if (!GpeEventInfo)
1074     {
1075         Status = AE_BAD_PARAMETER;
1076         goto UnlockAndExit;
1077     }
1078 
1079     /* Make sure that a handler is indeed installed */
1080 
1081     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
1082             ACPI_GPE_DISPATCH_HANDLER)
1083     {
1084         Status = AE_NOT_EXIST;
1085         goto UnlockAndExit;
1086     }
1087 
1088     /* Make sure that the installed handler is the same */
1089 
1090     if (GpeEventInfo->Dispatch.Handler->Address != Address)
1091     {
1092         Status = AE_BAD_PARAMETER;
1093         goto UnlockAndExit;
1094     }
1095 
1096     /* Remove the handler */
1097 
1098     Handler = GpeEventInfo->Dispatch.Handler;
1099 
1100     /* Restore Method node (if any), set dispatch flags */
1101 
1102     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1103     GpeEventInfo->Flags &=
1104         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1105     GpeEventInfo->Flags |= Handler->OriginalFlags;
1106 
1107     /*
1108      * If the GPE was previously associated with a method and it was
1109      * enabled, it should be enabled at this point to restore the
1110      * post-initialization configuration.
1111      */
1112     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
1113         Handler->OriginallyEnabled)
1114     {
1115         (void) AcpiEvAddGpeReference (GpeEventInfo);
1116     }
1117 
1118     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1119     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1120 
1121     /* Make sure all deferred GPE tasks are completed */
1122 
1123     AcpiOsWaitEventsComplete ();
1124 
1125     /* Now we can free the handler object */
1126 
1127     ACPI_FREE (Handler);
1128     return_ACPI_STATUS (Status);
1129 
1130 UnlockAndExit:
1131     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1132     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1133     return_ACPI_STATUS (Status);
1134 }
1135 
1136 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1137 
1138 
1139 /*******************************************************************************
1140  *
1141  * FUNCTION:    AcpiAcquireGlobalLock
1142  *
1143  * PARAMETERS:  Timeout         - How long the caller is willing to wait
1144  *              Handle          - Where the handle to the lock is returned
1145  *                                (if acquired)
1146  *
1147  * RETURN:      Status
1148  *
1149  * DESCRIPTION: Acquire the ACPI Global Lock
1150  *
1151  * Note: Allows callers with the same thread ID to acquire the global lock
1152  * multiple times. In other words, externally, the behavior of the global lock
1153  * is identical to an AML mutex. On the first acquire, a new handle is
1154  * returned. On any subsequent calls to acquire by the same thread, the same
1155  * handle is returned.
1156  *
1157  ******************************************************************************/
1158 
1159 ACPI_STATUS
1160 AcpiAcquireGlobalLock (
1161     UINT16                  Timeout,
1162     UINT32                  *Handle)
1163 {
1164     ACPI_STATUS             Status;
1165 
1166 
1167     if (!Handle)
1168     {
1169         return (AE_BAD_PARAMETER);
1170     }
1171 
1172     /* Must lock interpreter to prevent race conditions */
1173 
1174     AcpiExEnterInterpreter ();
1175 
1176     Status = AcpiExAcquireMutexObject (Timeout,
1177                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1178 
1179     if (ACPI_SUCCESS (Status))
1180     {
1181         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1182 
1183         *Handle = AcpiGbl_GlobalLockHandle;
1184     }
1185 
1186     AcpiExExitInterpreter ();
1187     return (Status);
1188 }
1189 
1190 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1191 
1192 
1193 /*******************************************************************************
1194  *
1195  * FUNCTION:    AcpiReleaseGlobalLock
1196  *
1197  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1198  *
1199  * RETURN:      Status
1200  *
1201  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1202  *
1203  ******************************************************************************/
1204 
1205 ACPI_STATUS
1206 AcpiReleaseGlobalLock (
1207     UINT32                  Handle)
1208 {
1209     ACPI_STATUS             Status;
1210 
1211 
1212     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1213     {
1214         return (AE_NOT_ACQUIRED);
1215     }
1216 
1217     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1218     return (Status);
1219 }
1220 
1221 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1222 
1223 #endif /* !ACPI_REDUCED_HARDWARE */
1224