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 = AE_OK;
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     /* Root Object. Global handlers are removed here */
285 
286     if (Device == ACPI_ROOT_OBJECT)
287     {
288         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
289         {
290             if (HandlerType & (i+1))
291             {
292                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
293                 if (ACPI_FAILURE (Status))
294                 {
295                     return_ACPI_STATUS (Status);
296                 }
297 
298                 if (!AcpiGbl_GlobalNotify[i].Handler ||
299                     (AcpiGbl_GlobalNotify[i].Handler != Handler))
300                 {
301                     Status = AE_NOT_EXIST;
302                     goto UnlockAndExit;
303                 }
304 
305                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
306                     "Removing global notify handler\n"));
307 
308                 AcpiGbl_GlobalNotify[i].Handler = NULL;
309                 AcpiGbl_GlobalNotify[i].Context = NULL;
310 
311                 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
312 
313                 /* Make sure all deferred notify tasks are completed */
314 
315                 AcpiOsWaitEventsComplete ();
316             }
317         }
318 
319         return_ACPI_STATUS (AE_OK);
320     }
321 
322     /* All other objects: Are Notifies allowed on this object? */
323 
324     if (!AcpiEvIsNotifyObject (Node))
325     {
326         return_ACPI_STATUS (AE_TYPE);
327     }
328 
329     /* Must have an existing internal object */
330 
331     ObjDesc = AcpiNsGetAttachedObject (Node);
332     if (!ObjDesc)
333     {
334         return_ACPI_STATUS (AE_NOT_EXIST);
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             Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
344             if (ACPI_FAILURE (Status))
345             {
346                 return_ACPI_STATUS (Status);
347             }
348 
349             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
350             PreviousHandlerObj = NULL;
351 
352             /* Attempt to find the handler in the handler list */
353 
354             while (HandlerObj &&
355                   (HandlerObj->Notify.Handler != Handler))
356             {
357                 PreviousHandlerObj = HandlerObj;
358                 HandlerObj = HandlerObj->Notify.Next[i];
359             }
360 
361             if (!HandlerObj)
362             {
363                 Status = AE_NOT_EXIST;
364                 goto UnlockAndExit;
365             }
366 
367             /* Remove the handler object from the list */
368 
369             if (PreviousHandlerObj) /* Handler is not at the list head */
370             {
371                 PreviousHandlerObj->Notify.Next[i] =
372                     HandlerObj->Notify.Next[i];
373             }
374             else /* Handler is at the list head */
375             {
376                 ObjDesc->CommonNotify.NotifyList[i] =
377                     HandlerObj->Notify.Next[i];
378             }
379 
380             (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
381 
382             /* Make sure all deferred notify tasks are completed */
383 
384             AcpiOsWaitEventsComplete ();
385             AcpiUtRemoveReference (HandlerObj);
386         }
387     }
388 
389     return_ACPI_STATUS (Status);
390 
391 
392 UnlockAndExit:
393     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
394     return_ACPI_STATUS (Status);
395 }
396 
397 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
398 
399 
400 /*******************************************************************************
401  *
402  * FUNCTION:    AcpiInstallExceptionHandler
403  *
404  * PARAMETERS:  Handler         - Pointer to the handler function for the
405  *                                event
406  *
407  * RETURN:      Status
408  *
409  * DESCRIPTION: Saves the pointer to the handler function
410  *
411  ******************************************************************************/
412 
413 ACPI_STATUS
414 AcpiInstallExceptionHandler (
415     ACPI_EXCEPTION_HANDLER  Handler)
416 {
417     ACPI_STATUS             Status;
418 
419 
420     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
421 
422 
423     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
424     if (ACPI_FAILURE (Status))
425     {
426         return_ACPI_STATUS (Status);
427     }
428 
429     /* Don't allow two handlers. */
430 
431     if (AcpiGbl_ExceptionHandler)
432     {
433         Status = AE_ALREADY_EXISTS;
434         goto Cleanup;
435     }
436 
437     /* Install the handler */
438 
439     AcpiGbl_ExceptionHandler = Handler;
440 
441 Cleanup:
442     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
443     return_ACPI_STATUS (Status);
444 }
445 
446 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
447 
448 
449 #if (!ACPI_REDUCED_HARDWARE)
450 /*******************************************************************************
451  *
452  * FUNCTION:    AcpiInstallSciHandler
453  *
454  * PARAMETERS:  Address             - Address of the handler
455  *              Context             - Value passed to the handler on each SCI
456  *
457  * RETURN:      Status
458  *
459  * DESCRIPTION: Install a handler for a System Control Interrupt.
460  *
461  ******************************************************************************/
462 
463 ACPI_STATUS
464 AcpiInstallSciHandler (
465     ACPI_SCI_HANDLER        Address,
466     void                    *Context)
467 {
468     ACPI_SCI_HANDLER_INFO   *NewSciHandler;
469     ACPI_SCI_HANDLER_INFO   *SciHandler;
470     ACPI_CPU_FLAGS          Flags;
471     ACPI_STATUS             Status;
472 
473 
474     ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
475 
476 
477     if (!Address)
478     {
479         return_ACPI_STATUS (AE_BAD_PARAMETER);
480     }
481 
482     /* Allocate and init a handler object */
483 
484     NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
485     if (!NewSciHandler)
486     {
487         return_ACPI_STATUS (AE_NO_MEMORY);
488     }
489 
490     NewSciHandler->Address = Address;
491     NewSciHandler->Context = Context;
492 
493     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
494     if (ACPI_FAILURE (Status))
495     {
496         goto Exit;
497     }
498 
499     /* Lock list during installation */
500 
501     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
502     SciHandler = AcpiGbl_SciHandlerList;
503 
504     /* Ensure handler does not already exist */
505 
506     while (SciHandler)
507     {
508         if (Address == SciHandler->Address)
509         {
510             Status = AE_ALREADY_EXISTS;
511             goto UnlockAndExit;
512         }
513 
514         SciHandler = SciHandler->Next;
515     }
516 
517     /* Install the new handler into the global list (at head) */
518 
519     NewSciHandler->Next = AcpiGbl_SciHandlerList;
520     AcpiGbl_SciHandlerList = NewSciHandler;
521 
522 
523 UnlockAndExit:
524 
525     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
526     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
527 
528 Exit:
529     if (ACPI_FAILURE (Status))
530     {
531         ACPI_FREE (NewSciHandler);
532     }
533     return_ACPI_STATUS (Status);
534 }
535 
536 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
537 
538 
539 /*******************************************************************************
540  *
541  * FUNCTION:    AcpiRemoveSciHandler
542  *
543  * PARAMETERS:  Address             - Address of the handler
544  *
545  * RETURN:      Status
546  *
547  * DESCRIPTION: Remove a handler for a System Control Interrupt.
548  *
549  ******************************************************************************/
550 
551 ACPI_STATUS
552 AcpiRemoveSciHandler (
553     ACPI_SCI_HANDLER        Address)
554 {
555     ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
556     ACPI_SCI_HANDLER_INFO   *NextSciHandler;
557     ACPI_CPU_FLAGS          Flags;
558     ACPI_STATUS             Status;
559 
560 
561     ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
562 
563 
564     if (!Address)
565     {
566         return_ACPI_STATUS (AE_BAD_PARAMETER);
567     }
568 
569     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
570     if (ACPI_FAILURE (Status))
571     {
572         return_ACPI_STATUS (Status);
573     }
574 
575     /* Remove the SCI handler with lock */
576 
577     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
578 
579     PrevSciHandler = NULL;
580     NextSciHandler = AcpiGbl_SciHandlerList;
581     while (NextSciHandler)
582     {
583         if (NextSciHandler->Address == Address)
584         {
585             /* Unlink and free the SCI handler info block */
586 
587             if (PrevSciHandler)
588             {
589                 PrevSciHandler->Next = NextSciHandler->Next;
590             }
591             else
592             {
593                 AcpiGbl_SciHandlerList = NextSciHandler->Next;
594             }
595 
596             AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
597             ACPI_FREE (NextSciHandler);
598             goto UnlockAndExit;
599         }
600 
601         PrevSciHandler = NextSciHandler;
602         NextSciHandler = NextSciHandler->Next;
603     }
604 
605     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
606     Status = AE_NOT_EXIST;
607 
608 
609 UnlockAndExit:
610     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
611     return_ACPI_STATUS (Status);
612 }
613 
614 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
615 
616 
617 /*******************************************************************************
618  *
619  * FUNCTION:    AcpiInstallGlobalEventHandler
620  *
621  * PARAMETERS:  Handler         - Pointer to the global event handler function
622  *              Context         - Value passed to the handler on each event
623  *
624  * RETURN:      Status
625  *
626  * DESCRIPTION: Saves the pointer to the handler function. The global handler
627  *              is invoked upon each incoming GPE and Fixed Event. It is
628  *              invoked at interrupt level at the time of the event dispatch.
629  *              Can be used to update event counters, etc.
630  *
631  ******************************************************************************/
632 
633 ACPI_STATUS
634 AcpiInstallGlobalEventHandler (
635     ACPI_GBL_EVENT_HANDLER  Handler,
636     void                    *Context)
637 {
638     ACPI_STATUS             Status;
639 
640 
641     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
642 
643 
644     /* Parameter validation */
645 
646     if (!Handler)
647     {
648         return_ACPI_STATUS (AE_BAD_PARAMETER);
649     }
650 
651     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
652     if (ACPI_FAILURE (Status))
653     {
654         return_ACPI_STATUS (Status);
655     }
656 
657     /* Don't allow two handlers. */
658 
659     if (AcpiGbl_GlobalEventHandler)
660     {
661         Status = AE_ALREADY_EXISTS;
662         goto Cleanup;
663     }
664 
665     AcpiGbl_GlobalEventHandler = Handler;
666     AcpiGbl_GlobalEventHandlerContext = Context;
667 
668 
669 Cleanup:
670     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
671     return_ACPI_STATUS (Status);
672 }
673 
674 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
675 
676 
677 /*******************************************************************************
678  *
679  * FUNCTION:    AcpiInstallFixedEventHandler
680  *
681  * PARAMETERS:  Event           - Event type to enable.
682  *              Handler         - Pointer to the handler function for the
683  *                                event
684  *              Context         - Value passed to the handler on each GPE
685  *
686  * RETURN:      Status
687  *
688  * DESCRIPTION: Saves the pointer to the handler function and then enables the
689  *              event.
690  *
691  ******************************************************************************/
692 
693 ACPI_STATUS
694 AcpiInstallFixedEventHandler (
695     UINT32                  Event,
696     ACPI_EVENT_HANDLER      Handler,
697     void                    *Context)
698 {
699     ACPI_STATUS             Status;
700 
701 
702     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
703 
704 
705     /* Parameter validation */
706 
707     if (Event > ACPI_EVENT_MAX)
708     {
709         return_ACPI_STATUS (AE_BAD_PARAMETER);
710     }
711 
712     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
713     if (ACPI_FAILURE (Status))
714     {
715         return_ACPI_STATUS (Status);
716     }
717 
718     /* Do not allow multiple handlers */
719 
720     if (AcpiGbl_FixedEventHandlers[Event].Handler)
721     {
722         Status = AE_ALREADY_EXISTS;
723         goto Cleanup;
724     }
725 
726     /* Install the handler before enabling the event */
727 
728     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
729     AcpiGbl_FixedEventHandlers[Event].Context = Context;
730 
731     Status = AcpiEnableEvent (Event, 0);
732     if (ACPI_FAILURE (Status))
733     {
734         ACPI_WARNING ((AE_INFO,
735             "Could not enable fixed event - %s (%u)",
736             AcpiUtGetEventName (Event), Event));
737 
738         /* Remove the handler */
739 
740         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
741         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
742     }
743     else
744     {
745         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
746             "Enabled fixed event %s (%X), Handler=%p\n",
747             AcpiUtGetEventName (Event), Event, Handler));
748     }
749 
750 
751 Cleanup:
752     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
753     return_ACPI_STATUS (Status);
754 }
755 
756 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
757 
758 
759 /*******************************************************************************
760  *
761  * FUNCTION:    AcpiRemoveFixedEventHandler
762  *
763  * PARAMETERS:  Event           - Event type to disable.
764  *              Handler         - Address of the handler
765  *
766  * RETURN:      Status
767  *
768  * DESCRIPTION: Disables the event and unregisters the event handler.
769  *
770  ******************************************************************************/
771 
772 ACPI_STATUS
773 AcpiRemoveFixedEventHandler (
774     UINT32                  Event,
775     ACPI_EVENT_HANDLER      Handler)
776 {
777     ACPI_STATUS             Status = AE_OK;
778 
779 
780     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
781 
782 
783     /* Parameter validation */
784 
785     if (Event > ACPI_EVENT_MAX)
786     {
787         return_ACPI_STATUS (AE_BAD_PARAMETER);
788     }
789 
790     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
791     if (ACPI_FAILURE (Status))
792     {
793         return_ACPI_STATUS (Status);
794     }
795 
796     /* Disable the event before removing the handler */
797 
798     Status = AcpiDisableEvent (Event, 0);
799 
800     /* Always Remove the handler */
801 
802     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
803     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
804 
805     if (ACPI_FAILURE (Status))
806     {
807         ACPI_WARNING ((AE_INFO,
808             "Could not disable fixed event - %s (%u)",
809             AcpiUtGetEventName (Event), Event));
810     }
811     else
812     {
813         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
814             "Disabled fixed event - %s (%X)\n",
815             AcpiUtGetEventName (Event), Event));
816     }
817 
818     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
819     return_ACPI_STATUS (Status);
820 }
821 
822 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
823 
824 
825 /*******************************************************************************
826  *
827  * FUNCTION:    AcpiInstallGpeHandler
828  *
829  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
830  *                                defined GPEs)
831  *              GpeNumber       - The GPE number within the GPE block
832  *              Type            - Whether this GPE should be treated as an
833  *                                edge- or level-triggered interrupt.
834  *              Address         - Address of the handler
835  *              Context         - Value passed to the handler on each GPE
836  *
837  * RETURN:      Status
838  *
839  * DESCRIPTION: Install a handler for a General Purpose Event.
840  *
841  ******************************************************************************/
842 
843 ACPI_STATUS
844 AcpiInstallGpeHandler (
845     ACPI_HANDLE             GpeDevice,
846     UINT32                  GpeNumber,
847     UINT32                  Type,
848     ACPI_GPE_HANDLER        Address,
849     void                    *Context)
850 {
851     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
852     ACPI_GPE_HANDLER_INFO   *Handler;
853     ACPI_STATUS             Status;
854     ACPI_CPU_FLAGS          Flags;
855 
856 
857     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
858 
859 
860     /* Parameter validation */
861 
862     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
863     {
864         return_ACPI_STATUS (AE_BAD_PARAMETER);
865     }
866 
867     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
868     if (ACPI_FAILURE (Status))
869     {
870         return_ACPI_STATUS (Status);
871     }
872 
873     /* Allocate and init handler object (before lock) */
874 
875     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
876     if (!Handler)
877     {
878         Status = AE_NO_MEMORY;
879         goto UnlockAndExit;
880     }
881 
882     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
883 
884     /* Ensure that we have a valid GPE number */
885 
886     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
887     if (!GpeEventInfo)
888     {
889         Status = AE_BAD_PARAMETER;
890         goto FreeAndExit;
891     }
892 
893     /* Make sure that there isn't a handler there already */
894 
895     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
896             ACPI_GPE_DISPATCH_HANDLER)
897     {
898         Status = AE_ALREADY_EXISTS;
899         goto FreeAndExit;
900     }
901 
902     Handler->Address = Address;
903     Handler->Context = Context;
904     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
905     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
906         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
907 
908     /*
909      * If the GPE is associated with a method, it may have been enabled
910      * automatically during initialization, in which case it has to be
911      * disabled now to avoid spurious execution of the handler.
912      */
913     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
914          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
915         GpeEventInfo->RuntimeCount)
916     {
917         Handler->OriginallyEnabled = TRUE;
918         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
919 
920         /* Sanity check of original type against new type */
921 
922         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
923         {
924             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
925         }
926     }
927 
928     /* Install the handler */
929 
930     GpeEventInfo->Dispatch.Handler = Handler;
931 
932     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
933 
934     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
935     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
936 
937     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
938 
939 
940 UnlockAndExit:
941     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
942     return_ACPI_STATUS (Status);
943 
944 FreeAndExit:
945     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
946     ACPI_FREE (Handler);
947     goto UnlockAndExit;
948 }
949 
950 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
951 
952 
953 /*******************************************************************************
954  *
955  * FUNCTION:    AcpiRemoveGpeHandler
956  *
957  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
958  *                                defined GPEs)
959  *              GpeNumber       - The event to remove a handler
960  *              Address         - Address of the handler
961  *
962  * RETURN:      Status
963  *
964  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
965  *
966  ******************************************************************************/
967 
968 ACPI_STATUS
969 AcpiRemoveGpeHandler (
970     ACPI_HANDLE             GpeDevice,
971     UINT32                  GpeNumber,
972     ACPI_GPE_HANDLER        Address)
973 {
974     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
975     ACPI_GPE_HANDLER_INFO   *Handler;
976     ACPI_STATUS             Status;
977     ACPI_CPU_FLAGS          Flags;
978 
979 
980     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
981 
982 
983     /* Parameter validation */
984 
985     if (!Address)
986     {
987         return_ACPI_STATUS (AE_BAD_PARAMETER);
988     }
989 
990     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
991     if (ACPI_FAILURE (Status))
992     {
993         return_ACPI_STATUS (Status);
994     }
995 
996     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
997 
998     /* Ensure that we have a valid GPE number */
999 
1000     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1001     if (!GpeEventInfo)
1002     {
1003         Status = AE_BAD_PARAMETER;
1004         goto UnlockAndExit;
1005     }
1006 
1007     /* Make sure that a handler is indeed installed */
1008 
1009     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
1010             ACPI_GPE_DISPATCH_HANDLER)
1011     {
1012         Status = AE_NOT_EXIST;
1013         goto UnlockAndExit;
1014     }
1015 
1016     /* Make sure that the installed handler is the same */
1017 
1018     if (GpeEventInfo->Dispatch.Handler->Address != Address)
1019     {
1020         Status = AE_BAD_PARAMETER;
1021         goto UnlockAndExit;
1022     }
1023 
1024     /* Remove the handler */
1025 
1026     Handler = GpeEventInfo->Dispatch.Handler;
1027 
1028     /* Restore Method node (if any), set dispatch flags */
1029 
1030     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1031     GpeEventInfo->Flags &=
1032         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1033     GpeEventInfo->Flags |= Handler->OriginalFlags;
1034 
1035     /*
1036      * If the GPE was previously associated with a method and it was
1037      * enabled, it should be enabled at this point to restore the
1038      * post-initialization configuration.
1039      */
1040     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
1041         Handler->OriginallyEnabled)
1042     {
1043         (void) AcpiEvAddGpeReference (GpeEventInfo);
1044     }
1045 
1046     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1047     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1048 
1049     /* Make sure all deferred GPE tasks are completed */
1050 
1051     AcpiOsWaitEventsComplete ();
1052 
1053     /* Now we can free the handler object */
1054 
1055     ACPI_FREE (Handler);
1056     return_ACPI_STATUS (Status);
1057 
1058 UnlockAndExit:
1059     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1060     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1061     return_ACPI_STATUS (Status);
1062 }
1063 
1064 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1065 
1066 
1067 /*******************************************************************************
1068  *
1069  * FUNCTION:    AcpiAcquireGlobalLock
1070  *
1071  * PARAMETERS:  Timeout         - How long the caller is willing to wait
1072  *              Handle          - Where the handle to the lock is returned
1073  *                                (if acquired)
1074  *
1075  * RETURN:      Status
1076  *
1077  * DESCRIPTION: Acquire the ACPI Global Lock
1078  *
1079  * Note: Allows callers with the same thread ID to acquire the global lock
1080  * multiple times. In other words, externally, the behavior of the global lock
1081  * is identical to an AML mutex. On the first acquire, a new handle is
1082  * returned. On any subsequent calls to acquire by the same thread, the same
1083  * handle is returned.
1084  *
1085  ******************************************************************************/
1086 
1087 ACPI_STATUS
1088 AcpiAcquireGlobalLock (
1089     UINT16                  Timeout,
1090     UINT32                  *Handle)
1091 {
1092     ACPI_STATUS             Status;
1093 
1094 
1095     if (!Handle)
1096     {
1097         return (AE_BAD_PARAMETER);
1098     }
1099 
1100     /* Must lock interpreter to prevent race conditions */
1101 
1102     AcpiExEnterInterpreter ();
1103 
1104     Status = AcpiExAcquireMutexObject (Timeout,
1105                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1106 
1107     if (ACPI_SUCCESS (Status))
1108     {
1109         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1110 
1111         *Handle = AcpiGbl_GlobalLockHandle;
1112     }
1113 
1114     AcpiExExitInterpreter ();
1115     return (Status);
1116 }
1117 
1118 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1119 
1120 
1121 /*******************************************************************************
1122  *
1123  * FUNCTION:    AcpiReleaseGlobalLock
1124  *
1125  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1126  *
1127  * RETURN:      Status
1128  *
1129  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1130  *
1131  ******************************************************************************/
1132 
1133 ACPI_STATUS
1134 AcpiReleaseGlobalLock (
1135     UINT32                  Handle)
1136 {
1137     ACPI_STATUS             Status;
1138 
1139 
1140     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1141     {
1142         return (AE_NOT_ACQUIRED);
1143     }
1144 
1145     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1146     return (Status);
1147 }
1148 
1149 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1150 
1151 #endif /* !ACPI_REDUCED_HARDWARE */
1152