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