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