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