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