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