evxface.c revision 138287
1/******************************************************************************
2 *
3 * Module Name: evxface - External interfaces for ACPI events
4 *              $Revision: 147 $
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2004, 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
142ACPI_STATUS
143AcpiInstallExceptionHandler (
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
170Cleanup:
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
192ACPI_STATUS
193AcpiInstallFixedEventHandler (
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
247Cleanup:
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
266ACPI_STATUS
267AcpiRemoveFixedEventHandler (
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
332ACPI_STATUS
333AcpiInstallNotifyHandler (
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
495UnlockAndExit:
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
518ACPI_STATUS
519AcpiRemoveNotifyHandler (
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, "Removing notify handler for ROOT object.\n"));
562
563        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
564              !AcpiGbl_SystemNotify.Handler)        ||
565            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
566              !AcpiGbl_DeviceNotify.Handler))
567        {
568            Status = AE_NOT_EXIST;
569            goto UnlockAndExit;
570        }
571
572        if (HandlerType & ACPI_SYSTEM_NOTIFY)
573        {
574            AcpiGbl_SystemNotify.Node    = NULL;
575            AcpiGbl_SystemNotify.Handler = NULL;
576            AcpiGbl_SystemNotify.Context = NULL;
577        }
578
579        if (HandlerType & ACPI_DEVICE_NOTIFY)
580        {
581            AcpiGbl_DeviceNotify.Node    = NULL;
582            AcpiGbl_DeviceNotify.Handler = NULL;
583            AcpiGbl_DeviceNotify.Context = NULL;
584        }
585    }
586
587    /* All Other Objects */
588
589    else
590    {
591        /* Notifies allowed on this object? */
592
593        if (!AcpiEvIsNotifyObject (Node))
594        {
595            Status = AE_TYPE;
596            goto UnlockAndExit;
597        }
598
599        /* Check for an existing internal object */
600
601        ObjDesc = AcpiNsGetAttachedObject (Node);
602        if (!ObjDesc)
603        {
604            Status = AE_NOT_EXIST;
605            goto UnlockAndExit;
606        }
607
608        /* Object exists - make sure there's an existing handler */
609
610        if (HandlerType & ACPI_SYSTEM_NOTIFY)
611        {
612            NotifyObj = ObjDesc->CommonNotify.SystemNotify;
613            if ((!NotifyObj) ||
614                 (NotifyObj->Notify.Handler != Handler))
615            {
616                Status = AE_BAD_PARAMETER;
617                goto UnlockAndExit;
618            }
619
620            /* Remove the handler */
621
622            ObjDesc->CommonNotify.SystemNotify = NULL;
623            AcpiUtRemoveReference (NotifyObj);
624        }
625
626        if (HandlerType & ACPI_DEVICE_NOTIFY)
627        {
628            NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
629            if ((!NotifyObj) ||
630                 (NotifyObj->Notify.Handler != Handler))
631            {
632                Status = AE_BAD_PARAMETER;
633                goto UnlockAndExit;
634            }
635
636            /* Remove the handler */
637
638            ObjDesc->CommonNotify.DeviceNotify = NULL;
639            AcpiUtRemoveReference (NotifyObj);
640        }
641    }
642
643
644UnlockAndExit:
645    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
646    return_ACPI_STATUS (Status);
647}
648
649
650/*******************************************************************************
651 *
652 * FUNCTION:    AcpiInstallGpeHandler
653 *
654 * PARAMETERS:  GpeNumber       - The GPE number within the GPE block
655 *              GpeBlock        - GPE block (NULL == FADT GPEs)
656 *              Type            - Whether this GPE should be treated as an
657 *                                edge- or level-triggered interrupt.
658 *              Address         - Address of the handler
659 *              Context         - Value passed to the handler on each GPE
660 *
661 * RETURN:      Status
662 *
663 * DESCRIPTION: Install a handler for a General Purpose Event.
664 *
665 ******************************************************************************/
666
667ACPI_STATUS
668AcpiInstallGpeHandler (
669    ACPI_HANDLE             GpeDevice,
670    UINT32                  GpeNumber,
671    UINT32                  Type,
672    ACPI_EVENT_HANDLER      Address,
673    void                    *Context)
674{
675    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
676    ACPI_HANDLER_INFO       *Handler;
677    ACPI_STATUS             Status;
678
679
680    ACPI_FUNCTION_TRACE ("AcpiInstallGpeHandler");
681
682
683    /* Parameter validation */
684
685    if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK))
686    {
687        return_ACPI_STATUS (AE_BAD_PARAMETER);
688    }
689
690    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
691    if (ACPI_FAILURE (Status))
692    {
693        return_ACPI_STATUS (Status);
694    }
695
696    /* Ensure that we have a valid GPE number */
697
698    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
699    if (!GpeEventInfo)
700    {
701        Status = AE_BAD_PARAMETER;
702        goto UnlockAndExit;
703    }
704
705    /* Make sure that there isn't a handler there already */
706
707    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER)
708    {
709        Status = AE_ALREADY_EXISTS;
710        goto UnlockAndExit;
711    }
712
713    /* Allocate and init handler object */
714
715    Handler = ACPI_MEM_CALLOCATE (sizeof (ACPI_HANDLER_INFO));
716    if (!Handler)
717    {
718        Status = AE_NO_MEMORY;
719        goto UnlockAndExit;
720    }
721
722    Handler->Address    = Address;
723    Handler->Context    = Context;
724    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
725
726    /* Disable the GPE before installing the handler */
727
728    Status = AcpiEvDisableGpe (GpeEventInfo);
729    if (ACPI_FAILURE (Status))
730    {
731        goto UnlockAndExit;
732    }
733
734    /* Install the handler */
735
736    AcpiOsAcquireLock (AcpiGbl_GpeLock, ACPI_NOT_ISR);
737    GpeEventInfo->Dispatch.Handler = Handler;
738
739    /* Setup up dispatch flags to indicate handler (vs. method) */
740
741    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);  /* Clear bits */
742    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
743
744    AcpiOsReleaseLock (AcpiGbl_GpeLock, ACPI_NOT_ISR);
745
746
747UnlockAndExit:
748    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
749    return_ACPI_STATUS (Status);
750}
751
752
753/*******************************************************************************
754 *
755 * FUNCTION:    AcpiRemoveGpeHandler
756 *
757 * PARAMETERS:  GpeNumber       - The event to remove a handler
758 *              GpeBlock        - GPE block (NULL == FADT GPEs)
759 *              Address         - Address of the handler
760 *
761 * RETURN:      Status
762 *
763 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
764 *
765 ******************************************************************************/
766
767ACPI_STATUS
768AcpiRemoveGpeHandler (
769    ACPI_HANDLE             GpeDevice,
770    UINT32                  GpeNumber,
771    ACPI_EVENT_HANDLER      Address)
772{
773    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
774    ACPI_HANDLER_INFO       *Handler;
775    ACPI_STATUS             Status;
776
777
778    ACPI_FUNCTION_TRACE ("AcpiRemoveGpeHandler");
779
780
781    /* Parameter validation */
782
783    if (!Address)
784    {
785        return_ACPI_STATUS (AE_BAD_PARAMETER);
786    }
787
788    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
789    if (ACPI_FAILURE (Status))
790    {
791        return_ACPI_STATUS (Status);
792    }
793
794    /* Ensure that we have a valid GPE number */
795
796    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
797    if (!GpeEventInfo)
798    {
799        Status = AE_BAD_PARAMETER;
800        goto UnlockAndExit;
801    }
802
803    /* Make sure that a handler is indeed installed */
804
805    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER)
806    {
807        Status = AE_NOT_EXIST;
808        goto UnlockAndExit;
809    }
810
811    /* Make sure that the installed handler is the same */
812
813    if (GpeEventInfo->Dispatch.Handler->Address != Address)
814    {
815        Status = AE_BAD_PARAMETER;
816        goto UnlockAndExit;
817    }
818
819    /* Disable the GPE before removing the handler */
820
821    Status = AcpiEvDisableGpe (GpeEventInfo);
822    if (ACPI_FAILURE (Status))
823    {
824        goto UnlockAndExit;
825    }
826
827    /* Remove the handler */
828
829    AcpiOsAcquireLock (AcpiGbl_GpeLock, ACPI_NOT_ISR);
830    Handler = GpeEventInfo->Dispatch.Handler;
831
832    /* Restore Method node (if any), set dispatch flags */
833
834    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
835    GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;  /* Clear bits */
836    if (Handler->MethodNode)
837    {
838        GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD;
839    }
840    AcpiOsReleaseLock (AcpiGbl_GpeLock, ACPI_NOT_ISR);
841
842    /* Now we can free the handler object */
843
844    ACPI_MEM_FREE (Handler);
845
846
847UnlockAndExit:
848    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
849    return_ACPI_STATUS (Status);
850}
851
852
853/*******************************************************************************
854 *
855 * FUNCTION:    AcpiAcquireGlobalLock
856 *
857 * PARAMETERS:  Timeout         - How long the caller is willing to wait
858 *              OutHandle       - A handle to the lock if acquired
859 *
860 * RETURN:      Status
861 *
862 * DESCRIPTION: Acquire the ACPI Global Lock
863 *
864 ******************************************************************************/
865
866ACPI_STATUS
867AcpiAcquireGlobalLock (
868    UINT16                  Timeout,
869    UINT32                  *Handle)
870{
871    ACPI_STATUS             Status;
872
873
874    if (!Handle)
875    {
876        return (AE_BAD_PARAMETER);
877    }
878
879    Status = AcpiExEnterInterpreter ();
880    if (ACPI_FAILURE (Status))
881    {
882        return (Status);
883    }
884
885    Status = AcpiEvAcquireGlobalLock (Timeout);
886    AcpiExExitInterpreter ();
887
888    if (ACPI_SUCCESS (Status))
889    {
890        AcpiGbl_GlobalLockHandle++;
891        *Handle = AcpiGbl_GlobalLockHandle;
892    }
893
894    return (Status);
895}
896
897
898/*******************************************************************************
899 *
900 * FUNCTION:    AcpiReleaseGlobalLock
901 *
902 * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
903 *
904 * RETURN:      Status
905 *
906 * DESCRIPTION: Release the ACPI Global Lock
907 *
908 ******************************************************************************/
909
910ACPI_STATUS
911AcpiReleaseGlobalLock (
912    UINT32                  Handle)
913{
914    ACPI_STATUS             Status;
915
916
917    if (Handle != AcpiGbl_GlobalLockHandle)
918    {
919        return (AE_NOT_ACQUIRED);
920    }
921
922    Status = AcpiEvReleaseGlobalLock ();
923    return (Status);
924}
925
926
927