evxface.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: evxface - External interfaces for ACPI events
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#define EXPORT_ACPI_INTERFACES
45
46#include <contrib/dev/acpica/include/acpi.h>
47#include <contrib/dev/acpica/include/accommon.h>
48#include <contrib/dev/acpica/include/acnamesp.h>
49#include <contrib/dev/acpica/include/acevents.h>
50#include <contrib/dev/acpica/include/acinterp.h>
51
52#define _COMPONENT          ACPI_EVENTS
53        ACPI_MODULE_NAME    ("evxface")
54
55#if (!ACPI_REDUCED_HARDWARE)
56
57/* Local prototypes */
58
59static ACPI_STATUS
60AcpiEvInstallGpeHandler (
61    ACPI_HANDLE             GpeDevice,
62    UINT32                  GpeNumber,
63    UINT32                  Type,
64    BOOLEAN                 IsRawHandler,
65    ACPI_GPE_HANDLER        Address,
66    void                    *Context);
67
68#endif
69
70
71/*******************************************************************************
72 *
73 * FUNCTION:    AcpiInstallNotifyHandler
74 *
75 * PARAMETERS:  Device          - The device for which notifies will be handled
76 *              HandlerType     - The type of handler:
77 *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
78 *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
79 *                                  ACPI_ALL_NOTIFY:    Both System and Device
80 *              Handler         - Address of the handler
81 *              Context         - Value passed to the handler on each GPE
82 *
83 * RETURN:      Status
84 *
85 * DESCRIPTION: Install a handler for notifications on an ACPI Device,
86 *              ThermalZone, or Processor object.
87 *
88 * NOTES:       The Root namespace object may have only one handler for each
89 *              type of notify (System/Device). Device/Thermal/Processor objects
90 *              may have one device notify handler, and multiple system notify
91 *              handlers.
92 *
93 ******************************************************************************/
94
95ACPI_STATUS
96AcpiInstallNotifyHandler (
97    ACPI_HANDLE             Device,
98    UINT32                  HandlerType,
99    ACPI_NOTIFY_HANDLER     Handler,
100    void                    *Context)
101{
102    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
103    ACPI_OPERAND_OBJECT     *ObjDesc;
104    ACPI_OPERAND_OBJECT     *HandlerObj;
105    ACPI_STATUS             Status;
106    UINT32                  i;
107
108
109    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
110
111
112    /* Parameter validation */
113
114    if ((!Device) || (!Handler) || (!HandlerType) ||
115        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
116    {
117        return_ACPI_STATUS (AE_BAD_PARAMETER);
118    }
119
120    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
121    if (ACPI_FAILURE (Status))
122    {
123        return_ACPI_STATUS (Status);
124    }
125
126    /*
127     * Root Object:
128     * Registering a notify handler on the root object indicates that the
129     * caller wishes to receive notifications for all objects. Note that
130     * only one global handler can be registered per notify type.
131     * Ensure that a handler is not already installed.
132     */
133    if (Device == ACPI_ROOT_OBJECT)
134    {
135        for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
136        {
137            if (HandlerType & (i+1))
138            {
139                if (AcpiGbl_GlobalNotify[i].Handler)
140                {
141                    Status = AE_ALREADY_EXISTS;
142                    goto UnlockAndExit;
143                }
144
145                AcpiGbl_GlobalNotify[i].Handler = Handler;
146                AcpiGbl_GlobalNotify[i].Context = Context;
147            }
148        }
149
150        goto UnlockAndExit; /* Global notify handler installed, all done */
151    }
152
153    /*
154     * All Other Objects:
155     * Caller will only receive notifications specific to the target
156     * object. Note that only certain object types are allowed to
157     * receive notifications.
158     */
159
160    /* Are Notifies allowed on this object? */
161
162    if (!AcpiEvIsNotifyObject (Node))
163    {
164        Status = AE_TYPE;
165        goto UnlockAndExit;
166    }
167
168    /* Check for an existing internal object, might not exist */
169
170    ObjDesc = AcpiNsGetAttachedObject (Node);
171    if (!ObjDesc)
172    {
173        /* Create a new object */
174
175        ObjDesc = AcpiUtCreateInternalObject (Node->Type);
176        if (!ObjDesc)
177        {
178            Status = AE_NO_MEMORY;
179            goto UnlockAndExit;
180        }
181
182        /* Attach new object to the Node, remove local reference */
183
184        Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
185        AcpiUtRemoveReference (ObjDesc);
186        if (ACPI_FAILURE (Status))
187        {
188            goto UnlockAndExit;
189        }
190    }
191
192    /* Ensure that the handler is not already installed in the lists */
193
194    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
195    {
196        if (HandlerType & (i+1))
197        {
198            HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
199            while (HandlerObj)
200            {
201                if (HandlerObj->Notify.Handler == Handler)
202                {
203                    Status = AE_ALREADY_EXISTS;
204                    goto UnlockAndExit;
205                }
206
207                HandlerObj = HandlerObj->Notify.Next[i];
208            }
209        }
210    }
211
212    /* Create and populate a new notify handler object */
213
214    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
215    if (!HandlerObj)
216    {
217        Status = AE_NO_MEMORY;
218        goto UnlockAndExit;
219    }
220
221    HandlerObj->Notify.Node = Node;
222    HandlerObj->Notify.HandlerType = HandlerType;
223    HandlerObj->Notify.Handler = Handler;
224    HandlerObj->Notify.Context = Context;
225
226    /* Install the handler at the list head(s) */
227
228    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
229    {
230        if (HandlerType & (i+1))
231        {
232            HandlerObj->Notify.Next[i] =
233                ObjDesc->CommonNotify.NotifyList[i];
234
235            ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
236        }
237    }
238
239    /* Add an extra reference if handler was installed in both lists */
240
241    if (HandlerType == ACPI_ALL_NOTIFY)
242    {
243        AcpiUtAddReference (HandlerObj);
244    }
245
246
247UnlockAndExit:
248    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
249    return_ACPI_STATUS (Status);
250}
251
252ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
253
254
255/*******************************************************************************
256 *
257 * FUNCTION:    AcpiRemoveNotifyHandler
258 *
259 * PARAMETERS:  Device          - The device for which the handler is installed
260 *              HandlerType     - The type of handler:
261 *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
262 *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
263 *                                  ACPI_ALL_NOTIFY:    Both System and Device
264 *              Handler         - Address of the handler
265 *
266 * RETURN:      Status
267 *
268 * DESCRIPTION: Remove a handler for notifies on an ACPI device
269 *
270 ******************************************************************************/
271
272ACPI_STATUS
273AcpiRemoveNotifyHandler (
274    ACPI_HANDLE             Device,
275    UINT32                  HandlerType,
276    ACPI_NOTIFY_HANDLER     Handler)
277{
278    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
279    ACPI_OPERAND_OBJECT     *ObjDesc;
280    ACPI_OPERAND_OBJECT     *HandlerObj;
281    ACPI_OPERAND_OBJECT     *PreviousHandlerObj;
282    ACPI_STATUS             Status = AE_OK;
283    UINT32                  i;
284
285
286    ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
287
288
289    /* Parameter validation */
290
291    if ((!Device) || (!Handler) || (!HandlerType) ||
292        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
293    {
294        return_ACPI_STATUS (AE_BAD_PARAMETER);
295    }
296
297    /* Root Object. Global handlers are removed here */
298
299    if (Device == ACPI_ROOT_OBJECT)
300    {
301        for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
302        {
303            if (HandlerType & (i+1))
304            {
305                Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
306                if (ACPI_FAILURE (Status))
307                {
308                    return_ACPI_STATUS (Status);
309                }
310
311                if (!AcpiGbl_GlobalNotify[i].Handler ||
312                    (AcpiGbl_GlobalNotify[i].Handler != Handler))
313                {
314                    Status = AE_NOT_EXIST;
315                    goto UnlockAndExit;
316                }
317
318                ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
319                    "Removing global notify handler\n"));
320
321                AcpiGbl_GlobalNotify[i].Handler = NULL;
322                AcpiGbl_GlobalNotify[i].Context = NULL;
323
324                (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
325
326                /* Make sure all deferred notify tasks are completed */
327
328                AcpiOsWaitEventsComplete ();
329            }
330        }
331
332        return_ACPI_STATUS (AE_OK);
333    }
334
335    /* All other objects: Are Notifies allowed on this object? */
336
337    if (!AcpiEvIsNotifyObject (Node))
338    {
339        return_ACPI_STATUS (AE_TYPE);
340    }
341
342    /* Must have an existing internal object */
343
344    ObjDesc = AcpiNsGetAttachedObject (Node);
345    if (!ObjDesc)
346    {
347        return_ACPI_STATUS (AE_NOT_EXIST);
348    }
349
350    /* Internal object exists. Find the handler and remove it */
351
352    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
353    {
354        if (HandlerType & (i+1))
355        {
356            Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
357            if (ACPI_FAILURE (Status))
358            {
359                return_ACPI_STATUS (Status);
360            }
361
362            HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
363            PreviousHandlerObj = NULL;
364
365            /* Attempt to find the handler in the handler list */
366
367            while (HandlerObj &&
368                  (HandlerObj->Notify.Handler != Handler))
369            {
370                PreviousHandlerObj = HandlerObj;
371                HandlerObj = HandlerObj->Notify.Next[i];
372            }
373
374            if (!HandlerObj)
375            {
376                Status = AE_NOT_EXIST;
377                goto UnlockAndExit;
378            }
379
380            /* Remove the handler object from the list */
381
382            if (PreviousHandlerObj) /* Handler is not at the list head */
383            {
384                PreviousHandlerObj->Notify.Next[i] =
385                    HandlerObj->Notify.Next[i];
386            }
387            else /* Handler is at the list head */
388            {
389                ObjDesc->CommonNotify.NotifyList[i] =
390                    HandlerObj->Notify.Next[i];
391            }
392
393            (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
394
395            /* Make sure all deferred notify tasks are completed */
396
397            AcpiOsWaitEventsComplete ();
398            AcpiUtRemoveReference (HandlerObj);
399        }
400    }
401
402    return_ACPI_STATUS (Status);
403
404
405UnlockAndExit:
406    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
407    return_ACPI_STATUS (Status);
408}
409
410ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
411
412
413/*******************************************************************************
414 *
415 * FUNCTION:    AcpiInstallExceptionHandler
416 *
417 * PARAMETERS:  Handler         - Pointer to the handler function for the
418 *                                event
419 *
420 * RETURN:      Status
421 *
422 * DESCRIPTION: Saves the pointer to the handler function
423 *
424 ******************************************************************************/
425
426ACPI_STATUS
427AcpiInstallExceptionHandler (
428    ACPI_EXCEPTION_HANDLER  Handler)
429{
430    ACPI_STATUS             Status;
431
432
433    ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
434
435
436    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
437    if (ACPI_FAILURE (Status))
438    {
439        return_ACPI_STATUS (Status);
440    }
441
442    /* Don't allow two handlers. */
443
444    if (AcpiGbl_ExceptionHandler)
445    {
446        Status = AE_ALREADY_EXISTS;
447        goto Cleanup;
448    }
449
450    /* Install the handler */
451
452    AcpiGbl_ExceptionHandler = Handler;
453
454Cleanup:
455    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
456    return_ACPI_STATUS (Status);
457}
458
459ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
460
461
462#if (!ACPI_REDUCED_HARDWARE)
463/*******************************************************************************
464 *
465 * FUNCTION:    AcpiInstallSciHandler
466 *
467 * PARAMETERS:  Address             - Address of the handler
468 *              Context             - Value passed to the handler on each SCI
469 *
470 * RETURN:      Status
471 *
472 * DESCRIPTION: Install a handler for a System Control Interrupt.
473 *
474 ******************************************************************************/
475
476ACPI_STATUS
477AcpiInstallSciHandler (
478    ACPI_SCI_HANDLER        Address,
479    void                    *Context)
480{
481    ACPI_SCI_HANDLER_INFO   *NewSciHandler;
482    ACPI_SCI_HANDLER_INFO   *SciHandler;
483    ACPI_CPU_FLAGS          Flags;
484    ACPI_STATUS             Status;
485
486
487    ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
488
489
490    if (!Address)
491    {
492        return_ACPI_STATUS (AE_BAD_PARAMETER);
493    }
494
495    /* Allocate and init a handler object */
496
497    NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
498    if (!NewSciHandler)
499    {
500        return_ACPI_STATUS (AE_NO_MEMORY);
501    }
502
503    NewSciHandler->Address = Address;
504    NewSciHandler->Context = Context;
505
506    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
507    if (ACPI_FAILURE (Status))
508    {
509        goto Exit;
510    }
511
512    /* Lock list during installation */
513
514    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
515    SciHandler = AcpiGbl_SciHandlerList;
516
517    /* Ensure handler does not already exist */
518
519    while (SciHandler)
520    {
521        if (Address == SciHandler->Address)
522        {
523            Status = AE_ALREADY_EXISTS;
524            goto UnlockAndExit;
525        }
526
527        SciHandler = SciHandler->Next;
528    }
529
530    /* Install the new handler into the global list (at head) */
531
532    NewSciHandler->Next = AcpiGbl_SciHandlerList;
533    AcpiGbl_SciHandlerList = NewSciHandler;
534
535
536UnlockAndExit:
537
538    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
539    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
540
541Exit:
542    if (ACPI_FAILURE (Status))
543    {
544        ACPI_FREE (NewSciHandler);
545    }
546    return_ACPI_STATUS (Status);
547}
548
549ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
550
551
552/*******************************************************************************
553 *
554 * FUNCTION:    AcpiRemoveSciHandler
555 *
556 * PARAMETERS:  Address             - Address of the handler
557 *
558 * RETURN:      Status
559 *
560 * DESCRIPTION: Remove a handler for a System Control Interrupt.
561 *
562 ******************************************************************************/
563
564ACPI_STATUS
565AcpiRemoveSciHandler (
566    ACPI_SCI_HANDLER        Address)
567{
568    ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
569    ACPI_SCI_HANDLER_INFO   *NextSciHandler;
570    ACPI_CPU_FLAGS          Flags;
571    ACPI_STATUS             Status;
572
573
574    ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
575
576
577    if (!Address)
578    {
579        return_ACPI_STATUS (AE_BAD_PARAMETER);
580    }
581
582    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
583    if (ACPI_FAILURE (Status))
584    {
585        return_ACPI_STATUS (Status);
586    }
587
588    /* Remove the SCI handler with lock */
589
590    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
591
592    PrevSciHandler = NULL;
593    NextSciHandler = AcpiGbl_SciHandlerList;
594    while (NextSciHandler)
595    {
596        if (NextSciHandler->Address == Address)
597        {
598            /* Unlink and free the SCI handler info block */
599
600            if (PrevSciHandler)
601            {
602                PrevSciHandler->Next = NextSciHandler->Next;
603            }
604            else
605            {
606                AcpiGbl_SciHandlerList = NextSciHandler->Next;
607            }
608
609            AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
610            ACPI_FREE (NextSciHandler);
611            goto UnlockAndExit;
612        }
613
614        PrevSciHandler = NextSciHandler;
615        NextSciHandler = NextSciHandler->Next;
616    }
617
618    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
619    Status = AE_NOT_EXIST;
620
621
622UnlockAndExit:
623    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
624    return_ACPI_STATUS (Status);
625}
626
627ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
628
629
630/*******************************************************************************
631 *
632 * FUNCTION:    AcpiInstallGlobalEventHandler
633 *
634 * PARAMETERS:  Handler         - Pointer to the global event handler function
635 *              Context         - Value passed to the handler on each event
636 *
637 * RETURN:      Status
638 *
639 * DESCRIPTION: Saves the pointer to the handler function. The global handler
640 *              is invoked upon each incoming GPE and Fixed Event. It is
641 *              invoked at interrupt level at the time of the event dispatch.
642 *              Can be used to update event counters, etc.
643 *
644 ******************************************************************************/
645
646ACPI_STATUS
647AcpiInstallGlobalEventHandler (
648    ACPI_GBL_EVENT_HANDLER  Handler,
649    void                    *Context)
650{
651    ACPI_STATUS             Status;
652
653
654    ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
655
656
657    /* Parameter validation */
658
659    if (!Handler)
660    {
661        return_ACPI_STATUS (AE_BAD_PARAMETER);
662    }
663
664    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
665    if (ACPI_FAILURE (Status))
666    {
667        return_ACPI_STATUS (Status);
668    }
669
670    /* Don't allow two handlers. */
671
672    if (AcpiGbl_GlobalEventHandler)
673    {
674        Status = AE_ALREADY_EXISTS;
675        goto Cleanup;
676    }
677
678    AcpiGbl_GlobalEventHandler = Handler;
679    AcpiGbl_GlobalEventHandlerContext = Context;
680
681
682Cleanup:
683    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
684    return_ACPI_STATUS (Status);
685}
686
687ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
688
689
690/*******************************************************************************
691 *
692 * FUNCTION:    AcpiInstallFixedEventHandler
693 *
694 * PARAMETERS:  Event           - Event type to enable.
695 *              Handler         - Pointer to the handler function for the
696 *                                event
697 *              Context         - Value passed to the handler on each GPE
698 *
699 * RETURN:      Status
700 *
701 * DESCRIPTION: Saves the pointer to the handler function and then enables the
702 *              event.
703 *
704 ******************************************************************************/
705
706ACPI_STATUS
707AcpiInstallFixedEventHandler (
708    UINT32                  Event,
709    ACPI_EVENT_HANDLER      Handler,
710    void                    *Context)
711{
712    ACPI_STATUS             Status;
713
714
715    ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
716
717
718    /* Parameter validation */
719
720    if (Event > ACPI_EVENT_MAX)
721    {
722        return_ACPI_STATUS (AE_BAD_PARAMETER);
723    }
724
725    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
726    if (ACPI_FAILURE (Status))
727    {
728        return_ACPI_STATUS (Status);
729    }
730
731    /* Do not allow multiple handlers */
732
733    if (AcpiGbl_FixedEventHandlers[Event].Handler)
734    {
735        Status = AE_ALREADY_EXISTS;
736        goto Cleanup;
737    }
738
739    /* Install the handler before enabling the event */
740
741    AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
742    AcpiGbl_FixedEventHandlers[Event].Context = Context;
743
744    Status = AcpiEnableEvent (Event, 0);
745    if (ACPI_FAILURE (Status))
746    {
747        ACPI_WARNING ((AE_INFO,
748            "Could not enable fixed event - %s (%u)",
749            AcpiUtGetEventName (Event), Event));
750
751        /* Remove the handler */
752
753        AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
754        AcpiGbl_FixedEventHandlers[Event].Context = NULL;
755    }
756    else
757    {
758        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
759            "Enabled fixed event %s (%X), Handler=%p\n",
760            AcpiUtGetEventName (Event), Event, Handler));
761    }
762
763
764Cleanup:
765    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
766    return_ACPI_STATUS (Status);
767}
768
769ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
770
771
772/*******************************************************************************
773 *
774 * FUNCTION:    AcpiRemoveFixedEventHandler
775 *
776 * PARAMETERS:  Event           - Event type to disable.
777 *              Handler         - Address of the handler
778 *
779 * RETURN:      Status
780 *
781 * DESCRIPTION: Disables the event and unregisters the event handler.
782 *
783 ******************************************************************************/
784
785ACPI_STATUS
786AcpiRemoveFixedEventHandler (
787    UINT32                  Event,
788    ACPI_EVENT_HANDLER      Handler)
789{
790    ACPI_STATUS             Status = AE_OK;
791
792
793    ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
794
795
796    /* Parameter validation */
797
798    if (Event > ACPI_EVENT_MAX)
799    {
800        return_ACPI_STATUS (AE_BAD_PARAMETER);
801    }
802
803    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
804    if (ACPI_FAILURE (Status))
805    {
806        return_ACPI_STATUS (Status);
807    }
808
809    /* Disable the event before removing the handler */
810
811    Status = AcpiDisableEvent (Event, 0);
812
813    /* Always Remove the handler */
814
815    AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
816    AcpiGbl_FixedEventHandlers[Event].Context = NULL;
817
818    if (ACPI_FAILURE (Status))
819    {
820        ACPI_WARNING ((AE_INFO,
821            "Could not disable fixed event - %s (%u)",
822            AcpiUtGetEventName (Event), Event));
823    }
824    else
825    {
826        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
827            "Disabled fixed event - %s (%X)\n",
828            AcpiUtGetEventName (Event), Event));
829    }
830
831    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
832    return_ACPI_STATUS (Status);
833}
834
835ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
836
837
838/*******************************************************************************
839 *
840 * FUNCTION:    AcpiEvInstallGpeHandler
841 *
842 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
843 *                                defined GPEs)
844 *              GpeNumber       - The GPE number within the GPE block
845 *              Type            - Whether this GPE should be treated as an
846 *                                edge- or level-triggered interrupt.
847 *              IsRawHandler    - Whether this GPE should be handled using
848 *                                the special GPE handler mode.
849 *              Address         - Address of the handler
850 *              Context         - Value passed to the handler on each GPE
851 *
852 * RETURN:      Status
853 *
854 * DESCRIPTION: Internal function to install a handler for a General Purpose
855 *              Event.
856 *
857 ******************************************************************************/
858
859static ACPI_STATUS
860AcpiEvInstallGpeHandler (
861    ACPI_HANDLE             GpeDevice,
862    UINT32                  GpeNumber,
863    UINT32                  Type,
864    BOOLEAN                 IsRawHandler,
865    ACPI_GPE_HANDLER        Address,
866    void                    *Context)
867{
868    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
869    ACPI_GPE_HANDLER_INFO   *Handler;
870    ACPI_STATUS             Status;
871    ACPI_CPU_FLAGS          Flags;
872
873
874    ACPI_FUNCTION_TRACE (EvInstallGpeHandler);
875
876
877    /* Parameter validation */
878
879    if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
880    {
881        return_ACPI_STATUS (AE_BAD_PARAMETER);
882    }
883
884    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
885    if (ACPI_FAILURE (Status))
886    {
887        return_ACPI_STATUS (Status);
888    }
889
890    /* Allocate and init handler object (before lock) */
891
892    Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
893    if (!Handler)
894    {
895        Status = AE_NO_MEMORY;
896        goto UnlockAndExit;
897    }
898
899    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
900
901    /* Ensure that we have a valid GPE number */
902
903    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
904    if (!GpeEventInfo)
905    {
906        Status = AE_BAD_PARAMETER;
907        goto FreeAndExit;
908    }
909
910    /* Make sure that there isn't a handler there already */
911
912    if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
913            ACPI_GPE_DISPATCH_HANDLER) ||
914        (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
915            ACPI_GPE_DISPATCH_RAW_HANDLER))
916    {
917        Status = AE_ALREADY_EXISTS;
918        goto FreeAndExit;
919    }
920
921    Handler->Address = Address;
922    Handler->Context = Context;
923    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
924    Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
925        (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
926
927    /*
928     * If the GPE is associated with a method, it may have been enabled
929     * automatically during initialization, in which case it has to be
930     * disabled now to avoid spurious execution of the handler.
931     */
932    if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
933            ACPI_GPE_DISPATCH_METHOD) ||
934         (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
935            ACPI_GPE_DISPATCH_NOTIFY)) &&
936        GpeEventInfo->RuntimeCount)
937    {
938        Handler->OriginallyEnabled = TRUE;
939        (void) AcpiEvRemoveGpeReference (GpeEventInfo);
940
941        /* Sanity check of original type against new type */
942
943        if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
944        {
945            ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
946        }
947    }
948
949    /* Install the handler */
950
951    GpeEventInfo->Dispatch.Handler = Handler;
952
953    /* Setup up dispatch flags to indicate handler (vs. method/notify) */
954
955    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
956    GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ?
957        ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER));
958
959    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
960
961
962UnlockAndExit:
963    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
964    return_ACPI_STATUS (Status);
965
966FreeAndExit:
967    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
968    ACPI_FREE (Handler);
969    goto UnlockAndExit;
970}
971
972
973/*******************************************************************************
974 *
975 * FUNCTION:    AcpiInstallGpeHandler
976 *
977 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
978 *                                defined GPEs)
979 *              GpeNumber       - The GPE number within the GPE block
980 *              Type            - Whether this GPE should be treated as an
981 *                                edge- or level-triggered interrupt.
982 *              Address         - Address of the handler
983 *              Context         - Value passed to the handler on each GPE
984 *
985 * RETURN:      Status
986 *
987 * DESCRIPTION: Install a handler for a General Purpose Event.
988 *
989 ******************************************************************************/
990
991ACPI_STATUS
992AcpiInstallGpeHandler (
993    ACPI_HANDLE             GpeDevice,
994    UINT32                  GpeNumber,
995    UINT32                  Type,
996    ACPI_GPE_HANDLER        Address,
997    void                    *Context)
998{
999    ACPI_STATUS             Status;
1000
1001
1002    ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
1003
1004
1005    Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1006        FALSE, Address, Context);
1007
1008    return_ACPI_STATUS (Status);
1009}
1010
1011ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
1012
1013
1014/*******************************************************************************
1015 *
1016 * FUNCTION:    AcpiInstallGpeRawHandler
1017 *
1018 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
1019 *                                defined GPEs)
1020 *              GpeNumber       - The GPE number within the GPE block
1021 *              Type            - Whether this GPE should be treated as an
1022 *                                edge- or level-triggered interrupt.
1023 *              Address         - Address of the handler
1024 *              Context         - Value passed to the handler on each GPE
1025 *
1026 * RETURN:      Status
1027 *
1028 * DESCRIPTION: Install a handler for a General Purpose Event.
1029 *
1030 ******************************************************************************/
1031
1032ACPI_STATUS
1033AcpiInstallGpeRawHandler (
1034    ACPI_HANDLE             GpeDevice,
1035    UINT32                  GpeNumber,
1036    UINT32                  Type,
1037    ACPI_GPE_HANDLER        Address,
1038    void                    *Context)
1039{
1040    ACPI_STATUS             Status;
1041
1042
1043    ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler);
1044
1045
1046    Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
1047        TRUE, Address, Context);
1048
1049    return_ACPI_STATUS (Status);
1050}
1051
1052ACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler)
1053
1054
1055/*******************************************************************************
1056 *
1057 * FUNCTION:    AcpiRemoveGpeHandler
1058 *
1059 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
1060 *                                defined GPEs)
1061 *              GpeNumber       - The event to remove a handler
1062 *              Address         - Address of the handler
1063 *
1064 * RETURN:      Status
1065 *
1066 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
1067 *
1068 ******************************************************************************/
1069
1070ACPI_STATUS
1071AcpiRemoveGpeHandler (
1072    ACPI_HANDLE             GpeDevice,
1073    UINT32                  GpeNumber,
1074    ACPI_GPE_HANDLER        Address)
1075{
1076    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
1077    ACPI_GPE_HANDLER_INFO   *Handler;
1078    ACPI_STATUS             Status;
1079    ACPI_CPU_FLAGS          Flags;
1080
1081
1082    ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
1083
1084
1085    /* Parameter validation */
1086
1087    if (!Address)
1088    {
1089        return_ACPI_STATUS (AE_BAD_PARAMETER);
1090    }
1091
1092    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1093    if (ACPI_FAILURE (Status))
1094    {
1095        return_ACPI_STATUS (Status);
1096    }
1097
1098    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
1099
1100    /* Ensure that we have a valid GPE number */
1101
1102    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
1103    if (!GpeEventInfo)
1104    {
1105        Status = AE_BAD_PARAMETER;
1106        goto UnlockAndExit;
1107    }
1108
1109    /* Make sure that a handler is indeed installed */
1110
1111    if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1112            ACPI_GPE_DISPATCH_HANDLER) &&
1113        (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
1114            ACPI_GPE_DISPATCH_RAW_HANDLER))
1115    {
1116        Status = AE_NOT_EXIST;
1117        goto UnlockAndExit;
1118    }
1119
1120    /* Make sure that the installed handler is the same */
1121
1122    if (GpeEventInfo->Dispatch.Handler->Address != Address)
1123    {
1124        Status = AE_BAD_PARAMETER;
1125        goto UnlockAndExit;
1126    }
1127
1128    /* Remove the handler */
1129
1130    Handler = GpeEventInfo->Dispatch.Handler;
1131    GpeEventInfo->Dispatch.Handler = NULL;
1132
1133    /* Restore Method node (if any), set dispatch flags */
1134
1135    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1136    GpeEventInfo->Flags &=
1137        ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1138    GpeEventInfo->Flags |= Handler->OriginalFlags;
1139
1140    /*
1141     * If the GPE was previously associated with a method and it was
1142     * enabled, it should be enabled at this point to restore the
1143     * post-initialization configuration.
1144     */
1145    if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1146            ACPI_GPE_DISPATCH_METHOD) ||
1147         (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
1148            ACPI_GPE_DISPATCH_NOTIFY)) &&
1149        Handler->OriginallyEnabled)
1150    {
1151        (void) AcpiEvAddGpeReference (GpeEventInfo);
1152    }
1153
1154    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1155    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1156
1157    /* Make sure all deferred GPE tasks are completed */
1158
1159    AcpiOsWaitEventsComplete ();
1160
1161    /* Now we can free the handler object */
1162
1163    ACPI_FREE (Handler);
1164    return_ACPI_STATUS (Status);
1165
1166UnlockAndExit:
1167    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1168    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1169    return_ACPI_STATUS (Status);
1170}
1171
1172ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1173
1174
1175/*******************************************************************************
1176 *
1177 * FUNCTION:    AcpiAcquireGlobalLock
1178 *
1179 * PARAMETERS:  Timeout         - How long the caller is willing to wait
1180 *              Handle          - Where the handle to the lock is returned
1181 *                                (if acquired)
1182 *
1183 * RETURN:      Status
1184 *
1185 * DESCRIPTION: Acquire the ACPI Global Lock
1186 *
1187 * Note: Allows callers with the same thread ID to acquire the global lock
1188 * multiple times. In other words, externally, the behavior of the global lock
1189 * is identical to an AML mutex. On the first acquire, a new handle is
1190 * returned. On any subsequent calls to acquire by the same thread, the same
1191 * handle is returned.
1192 *
1193 ******************************************************************************/
1194
1195ACPI_STATUS
1196AcpiAcquireGlobalLock (
1197    UINT16                  Timeout,
1198    UINT32                  *Handle)
1199{
1200    ACPI_STATUS             Status;
1201
1202
1203    if (!Handle)
1204    {
1205        return (AE_BAD_PARAMETER);
1206    }
1207
1208    /* Must lock interpreter to prevent race conditions */
1209
1210    AcpiExEnterInterpreter ();
1211
1212    Status = AcpiExAcquireMutexObject (Timeout,
1213        AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1214
1215    if (ACPI_SUCCESS (Status))
1216    {
1217        /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1218
1219        *Handle = AcpiGbl_GlobalLockHandle;
1220    }
1221
1222    AcpiExExitInterpreter ();
1223    return (Status);
1224}
1225
1226ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1227
1228
1229/*******************************************************************************
1230 *
1231 * FUNCTION:    AcpiReleaseGlobalLock
1232 *
1233 * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1234 *
1235 * RETURN:      Status
1236 *
1237 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1238 *
1239 ******************************************************************************/
1240
1241ACPI_STATUS
1242AcpiReleaseGlobalLock (
1243    UINT32                  Handle)
1244{
1245    ACPI_STATUS             Status;
1246
1247
1248    if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1249    {
1250        return (AE_NOT_ACQUIRED);
1251    }
1252
1253    Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1254    return (Status);
1255}
1256
1257ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1258
1259#endif /* !ACPI_REDUCED_HARDWARE */
1260