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