1 /******************************************************************************
2  *
3  * Module Name: evxface - External interfaces for ACPI events
4  *              $Revision: 150 $
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial prton of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 
118 #define __EVXFACE_C__
119 
120 #include "acpi.h"
121 #include "acnamesp.h"
122 #include "acevents.h"
123 #include "acinterp.h"
124 
125 #define _COMPONENT          ACPI_EVENTS
126         ACPI_MODULE_NAME    ("evxface")
127 
128 
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiInstallExceptionHandler
132  *
133  * PARAMETERS:  Handler         - Pointer to the handler function for the
134  *                                event
135  *
136  * RETURN:      Status
137  *
138  * DESCRIPTION: Saves the pointer to the handler function
139  *
140  ******************************************************************************/
141 
142 ACPI_STATUS
143 AcpiInstallExceptionHandler (
144     ACPI_EXCEPTION_HANDLER  Handler)
145 {
146     ACPI_STATUS             Status;
147 
148 
149     ACPI_FUNCTION_TRACE ("AcpiInstallExceptionHandler");
150 
151 
152     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
153     if (ACPI_FAILURE (Status))
154     {
155         return_ACPI_STATUS (Status);
156     }
157 
158     /* Don't allow two handlers. */
159 
160     if (AcpiGbl_ExceptionHandler)
161     {
162         Status = AE_ALREADY_EXISTS;
163         goto Cleanup;
164     }
165 
166     /* Install the handler */
167 
168     AcpiGbl_ExceptionHandler = Handler;
169 
170 Cleanup:
171     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
172     return_ACPI_STATUS (Status);
173 }
174 
175 
176 /*******************************************************************************
177  *
178  * FUNCTION:    AcpiInstallFixedEventHandler
179  *
180  * PARAMETERS:  Event           - Event type to enable.
181  *              Handler         - Pointer to the handler function for the
182  *                                event
183  *              Context         - Value passed to the handler on each GPE
184  *
185  * RETURN:      Status
186  *
187  * DESCRIPTION: Saves the pointer to the handler function and then enables the
188  *              event.
189  *
190  ******************************************************************************/
191 
192 ACPI_STATUS
193 AcpiInstallFixedEventHandler (
194     UINT32                  Event,
195     ACPI_EVENT_HANDLER      Handler,
196     void                    *Context)
197 {
198     ACPI_STATUS             Status;
199 
200 
201     ACPI_FUNCTION_TRACE ("AcpiInstallFixedEventHandler");
202 
203 
204     /* Parameter validation */
205 
206     if (Event > ACPI_EVENT_MAX)
207     {
208         return_ACPI_STATUS (AE_BAD_PARAMETER);
209     }
210 
211     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
212     if (ACPI_FAILURE (Status))
213     {
214         return_ACPI_STATUS (Status);
215     }
216 
217     /* Don't allow two handlers. */
218 
219     if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
220     {
221         Status = AE_ALREADY_EXISTS;
222         goto Cleanup;
223     }
224 
225     /* Install the handler before enabling the event */
226 
227     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
228     AcpiGbl_FixedEventHandlers[Event].Context = Context;
229 
230     Status = AcpiEnableEvent (Event, 0);
231     if (ACPI_FAILURE (Status))
232     {
233         ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
234 
235         /* Remove the handler */
236 
237         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
238         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
239     }
240     else
241     {
242         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
243             "Enabled fixed event %X, Handler=%p\n", Event, Handler));
244     }
245 
246 
247 Cleanup:
248     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
249     return_ACPI_STATUS (Status);
250 }
251 
252 
253 /*******************************************************************************
254  *
255  * FUNCTION:    AcpiRemoveFixedEventHandler
256  *
257  * PARAMETERS:  Event           - Event type to disable.
258  *              Handler         - Address of the handler
259  *
260  * RETURN:      Status
261  *
262  * DESCRIPTION: Disables the event and unregisters the event handler.
263  *
264  ******************************************************************************/
265 
266 ACPI_STATUS
267 AcpiRemoveFixedEventHandler (
268     UINT32                  Event,
269     ACPI_EVENT_HANDLER      Handler)
270 {
271     ACPI_STATUS             Status = AE_OK;
272 
273 
274     ACPI_FUNCTION_TRACE ("AcpiRemoveFixedEventHandler");
275 
276 
277     /* Parameter validation */
278 
279     if (Event > ACPI_EVENT_MAX)
280     {
281         return_ACPI_STATUS (AE_BAD_PARAMETER);
282     }
283 
284     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
285     if (ACPI_FAILURE (Status))
286     {
287         return_ACPI_STATUS (Status);
288     }
289 
290     /* Disable the event before removing the handler */
291 
292     Status = AcpiDisableEvent (Event, 0);
293 
294     /* Always Remove the handler */
295 
296     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
297     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
298 
299     if (ACPI_FAILURE (Status))
300     {
301         ACPI_DEBUG_PRINT ((ACPI_DB_WARN,
302             "Could not write to fixed event enable register.\n"));
303     }
304     else
305     {
306         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X.\n", Event));
307     }
308 
309     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
310     return_ACPI_STATUS (Status);
311 }
312 
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    AcpiInstallNotifyHandler
317  *
318  * PARAMETERS:  Device          - The device for which notifies will be handled
319  *              HandlerType     - The type of handler:
320  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
321  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
322  *                                  ACPI_ALL_NOTIFY:  both system and device
323  *              Handler         - Address of the handler
324  *              Context         - Value passed to the handler on each GPE
325  *
326  * RETURN:      Status
327  *
328  * DESCRIPTION: Install a handler for notifies on an ACPI device
329  *
330  ******************************************************************************/
331 
332 ACPI_STATUS
333 AcpiInstallNotifyHandler (
334     ACPI_HANDLE             Device,
335     UINT32                  HandlerType,
336     ACPI_NOTIFY_HANDLER     Handler,
337     void                    *Context)
338 {
339     ACPI_OPERAND_OBJECT     *ObjDesc;
340     ACPI_OPERAND_OBJECT     *NotifyObj;
341     ACPI_NAMESPACE_NODE     *Node;
342     ACPI_STATUS             Status;
343 
344 
345     ACPI_FUNCTION_TRACE ("AcpiInstallNotifyHandler");
346 
347 
348     /* Parameter validation */
349 
350     if ((!Device)  ||
351         (!Handler) ||
352         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
353     {
354         return_ACPI_STATUS (AE_BAD_PARAMETER);
355     }
356 
357     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
358     if (ACPI_FAILURE (Status))
359     {
360         return_ACPI_STATUS (Status);
361     }
362 
363     /* Convert and validate the device handle */
364 
365     Node = AcpiNsMapHandleToNode (Device);
366     if (!Node)
367     {
368         Status = AE_BAD_PARAMETER;
369         goto UnlockAndExit;
370     }
371 
372     /*
373      * Root Object:
374      * Registering a notify handler on the root object indicates that the
375      * caller wishes to receive notifications for all objects.  Note that
376      * only one <external> global handler can be regsitered (per notify type).
377      */
378     if (Device == ACPI_ROOT_OBJECT)
379     {
380         /* Make sure the handler is not already installed */
381 
382         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
383                 AcpiGbl_SystemNotify.Handler)       ||
384             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
385                 AcpiGbl_DeviceNotify.Handler))
386         {
387             Status = AE_ALREADY_EXISTS;
388             goto UnlockAndExit;
389         }
390 
391         if (HandlerType & ACPI_SYSTEM_NOTIFY)
392         {
393             AcpiGbl_SystemNotify.Node    = Node;
394             AcpiGbl_SystemNotify.Handler = Handler;
395             AcpiGbl_SystemNotify.Context = Context;
396         }
397 
398         if (HandlerType & ACPI_DEVICE_NOTIFY)
399         {
400             AcpiGbl_DeviceNotify.Node    = Node;
401             AcpiGbl_DeviceNotify.Handler = Handler;
402             AcpiGbl_DeviceNotify.Context = Context;
403         }
404 
405         /* Global notify handler installed */
406     }
407 
408     /*
409      * All Other Objects:
410      * Caller will only receive notifications specific to the target object.
411      * Note that only certain object types can receive notifications.
412      */
413     else
414     {
415         /* Notifies allowed on this object? */
416 
417         if (!AcpiEvIsNotifyObject (Node))
418         {
419             Status = AE_TYPE;
420             goto UnlockAndExit;
421         }
422 
423         /* Check for an existing internal object */
424 
425         ObjDesc = AcpiNsGetAttachedObject (Node);
426         if (ObjDesc)
427         {
428             /* Object exists - make sure there's no handler */
429 
430             if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
431                     ObjDesc->CommonNotify.SystemNotify)   ||
432                 ((HandlerType & ACPI_DEVICE_NOTIFY) &&
433                     ObjDesc->CommonNotify.DeviceNotify))
434             {
435                 Status = AE_ALREADY_EXISTS;
436                 goto UnlockAndExit;
437             }
438         }
439         else
440         {
441             /* Create a new object */
442 
443             ObjDesc = AcpiUtCreateInternalObject (Node->Type);
444             if (!ObjDesc)
445             {
446                 Status = AE_NO_MEMORY;
447                 goto UnlockAndExit;
448             }
449 
450             /* Attach new object to the Node */
451 
452             Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
453 
454             /* Remove local reference to the object */
455 
456             AcpiUtRemoveReference (ObjDesc);
457             if (ACPI_FAILURE (Status))
458             {
459                 goto UnlockAndExit;
460             }
461         }
462 
463         /* Install the handler */
464 
465         NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
466         if (!NotifyObj)
467         {
468             Status = AE_NO_MEMORY;
469             goto UnlockAndExit;
470         }
471 
472         NotifyObj->Notify.Node    = Node;
473         NotifyObj->Notify.Handler = Handler;
474         NotifyObj->Notify.Context = Context;
475 
476         if (HandlerType & ACPI_SYSTEM_NOTIFY)
477         {
478             ObjDesc->CommonNotify.SystemNotify = NotifyObj;
479         }
480 
481         if (HandlerType & ACPI_DEVICE_NOTIFY)
482         {
483             ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
484         }
485 
486         if (HandlerType == ACPI_ALL_NOTIFY)
487         {
488             /* Extra ref if installed in both */
489 
490             AcpiUtAddReference (NotifyObj);
491         }
492     }
493 
494 
495 UnlockAndExit:
496     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
497     return_ACPI_STATUS (Status);
498 }
499 
500 
501 /*******************************************************************************
502  *
503  * FUNCTION:    AcpiRemoveNotifyHandler
504  *
505  * PARAMETERS:  Device          - The device for which notifies will be handled
506  *              HandlerType     - The type of handler:
507  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
508  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
509  *                                  ACPI_ALL_NOTIFY:  both system and device
510  *              Handler         - Address of the handler
511  *
512  * RETURN:      Status
513  *
514  * DESCRIPTION: Remove a handler for notifies on an ACPI device
515  *
516  ******************************************************************************/
517 
518 ACPI_STATUS
519 AcpiRemoveNotifyHandler (
520     ACPI_HANDLE             Device,
521     UINT32                  HandlerType,
522     ACPI_NOTIFY_HANDLER     Handler)
523 {
524     ACPI_OPERAND_OBJECT     *NotifyObj;
525     ACPI_OPERAND_OBJECT     *ObjDesc;
526     ACPI_NAMESPACE_NODE     *Node;
527     ACPI_STATUS             Status;
528 
529 
530     ACPI_FUNCTION_TRACE ("AcpiRemoveNotifyHandler");
531 
532 
533     /* Parameter validation */
534 
535     if ((!Device)  ||
536         (!Handler) ||
537         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
538     {
539         return_ACPI_STATUS (AE_BAD_PARAMETER);
540     }
541 
542     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
543     if (ACPI_FAILURE (Status))
544     {
545         return_ACPI_STATUS (Status);
546     }
547 
548     /* Convert and validate the device handle */
549 
550     Node = AcpiNsMapHandleToNode (Device);
551     if (!Node)
552     {
553         Status = AE_BAD_PARAMETER;
554         goto UnlockAndExit;
555     }
556 
557     /* Root Object */
558 
559     if (Device == ACPI_ROOT_OBJECT)
560     {
561         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
562             "Removing notify handler for ROOT object.\n"));
563 
564         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
565               !AcpiGbl_SystemNotify.Handler)        ||
566             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
567               !AcpiGbl_DeviceNotify.Handler))
568         {
569             Status = AE_NOT_EXIST;
570             goto UnlockAndExit;
571         }
572 
573         if (HandlerType & ACPI_SYSTEM_NOTIFY)
574         {
575             AcpiGbl_SystemNotify.Node    = NULL;
576             AcpiGbl_SystemNotify.Handler = NULL;
577             AcpiGbl_SystemNotify.Context = NULL;
578         }
579 
580         if (HandlerType & ACPI_DEVICE_NOTIFY)
581         {
582             AcpiGbl_DeviceNotify.Node    = NULL;
583             AcpiGbl_DeviceNotify.Handler = NULL;
584             AcpiGbl_DeviceNotify.Context = NULL;
585         }
586     }
587 
588     /* All Other Objects */
589 
590     else
591     {
592         /* Notifies allowed on this object? */
593 
594         if (!AcpiEvIsNotifyObject (Node))
595         {
596             Status = AE_TYPE;
597             goto UnlockAndExit;
598         }
599 
600         /* Check for an existing internal object */
601 
602         ObjDesc = AcpiNsGetAttachedObject (Node);
603         if (!ObjDesc)
604         {
605             Status = AE_NOT_EXIST;
606             goto UnlockAndExit;
607         }
608 
609         /* Object exists - make sure there's an existing handler */
610 
611         if (HandlerType & ACPI_SYSTEM_NOTIFY)
612         {
613             NotifyObj = ObjDesc->CommonNotify.SystemNotify;
614             if ((!NotifyObj) ||
615                  (NotifyObj->Notify.Handler != Handler))
616             {
617                 Status = AE_BAD_PARAMETER;
618                 goto UnlockAndExit;
619             }
620 
621             /* Remove the handler */
622 
623             ObjDesc->CommonNotify.SystemNotify = NULL;
624             AcpiUtRemoveReference (NotifyObj);
625         }
626 
627         if (HandlerType & ACPI_DEVICE_NOTIFY)
628         {
629             NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
630             if ((!NotifyObj) ||
631                  (NotifyObj->Notify.Handler != Handler))
632             {
633                 Status = AE_BAD_PARAMETER;
634                 goto UnlockAndExit;
635             }
636 
637             /* Remove the handler */
638 
639             ObjDesc->CommonNotify.DeviceNotify = NULL;
640             AcpiUtRemoveReference (NotifyObj);
641         }
642     }
643 
644 
645 UnlockAndExit:
646     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
647     return_ACPI_STATUS (Status);
648 }
649 
650 
651 /*******************************************************************************
652  *
653  * FUNCTION:    AcpiInstallGpeHandler
654  *
655  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
656  *                                defined GPEs)
657  *              GpeNumber       - The GPE number within the GPE block
658  *              Type            - Whether this GPE should be treated as an
659  *                                edge- or level-triggered interrupt.
660  *              Address         - Address of the handler
661  *              Context         - Value passed to the handler on each GPE
662  *
663  * RETURN:      Status
664  *
665  * DESCRIPTION: Install a handler for a General Purpose Event.
666  *
667  ******************************************************************************/
668 
669 ACPI_STATUS
670 AcpiInstallGpeHandler (
671     ACPI_HANDLE             GpeDevice,
672     UINT32                  GpeNumber,
673     UINT32                  Type,
674     ACPI_EVENT_HANDLER      Address,
675     void                    *Context)
676 {
677     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
678     ACPI_HANDLER_INFO       *Handler;
679     ACPI_STATUS             Status;
680     UINT32                  Flags;
681 
682 
683     ACPI_FUNCTION_TRACE ("AcpiInstallGpeHandler");
684 
685 
686     /* Parameter validation */
687 
688     if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK))
689     {
690         return_ACPI_STATUS (AE_BAD_PARAMETER);
691     }
692 
693     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
694     if (ACPI_FAILURE (Status))
695     {
696         return_ACPI_STATUS (Status);
697     }
698 
699     /* Ensure that we have a valid GPE number */
700 
701     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
702     if (!GpeEventInfo)
703     {
704         Status = AE_BAD_PARAMETER;
705         goto UnlockAndExit;
706     }
707 
708     /* Make sure that there isn't a handler there already */
709 
710     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER)
711     {
712         Status = AE_ALREADY_EXISTS;
713         goto UnlockAndExit;
714     }
715 
716     /* Allocate and init handler object */
717 
718     Handler = ACPI_MEM_CALLOCATE (sizeof (ACPI_HANDLER_INFO));
719     if (!Handler)
720     {
721         Status = AE_NO_MEMORY;
722         goto UnlockAndExit;
723     }
724 
725     Handler->Address    = Address;
726     Handler->Context    = Context;
727     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
728 
729     /* Disable the GPE before installing the handler */
730 
731     Status = AcpiEvDisableGpe (GpeEventInfo);
732     if (ACPI_FAILURE (Status))
733     {
734         goto UnlockAndExit;
735     }
736 
737     /* Install the handler */
738 
739     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
740     GpeEventInfo->Dispatch.Handler = Handler;
741 
742     /* Setup up dispatch flags to indicate handler (vs. method) */
743 
744     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);  /* Clear bits */
745     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
746 
747     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
748 
749 
750 UnlockAndExit:
751     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
752     return_ACPI_STATUS (Status);
753 }
754 
755 
756 /*******************************************************************************
757  *
758  * FUNCTION:    AcpiRemoveGpeHandler
759  *
760  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
761  *                                defined GPEs)
762  *              GpeNumber       - The event to remove a handler
763  *              Address         - Address of the handler
764  *
765  * RETURN:      Status
766  *
767  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
768  *
769  ******************************************************************************/
770 
771 ACPI_STATUS
772 AcpiRemoveGpeHandler (
773     ACPI_HANDLE             GpeDevice,
774     UINT32                  GpeNumber,
775     ACPI_EVENT_HANDLER      Address)
776 {
777     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
778     ACPI_HANDLER_INFO       *Handler;
779     ACPI_STATUS             Status;
780     UINT32                  Flags;
781 
782 
783     ACPI_FUNCTION_TRACE ("AcpiRemoveGpeHandler");
784 
785 
786     /* Parameter validation */
787 
788     if (!Address)
789     {
790         return_ACPI_STATUS (AE_BAD_PARAMETER);
791     }
792 
793     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
794     if (ACPI_FAILURE (Status))
795     {
796         return_ACPI_STATUS (Status);
797     }
798 
799     /* Ensure that we have a valid GPE number */
800 
801     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
802     if (!GpeEventInfo)
803     {
804         Status = AE_BAD_PARAMETER;
805         goto UnlockAndExit;
806     }
807 
808     /* Make sure that a handler is indeed installed */
809 
810     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER)
811     {
812         Status = AE_NOT_EXIST;
813         goto UnlockAndExit;
814     }
815 
816     /* Make sure that the installed handler is the same */
817 
818     if (GpeEventInfo->Dispatch.Handler->Address != Address)
819     {
820         Status = AE_BAD_PARAMETER;
821         goto UnlockAndExit;
822     }
823 
824     /* Disable the GPE before removing the handler */
825 
826     Status = AcpiEvDisableGpe (GpeEventInfo);
827     if (ACPI_FAILURE (Status))
828     {
829         goto UnlockAndExit;
830     }
831 
832     /* Remove the handler */
833 
834     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
835     Handler = GpeEventInfo->Dispatch.Handler;
836 
837     /* Restore Method node (if any), set dispatch flags */
838 
839     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
840     GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;  /* Clear bits */
841     if (Handler->MethodNode)
842     {
843         GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD;
844     }
845     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
846 
847     /* Now we can free the handler object */
848 
849     ACPI_MEM_FREE (Handler);
850 
851 
852 UnlockAndExit:
853     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
854     return_ACPI_STATUS (Status);
855 }
856 
857 
858 /*******************************************************************************
859  *
860  * FUNCTION:    AcpiAcquireGlobalLock
861  *
862  * PARAMETERS:  Timeout         - How long the caller is willing to wait
863  *              Handle          - Where the handle to the lock is returned
864  *                                (if acquired)
865  *
866  * RETURN:      Status
867  *
868  * DESCRIPTION: Acquire the ACPI Global Lock
869  *
870  ******************************************************************************/
871 
872 ACPI_STATUS
873 AcpiAcquireGlobalLock (
874     UINT16                  Timeout,
875     UINT32                  *Handle)
876 {
877     ACPI_STATUS             Status;
878 
879 
880     if (!Handle)
881     {
882         return (AE_BAD_PARAMETER);
883     }
884 
885     Status = AcpiExEnterInterpreter ();
886     if (ACPI_FAILURE (Status))
887     {
888         return (Status);
889     }
890 
891     Status = AcpiEvAcquireGlobalLock (Timeout);
892     AcpiExExitInterpreter ();
893 
894     if (ACPI_SUCCESS (Status))
895     {
896         AcpiGbl_GlobalLockHandle++;
897         *Handle = AcpiGbl_GlobalLockHandle;
898     }
899 
900     return (Status);
901 }
902 
903 
904 /*******************************************************************************
905  *
906  * FUNCTION:    AcpiReleaseGlobalLock
907  *
908  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
909  *
910  * RETURN:      Status
911  *
912  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
913  *
914  ******************************************************************************/
915 
916 ACPI_STATUS
917 AcpiReleaseGlobalLock (
918     UINT32                  Handle)
919 {
920     ACPI_STATUS             Status;
921 
922 
923     if (Handle != AcpiGbl_GlobalLockHandle)
924     {
925         return (AE_NOT_ACQUIRED);
926     }
927 
928     Status = AcpiEvReleaseGlobalLock ();
929     return (Status);
930 }
931 
932 
933