evxface.c revision 254745
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: evxface - External interfaces for ACPI events
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
4467754Smsmith
4567754Smsmith#define __EVXFACE_C__
4667754Smsmith
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50193341Sjkim#include <contrib/dev/acpica/include/acevents.h>
51193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
5267754Smsmith
5377424Smsmith#define _COMPONENT          ACPI_EVENTS
5491116Smsmith        ACPI_MODULE_NAME    ("evxface")
5567754Smsmith
5667754Smsmith
5777424Smsmith/*******************************************************************************
5867754Smsmith *
5967754Smsmith * FUNCTION:    AcpiInstallNotifyHandler
6067754Smsmith *
6167754Smsmith * PARAMETERS:  Device          - The device for which notifies will be handled
6267754Smsmith *              HandlerType     - The type of handler:
63234623Sjkim *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
64234623Sjkim *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
65234623Sjkim *                                  ACPI_ALL_NOTIFY:    Both System and Device
6667754Smsmith *              Handler         - Address of the handler
6767754Smsmith *              Context         - Value passed to the handler on each GPE
6867754Smsmith *
6967754Smsmith * RETURN:      Status
7067754Smsmith *
71234623Sjkim * DESCRIPTION: Install a handler for notifications on an ACPI Device,
72234623Sjkim *              ThermalZone, or Processor object.
7367754Smsmith *
74234623Sjkim * NOTES:       The Root namespace object may have only one handler for each
75234623Sjkim *              type of notify (System/Device). Device/Thermal/Processor objects
76234623Sjkim *              may have one device notify handler, and multiple system notify
77234623Sjkim *              handlers.
78234623Sjkim *
7967754Smsmith ******************************************************************************/
8067754Smsmith
8167754SmsmithACPI_STATUS
8267754SmsmithAcpiInstallNotifyHandler (
8367754Smsmith    ACPI_HANDLE             Device,
8467754Smsmith    UINT32                  HandlerType,
8577424Smsmith    ACPI_NOTIFY_HANDLER     Handler,
8667754Smsmith    void                    *Context)
8767754Smsmith{
88234623Sjkim    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
8967754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
90234623Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
9191116Smsmith    ACPI_STATUS             Status;
92234623Sjkim    UINT32                  i;
9367754Smsmith
9467754Smsmith
95167802Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
9667754Smsmith
9767754Smsmith
9867754Smsmith    /* Parameter validation */
9967754Smsmith
100234623Sjkim    if ((!Device) || (!Handler) || (!HandlerType) ||
10167754Smsmith        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
10267754Smsmith    {
10367754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
10467754Smsmith    }
10567754Smsmith
10691116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
10791116Smsmith    if (ACPI_FAILURE (Status))
10891116Smsmith    {
10991116Smsmith        return_ACPI_STATUS (Status);
11091116Smsmith    }
11171867Smsmith
11267754Smsmith    /*
11371867Smsmith     * Root Object:
11471867Smsmith     * Registering a notify handler on the root object indicates that the
115193267Sjkim     * caller wishes to receive notifications for all objects. Note that
116234623Sjkim     * only one global handler can be registered per notify type.
117234623Sjkim     * Ensure that a handler is not already installed.
11867754Smsmith     */
11967754Smsmith    if (Device == ACPI_ROOT_OBJECT)
12067754Smsmith    {
121234623Sjkim        for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
12267754Smsmith        {
123234623Sjkim            if (HandlerType & (i+1))
124234623Sjkim            {
125234623Sjkim                if (AcpiGbl_GlobalNotify[i].Handler)
126234623Sjkim                {
127234623Sjkim                    Status = AE_ALREADY_EXISTS;
128234623Sjkim                    goto UnlockAndExit;
129234623Sjkim                }
13067754Smsmith
131234623Sjkim                AcpiGbl_GlobalNotify[i].Handler = Handler;
132234623Sjkim                AcpiGbl_GlobalNotify[i].Context = Context;
133234623Sjkim            }
13467754Smsmith        }
135129684Snjl
136234623Sjkim        goto UnlockAndExit; /* Global notify handler installed, all done */
13767754Smsmith    }
13867754Smsmith
13967754Smsmith    /*
14085756Smsmith     * All Other Objects:
141234623Sjkim     * Caller will only receive notifications specific to the target
142234623Sjkim     * object. Note that only certain object types are allowed to
143234623Sjkim     * receive notifications.
14467754Smsmith     */
145234623Sjkim
146234623Sjkim    /* Are Notifies allowed on this object? */
147234623Sjkim
148234623Sjkim    if (!AcpiEvIsNotifyObject (Node))
14985756Smsmith    {
150234623Sjkim        Status = AE_TYPE;
151234623Sjkim        goto UnlockAndExit;
152234623Sjkim    }
15399146Siwasaki
154234623Sjkim    /* Check for an existing internal object, might not exist */
155234623Sjkim
156234623Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
157234623Sjkim    if (!ObjDesc)
158234623Sjkim    {
159234623Sjkim        /* Create a new object */
160234623Sjkim
161234623Sjkim        ObjDesc = AcpiUtCreateInternalObject (Node->Type);
162234623Sjkim        if (!ObjDesc)
16367754Smsmith        {
164234623Sjkim            Status = AE_NO_MEMORY;
16567754Smsmith            goto UnlockAndExit;
16667754Smsmith        }
16767754Smsmith
168234623Sjkim        /* Attach new object to the Node, remove local reference */
16967754Smsmith
170234623Sjkim        Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
171234623Sjkim        AcpiUtRemoveReference (ObjDesc);
172234623Sjkim        if (ACPI_FAILURE (Status))
17367754Smsmith        {
174234623Sjkim            goto UnlockAndExit;
175234623Sjkim        }
176234623Sjkim    }
17771867Smsmith
178234623Sjkim    /* Ensure that the handler is not already installed in the lists */
179234623Sjkim
180234623Sjkim    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
181234623Sjkim    {
182234623Sjkim        if (HandlerType & (i+1))
18371867Smsmith        {
184234623Sjkim            HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
185234623Sjkim            while (HandlerObj)
18671867Smsmith            {
187234623Sjkim                if (HandlerObj->Notify.Handler == Handler)
188234623Sjkim                {
189234623Sjkim                    Status = AE_ALREADY_EXISTS;
190234623Sjkim                    goto UnlockAndExit;
191234623Sjkim                }
19267754Smsmith
193234623Sjkim                HandlerObj = HandlerObj->Notify.Next[i];
19471867Smsmith            }
19571867Smsmith        }
196234623Sjkim    }
19771867Smsmith
198234623Sjkim    /* Create and populate a new notify handler object */
19971867Smsmith
200234623Sjkim    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
201234623Sjkim    if (!HandlerObj)
202234623Sjkim    {
203234623Sjkim        Status = AE_NO_MEMORY;
204234623Sjkim        goto UnlockAndExit;
205234623Sjkim    }
20667754Smsmith
207234623Sjkim    HandlerObj->Notify.Node = Node;
208234623Sjkim    HandlerObj->Notify.HandlerType = HandlerType;
209234623Sjkim    HandlerObj->Notify.Handler = Handler;
210234623Sjkim    HandlerObj->Notify.Context = Context;
21167754Smsmith
212234623Sjkim    /* Install the handler at the list head(s) */
213234623Sjkim
214234623Sjkim    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
215234623Sjkim    {
216234623Sjkim        if (HandlerType & (i+1))
21771867Smsmith        {
218234623Sjkim            HandlerObj->Notify.Next[i] =
219234623Sjkim                ObjDesc->CommonNotify.NotifyList[i];
220129684Snjl
221234623Sjkim            ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
22271867Smsmith        }
223234623Sjkim    }
224129684Snjl
225234623Sjkim    /* Add an extra reference if handler was installed in both lists */
226129684Snjl
227234623Sjkim    if (HandlerType == ACPI_ALL_NOTIFY)
228234623Sjkim    {
229234623Sjkim        AcpiUtAddReference (HandlerObj);
23067754Smsmith    }
23167754Smsmith
23285756Smsmith
23367754SmsmithUnlockAndExit:
23491116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
23567754Smsmith    return_ACPI_STATUS (Status);
23667754Smsmith}
23767754Smsmith
238167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
23967754Smsmith
240167802Sjkim
24177424Smsmith/*******************************************************************************
24267754Smsmith *
24367754Smsmith * FUNCTION:    AcpiRemoveNotifyHandler
24467754Smsmith *
245234623Sjkim * PARAMETERS:  Device          - The device for which the handler is installed
24667754Smsmith *              HandlerType     - The type of handler:
247234623Sjkim *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
248234623Sjkim *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
249234623Sjkim *                                  ACPI_ALL_NOTIFY:    Both System and Device
25067754Smsmith *              Handler         - Address of the handler
251138287Smarks *
25267754Smsmith * RETURN:      Status
25367754Smsmith *
25467754Smsmith * DESCRIPTION: Remove a handler for notifies on an ACPI device
25567754Smsmith *
25667754Smsmith ******************************************************************************/
25767754Smsmith
25867754SmsmithACPI_STATUS
25967754SmsmithAcpiRemoveNotifyHandler (
26067754Smsmith    ACPI_HANDLE             Device,
26167754Smsmith    UINT32                  HandlerType,
26277424Smsmith    ACPI_NOTIFY_HANDLER     Handler)
26367754Smsmith{
264234623Sjkim    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
26567754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
266234623Sjkim    ACPI_OPERAND_OBJECT     *HandlerObj;
267234623Sjkim    ACPI_OPERAND_OBJECT     *PreviousHandlerObj;
26891116Smsmith    ACPI_STATUS             Status;
269234623Sjkim    UINT32                  i;
27067754Smsmith
27177424Smsmith
272167802Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
27367754Smsmith
27477424Smsmith
27567754Smsmith    /* Parameter validation */
27667754Smsmith
277234623Sjkim    if ((!Device) || (!Handler) || (!HandlerType) ||
27867754Smsmith        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
27967754Smsmith    {
28067754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
28167754Smsmith    }
28267754Smsmith
283235945Sjkim    /* Make sure all deferred notify tasks are completed */
284234623Sjkim
285235945Sjkim    AcpiOsWaitEventsComplete ();
286234623Sjkim
28791116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
28891116Smsmith    if (ACPI_FAILURE (Status))
28991116Smsmith    {
29091116Smsmith        return_ACPI_STATUS (Status);
29191116Smsmith    }
29267754Smsmith
293234623Sjkim    /* Root Object. Global handlers are removed here */
29467754Smsmith
29587031Smsmith    if (Device == ACPI_ROOT_OBJECT)
29685756Smsmith    {
297234623Sjkim        for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
29871867Smsmith        {
299234623Sjkim            if (HandlerType & (i+1))
300234623Sjkim            {
301234623Sjkim                if (!AcpiGbl_GlobalNotify[i].Handler ||
302234623Sjkim                    (AcpiGbl_GlobalNotify[i].Handler != Handler))
303234623Sjkim                {
304234623Sjkim                    Status = AE_NOT_EXIST;
305234623Sjkim                    goto UnlockAndExit;
306234623Sjkim                }
30767754Smsmith
308234623Sjkim                ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
309234623Sjkim                    "Removing global notify handler\n"));
310234623Sjkim
311234623Sjkim                AcpiGbl_GlobalNotify[i].Handler = NULL;
312234623Sjkim                AcpiGbl_GlobalNotify[i].Context = NULL;
313234623Sjkim            }
31471867Smsmith        }
315129684Snjl
316234623Sjkim        goto UnlockAndExit;
31767754Smsmith    }
31867754Smsmith
319234623Sjkim    /* All other objects: Are Notifies allowed on this object? */
320138287Smarks
321234623Sjkim    if (!AcpiEvIsNotifyObject (Node))
32285756Smsmith    {
323234623Sjkim        Status = AE_TYPE;
324234623Sjkim        goto UnlockAndExit;
325234623Sjkim    }
32699146Siwasaki
327234623Sjkim    /* Must have an existing internal object */
32867754Smsmith
329234623Sjkim    ObjDesc = AcpiNsGetAttachedObject (Node);
330234623Sjkim    if (!ObjDesc)
331234623Sjkim    {
332234623Sjkim        Status = AE_NOT_EXIST;
333234623Sjkim        goto UnlockAndExit;
334234623Sjkim    }
33567754Smsmith
336234623Sjkim    /* Internal object exists. Find the handler and remove it */
337234623Sjkim
338234623Sjkim    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
339234623Sjkim    {
340234623Sjkim        if (HandlerType & (i+1))
34171867Smsmith        {
342234623Sjkim            HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
343234623Sjkim            PreviousHandlerObj = NULL;
34467754Smsmith
345234623Sjkim            /* Attempt to find the handler in the handler list */
34671867Smsmith
347234623Sjkim            while (HandlerObj &&
348234623Sjkim                  (HandlerObj->Notify.Handler != Handler))
349129684Snjl            {
350234623Sjkim                PreviousHandlerObj = HandlerObj;
351234623Sjkim                HandlerObj = HandlerObj->Notify.Next[i];
352167802Sjkim            }
353167802Sjkim
354234623Sjkim            if (!HandlerObj)
355167802Sjkim            {
356234623Sjkim                Status = AE_NOT_EXIST;
357129684Snjl                goto UnlockAndExit;
358129684Snjl            }
359129684Snjl
360234623Sjkim            /* Remove the handler object from the list */
361129684Snjl
362234623Sjkim            if (PreviousHandlerObj) /* Handler is not at the list head */
363129684Snjl            {
364234623Sjkim                PreviousHandlerObj->Notify.Next[i] =
365234623Sjkim                    HandlerObj->Notify.Next[i];
366167802Sjkim            }
367234623Sjkim            else /* Handler is at the list head */
368167802Sjkim            {
369234623Sjkim                ObjDesc->CommonNotify.NotifyList[i] =
370234623Sjkim                    HandlerObj->Notify.Next[i];
371129684Snjl            }
37271867Smsmith
373234623Sjkim            AcpiUtRemoveReference (HandlerObj);
37471867Smsmith        }
37567754Smsmith    }
37667754Smsmith
37767754Smsmith
37867754SmsmithUnlockAndExit:
37991116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
38067754Smsmith    return_ACPI_STATUS (Status);
38167754Smsmith}
38267754Smsmith
383167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
38471867Smsmith
385167802Sjkim
38677424Smsmith/*******************************************************************************
38767754Smsmith *
388231844Sjkim * FUNCTION:    AcpiInstallExceptionHandler
389231844Sjkim *
390231844Sjkim * PARAMETERS:  Handler         - Pointer to the handler function for the
391231844Sjkim *                                event
392231844Sjkim *
393231844Sjkim * RETURN:      Status
394231844Sjkim *
395231844Sjkim * DESCRIPTION: Saves the pointer to the handler function
396231844Sjkim *
397231844Sjkim ******************************************************************************/
398231844Sjkim
399231844SjkimACPI_STATUS
400231844SjkimAcpiInstallExceptionHandler (
401231844Sjkim    ACPI_EXCEPTION_HANDLER  Handler)
402231844Sjkim{
403231844Sjkim    ACPI_STATUS             Status;
404231844Sjkim
405231844Sjkim
406231844Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
407231844Sjkim
408231844Sjkim
409231844Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
410231844Sjkim    if (ACPI_FAILURE (Status))
411231844Sjkim    {
412231844Sjkim        return_ACPI_STATUS (Status);
413231844Sjkim    }
414231844Sjkim
415231844Sjkim    /* Don't allow two handlers. */
416231844Sjkim
417231844Sjkim    if (AcpiGbl_ExceptionHandler)
418231844Sjkim    {
419231844Sjkim        Status = AE_ALREADY_EXISTS;
420231844Sjkim        goto Cleanup;
421231844Sjkim    }
422231844Sjkim
423231844Sjkim    /* Install the handler */
424231844Sjkim
425231844Sjkim    AcpiGbl_ExceptionHandler = Handler;
426231844Sjkim
427231844SjkimCleanup:
428231844Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
429231844Sjkim    return_ACPI_STATUS (Status);
430231844Sjkim}
431231844Sjkim
432231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
433231844Sjkim
434231844Sjkim
435231844Sjkim#if (!ACPI_REDUCED_HARDWARE)
436231844Sjkim/*******************************************************************************
437231844Sjkim *
438254745Sjkim * FUNCTION:    AcpiInstallSciHandler
439254745Sjkim *
440254745Sjkim * PARAMETERS:  Address             - Address of the handler
441254745Sjkim *              Context             - Value passed to the handler on each SCI
442254745Sjkim *
443254745Sjkim * RETURN:      Status
444254745Sjkim *
445254745Sjkim * DESCRIPTION: Install a handler for a System Control Interrupt.
446254745Sjkim *
447254745Sjkim ******************************************************************************/
448254745Sjkim
449254745SjkimACPI_STATUS
450254745SjkimAcpiInstallSciHandler (
451254745Sjkim    ACPI_SCI_HANDLER        Address,
452254745Sjkim    void                    *Context)
453254745Sjkim{
454254745Sjkim    ACPI_SCI_HANDLER_INFO   *NewSciHandler;
455254745Sjkim    ACPI_SCI_HANDLER_INFO   *SciHandler;
456254745Sjkim    ACPI_CPU_FLAGS          Flags;
457254745Sjkim    ACPI_STATUS             Status;
458254745Sjkim
459254745Sjkim
460254745Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
461254745Sjkim
462254745Sjkim
463254745Sjkim    if (!Address)
464254745Sjkim    {
465254745Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
466254745Sjkim    }
467254745Sjkim
468254745Sjkim    /* Allocate and init a handler object */
469254745Sjkim
470254745Sjkim    NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
471254745Sjkim    if (!NewSciHandler)
472254745Sjkim    {
473254745Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
474254745Sjkim    }
475254745Sjkim
476254745Sjkim    NewSciHandler->Address = Address;
477254745Sjkim    NewSciHandler->Context = Context;
478254745Sjkim
479254745Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
480254745Sjkim    if (ACPI_FAILURE (Status))
481254745Sjkim    {
482254745Sjkim        goto Exit;
483254745Sjkim    }
484254745Sjkim
485254745Sjkim    /* Lock list during installation */
486254745Sjkim
487254745Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
488254745Sjkim    SciHandler = AcpiGbl_SciHandlerList;
489254745Sjkim
490254745Sjkim    /* Ensure handler does not already exist */
491254745Sjkim
492254745Sjkim    while (SciHandler)
493254745Sjkim    {
494254745Sjkim        if (Address == SciHandler->Address)
495254745Sjkim        {
496254745Sjkim            Status = AE_ALREADY_EXISTS;
497254745Sjkim            goto UnlockAndExit;
498254745Sjkim        }
499254745Sjkim
500254745Sjkim        SciHandler = SciHandler->Next;
501254745Sjkim    }
502254745Sjkim
503254745Sjkim    /* Install the new handler into the global list (at head) */
504254745Sjkim
505254745Sjkim    NewSciHandler->Next = AcpiGbl_SciHandlerList;
506254745Sjkim    AcpiGbl_SciHandlerList = NewSciHandler;
507254745Sjkim
508254745Sjkim
509254745SjkimUnlockAndExit:
510254745Sjkim
511254745Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
512254745Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
513254745Sjkim
514254745SjkimExit:
515254745Sjkim    if (ACPI_FAILURE (Status))
516254745Sjkim    {
517254745Sjkim        ACPI_FREE (NewSciHandler);
518254745Sjkim    }
519254745Sjkim    return_ACPI_STATUS (Status);
520254745Sjkim}
521254745Sjkim
522254745Sjkim
523254745Sjkim/*******************************************************************************
524254745Sjkim *
525254745Sjkim * FUNCTION:    AcpiRemoveSciHandler
526254745Sjkim *
527254745Sjkim * PARAMETERS:  Address             - Address of the handler
528254745Sjkim *
529254745Sjkim * RETURN:      Status
530254745Sjkim *
531254745Sjkim * DESCRIPTION: Remove a handler for a System Control Interrupt.
532254745Sjkim *
533254745Sjkim ******************************************************************************/
534254745Sjkim
535254745SjkimACPI_STATUS
536254745SjkimAcpiRemoveSciHandler (
537254745Sjkim    ACPI_SCI_HANDLER        Address)
538254745Sjkim{
539254745Sjkim    ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
540254745Sjkim    ACPI_SCI_HANDLER_INFO   *NextSciHandler;
541254745Sjkim    ACPI_CPU_FLAGS          Flags;
542254745Sjkim    ACPI_STATUS             Status;
543254745Sjkim
544254745Sjkim
545254745Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
546254745Sjkim
547254745Sjkim
548254745Sjkim    if (!Address)
549254745Sjkim    {
550254745Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
551254745Sjkim    }
552254745Sjkim
553254745Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
554254745Sjkim    if (ACPI_FAILURE (Status))
555254745Sjkim    {
556254745Sjkim        return_ACPI_STATUS (Status);
557254745Sjkim    }
558254745Sjkim
559254745Sjkim    /* Remove the SCI handler with lock */
560254745Sjkim
561254745Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
562254745Sjkim
563254745Sjkim    PrevSciHandler = NULL;
564254745Sjkim    NextSciHandler = AcpiGbl_SciHandlerList;
565254745Sjkim    while (NextSciHandler)
566254745Sjkim    {
567254745Sjkim        if (NextSciHandler->Address == Address)
568254745Sjkim        {
569254745Sjkim            /* Unlink and free the SCI handler info block */
570254745Sjkim
571254745Sjkim            if (PrevSciHandler)
572254745Sjkim            {
573254745Sjkim                PrevSciHandler->Next = NextSciHandler->Next;
574254745Sjkim            }
575254745Sjkim            else
576254745Sjkim            {
577254745Sjkim                AcpiGbl_SciHandlerList = NextSciHandler->Next;
578254745Sjkim            }
579254745Sjkim
580254745Sjkim            AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
581254745Sjkim            ACPI_FREE (NextSciHandler);
582254745Sjkim            goto UnlockAndExit;
583254745Sjkim        }
584254745Sjkim
585254745Sjkim        PrevSciHandler = NextSciHandler;
586254745Sjkim        NextSciHandler = NextSciHandler->Next;
587254745Sjkim    }
588254745Sjkim
589254745Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
590254745Sjkim    Status = AE_NOT_EXIST;
591254745Sjkim
592254745Sjkim
593254745SjkimUnlockAndExit:
594254745Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
595254745Sjkim    return_ACPI_STATUS (Status);
596254745Sjkim}
597254745Sjkim
598254745Sjkim
599254745Sjkim/*******************************************************************************
600254745Sjkim *
601231844Sjkim * FUNCTION:    AcpiInstallGlobalEventHandler
602231844Sjkim *
603231844Sjkim * PARAMETERS:  Handler         - Pointer to the global event handler function
604231844Sjkim *              Context         - Value passed to the handler on each event
605231844Sjkim *
606231844Sjkim * RETURN:      Status
607231844Sjkim *
608231844Sjkim * DESCRIPTION: Saves the pointer to the handler function. The global handler
609231844Sjkim *              is invoked upon each incoming GPE and Fixed Event. It is
610231844Sjkim *              invoked at interrupt level at the time of the event dispatch.
611231844Sjkim *              Can be used to update event counters, etc.
612231844Sjkim *
613231844Sjkim ******************************************************************************/
614231844Sjkim
615231844SjkimACPI_STATUS
616231844SjkimAcpiInstallGlobalEventHandler (
617231844Sjkim    ACPI_GBL_EVENT_HANDLER  Handler,
618231844Sjkim    void                    *Context)
619231844Sjkim{
620231844Sjkim    ACPI_STATUS             Status;
621231844Sjkim
622231844Sjkim
623231844Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
624231844Sjkim
625231844Sjkim
626231844Sjkim    /* Parameter validation */
627231844Sjkim
628231844Sjkim    if (!Handler)
629231844Sjkim    {
630231844Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
631231844Sjkim    }
632231844Sjkim
633231844Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
634231844Sjkim    if (ACPI_FAILURE (Status))
635231844Sjkim    {
636231844Sjkim        return_ACPI_STATUS (Status);
637231844Sjkim    }
638231844Sjkim
639231844Sjkim    /* Don't allow two handlers. */
640231844Sjkim
641231844Sjkim    if (AcpiGbl_GlobalEventHandler)
642231844Sjkim    {
643231844Sjkim        Status = AE_ALREADY_EXISTS;
644231844Sjkim        goto Cleanup;
645231844Sjkim    }
646231844Sjkim
647231844Sjkim    AcpiGbl_GlobalEventHandler = Handler;
648231844Sjkim    AcpiGbl_GlobalEventHandlerContext = Context;
649231844Sjkim
650231844Sjkim
651231844SjkimCleanup:
652231844Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
653231844Sjkim    return_ACPI_STATUS (Status);
654231844Sjkim}
655231844Sjkim
656231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
657231844Sjkim
658231844Sjkim
659231844Sjkim/*******************************************************************************
660231844Sjkim *
661231844Sjkim * FUNCTION:    AcpiInstallFixedEventHandler
662231844Sjkim *
663231844Sjkim * PARAMETERS:  Event           - Event type to enable.
664231844Sjkim *              Handler         - Pointer to the handler function for the
665231844Sjkim *                                event
666231844Sjkim *              Context         - Value passed to the handler on each GPE
667231844Sjkim *
668231844Sjkim * RETURN:      Status
669231844Sjkim *
670231844Sjkim * DESCRIPTION: Saves the pointer to the handler function and then enables the
671231844Sjkim *              event.
672231844Sjkim *
673231844Sjkim ******************************************************************************/
674231844Sjkim
675231844SjkimACPI_STATUS
676231844SjkimAcpiInstallFixedEventHandler (
677231844Sjkim    UINT32                  Event,
678231844Sjkim    ACPI_EVENT_HANDLER      Handler,
679231844Sjkim    void                    *Context)
680231844Sjkim{
681231844Sjkim    ACPI_STATUS             Status;
682231844Sjkim
683231844Sjkim
684231844Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
685231844Sjkim
686231844Sjkim
687231844Sjkim    /* Parameter validation */
688231844Sjkim
689231844Sjkim    if (Event > ACPI_EVENT_MAX)
690231844Sjkim    {
691231844Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
692231844Sjkim    }
693231844Sjkim
694231844Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
695231844Sjkim    if (ACPI_FAILURE (Status))
696231844Sjkim    {
697231844Sjkim        return_ACPI_STATUS (Status);
698231844Sjkim    }
699231844Sjkim
700246849Sjkim    /* Do not allow multiple handlers */
701231844Sjkim
702246849Sjkim    if (AcpiGbl_FixedEventHandlers[Event].Handler)
703231844Sjkim    {
704231844Sjkim        Status = AE_ALREADY_EXISTS;
705231844Sjkim        goto Cleanup;
706231844Sjkim    }
707231844Sjkim
708231844Sjkim    /* Install the handler before enabling the event */
709231844Sjkim
710231844Sjkim    AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
711231844Sjkim    AcpiGbl_FixedEventHandlers[Event].Context = Context;
712231844Sjkim
713231844Sjkim    Status = AcpiEnableEvent (Event, 0);
714231844Sjkim    if (ACPI_FAILURE (Status))
715231844Sjkim    {
716246849Sjkim        ACPI_WARNING ((AE_INFO,
717246849Sjkim            "Could not enable fixed event - %s (%u)",
718246849Sjkim            AcpiUtGetEventName (Event), Event));
719231844Sjkim
720231844Sjkim        /* Remove the handler */
721231844Sjkim
722231844Sjkim        AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
723231844Sjkim        AcpiGbl_FixedEventHandlers[Event].Context = NULL;
724231844Sjkim    }
725231844Sjkim    else
726231844Sjkim    {
727231844Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
728246849Sjkim            "Enabled fixed event %s (%X), Handler=%p\n",
729246849Sjkim            AcpiUtGetEventName (Event), Event, Handler));
730231844Sjkim    }
731231844Sjkim
732231844Sjkim
733231844SjkimCleanup:
734231844Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
735231844Sjkim    return_ACPI_STATUS (Status);
736231844Sjkim}
737231844Sjkim
738231844SjkimACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
739231844Sjkim
740231844Sjkim
741231844Sjkim/*******************************************************************************
742231844Sjkim *
743231844Sjkim * FUNCTION:    AcpiRemoveFixedEventHandler
744231844Sjkim *
745231844Sjkim * PARAMETERS:  Event           - Event type to disable.
746231844Sjkim *              Handler         - Address of the handler
747231844Sjkim *
748231844Sjkim * RETURN:      Status
749231844Sjkim *
750231844Sjkim * DESCRIPTION: Disables the event and unregisters the event handler.
751231844Sjkim *
752231844Sjkim ******************************************************************************/
753231844Sjkim
754231844SjkimACPI_STATUS
755231844SjkimAcpiRemoveFixedEventHandler (
756231844Sjkim    UINT32                  Event,
757231844Sjkim    ACPI_EVENT_HANDLER      Handler)
758231844Sjkim{
759231844Sjkim    ACPI_STATUS             Status = AE_OK;
760231844Sjkim
761231844Sjkim
762231844Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
763231844Sjkim
764231844Sjkim
765231844Sjkim    /* Parameter validation */
766231844Sjkim
767231844Sjkim    if (Event > ACPI_EVENT_MAX)
768231844Sjkim    {
769231844Sjkim        return_ACPI_STATUS (AE_BAD_PARAMETER);
770231844Sjkim    }
771231844Sjkim
772231844Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
773231844Sjkim    if (ACPI_FAILURE (Status))
774231844Sjkim    {
775231844Sjkim        return_ACPI_STATUS (Status);
776231844Sjkim    }
777231844Sjkim
778231844Sjkim    /* Disable the event before removing the handler */
779231844Sjkim
780231844Sjkim    Status = AcpiDisableEvent (Event, 0);
781231844Sjkim
782231844Sjkim    /* Always Remove the handler */
783231844Sjkim
784231844Sjkim    AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
785231844Sjkim    AcpiGbl_FixedEventHandlers[Event].Context = NULL;
786231844Sjkim
787231844Sjkim    if (ACPI_FAILURE (Status))
788231844Sjkim    {
789231844Sjkim        ACPI_WARNING ((AE_INFO,
790246849Sjkim            "Could not disable fixed event - %s (%u)",
791246849Sjkim            AcpiUtGetEventName (Event), Event));
792231844Sjkim    }
793231844Sjkim    else
794231844Sjkim    {
795246849Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
796246849Sjkim            "Disabled fixed event - %s (%X)\n",
797246849Sjkim            AcpiUtGetEventName (Event), Event));
798231844Sjkim    }
799231844Sjkim
800231844Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
801231844Sjkim    return_ACPI_STATUS (Status);
802231844Sjkim}
803231844Sjkim
804231844SjkimACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
805231844Sjkim
806231844Sjkim
807231844Sjkim/*******************************************************************************
808231844Sjkim *
80967754Smsmith * FUNCTION:    AcpiInstallGpeHandler
81067754Smsmith *
811151937Sjkim * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
812151937Sjkim *                                defined GPEs)
813151937Sjkim *              GpeNumber       - The GPE number within the GPE block
81467754Smsmith *              Type            - Whether this GPE should be treated as an
81567754Smsmith *                                edge- or level-triggered interrupt.
816129684Snjl *              Address         - Address of the handler
81767754Smsmith *              Context         - Value passed to the handler on each GPE
81867754Smsmith *
81967754Smsmith * RETURN:      Status
82067754Smsmith *
82167754Smsmith * DESCRIPTION: Install a handler for a General Purpose Event.
82267754Smsmith *
82367754Smsmith ******************************************************************************/
82467754Smsmith
82567754SmsmithACPI_STATUS
82667754SmsmithAcpiInstallGpeHandler (
827117521Snjl    ACPI_HANDLE             GpeDevice,
82867754Smsmith    UINT32                  GpeNumber,
82967754Smsmith    UINT32                  Type,
830216471Sjkim    ACPI_GPE_HANDLER        Address,
83167754Smsmith    void                    *Context)
83267754Smsmith{
833129684Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
834216471Sjkim    ACPI_GPE_HANDLER_INFO   *Handler;
83591116Smsmith    ACPI_STATUS             Status;
836167802Sjkim    ACPI_CPU_FLAGS          Flags;
83767754Smsmith
83877424Smsmith
839167802Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
84067754Smsmith
84177424Smsmith
84267754Smsmith    /* Parameter validation */
84367754Smsmith
844206117Sjkim    if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
84567754Smsmith    {
84667754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
84767754Smsmith    }
84867754Smsmith
849117521Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
850117521Snjl    if (ACPI_FAILURE (Status))
851117521Snjl    {
852117521Snjl        return_ACPI_STATUS (Status);
853117521Snjl    }
854117521Snjl
855216471Sjkim    /* Allocate and init handler object (before lock) */
856216471Sjkim
857216471Sjkim    Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
858216471Sjkim    if (!Handler)
859216471Sjkim    {
860216471Sjkim        Status = AE_NO_MEMORY;
861216471Sjkim        goto UnlockAndExit;
862216471Sjkim    }
863216471Sjkim
864216471Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
865216471Sjkim
86667754Smsmith    /* Ensure that we have a valid GPE number */
86767754Smsmith
868117521Snjl    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
869114237Snjl    if (!GpeEventInfo)
87067754Smsmith    {
871117521Snjl        Status = AE_BAD_PARAMETER;
872216471Sjkim        goto FreeAndExit;
87367754Smsmith    }
87467754Smsmith
87567754Smsmith    /* Make sure that there isn't a handler there already */
87667754Smsmith
877193267Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
878193267Sjkim            ACPI_GPE_DISPATCH_HANDLER)
87967754Smsmith    {
88087031Smsmith        Status = AE_ALREADY_EXISTS;
881216471Sjkim        goto FreeAndExit;
88267754Smsmith    }
88367754Smsmith
884216471Sjkim    Handler->Address = Address;
885216471Sjkim    Handler->Context = Context;
886216471Sjkim    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
887216471Sjkim    Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
888216471Sjkim        (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
88967754Smsmith
890216471Sjkim    /*
891216471Sjkim     * If the GPE is associated with a method, it may have been enabled
892216471Sjkim     * automatically during initialization, in which case it has to be
893216471Sjkim     * disabled now to avoid spurious execution of the handler.
894216471Sjkim     */
895216471Sjkim    if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
896216471Sjkim         (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
897216471Sjkim        GpeEventInfo->RuntimeCount)
898129684Snjl    {
899216471Sjkim        Handler->OriginallyEnabled = TRUE;
900216471Sjkim        (void) AcpiEvRemoveGpeReference (GpeEventInfo);
901216471Sjkim
902216471Sjkim        /* Sanity check of original type against new type */
903216471Sjkim
904216471Sjkim        if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
905216471Sjkim        {
906216471Sjkim            ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
907216471Sjkim        }
908129684Snjl    }
90967754Smsmith
910129684Snjl    /* Install the handler */
91185756Smsmith
912129684Snjl    GpeEventInfo->Dispatch.Handler = Handler;
91399679Siwasaki
914216471Sjkim    /* Setup up dispatch flags to indicate handler (vs. method/notify) */
915129684Snjl
916193267Sjkim    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
917129684Snjl    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
918129684Snjl
919151937Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
920129684Snjl
921129684Snjl
922117521SnjlUnlockAndExit:
92391116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
92467754Smsmith    return_ACPI_STATUS (Status);
925216471Sjkim
926216471SjkimFreeAndExit:
927216471Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
928216471Sjkim    ACPI_FREE (Handler);
929216471Sjkim    goto UnlockAndExit;
93067754Smsmith}
93167754Smsmith
932167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
93367754Smsmith
934167802Sjkim
93577424Smsmith/*******************************************************************************
93667754Smsmith *
93767754Smsmith * FUNCTION:    AcpiRemoveGpeHandler
93867754Smsmith *
939151937Sjkim * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
940151937Sjkim *                                defined GPEs)
941151937Sjkim *              GpeNumber       - The event to remove a handler
942129684Snjl *              Address         - Address of the handler
94367754Smsmith *
94467754Smsmith * RETURN:      Status
94567754Smsmith *
94667754Smsmith * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
94767754Smsmith *
94867754Smsmith ******************************************************************************/
94967754Smsmith
95067754SmsmithACPI_STATUS
95167754SmsmithAcpiRemoveGpeHandler (
952117521Snjl    ACPI_HANDLE             GpeDevice,
95367754Smsmith    UINT32                  GpeNumber,
954216471Sjkim    ACPI_GPE_HANDLER        Address)
95567754Smsmith{
956129684Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
957216471Sjkim    ACPI_GPE_HANDLER_INFO   *Handler;
95891116Smsmith    ACPI_STATUS             Status;
959167802Sjkim    ACPI_CPU_FLAGS          Flags;
96067754Smsmith
96167754Smsmith
962167802Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
96367754Smsmith
96467754Smsmith
96567754Smsmith    /* Parameter validation */
96667754Smsmith
967129684Snjl    if (!Address)
96867754Smsmith    {
96967754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
97067754Smsmith    }
97167754Smsmith
972235945Sjkim    /* Make sure all deferred GPE tasks are completed */
973235945Sjkim
974235945Sjkim    AcpiOsWaitEventsComplete ();
975235945Sjkim
976117521Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
977117521Snjl    if (ACPI_FAILURE (Status))
978117521Snjl    {
979117521Snjl        return_ACPI_STATUS (Status);
980117521Snjl    }
981117521Snjl
982216471Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
983216471Sjkim
98467754Smsmith    /* Ensure that we have a valid GPE number */
98567754Smsmith
986117521Snjl    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
987114237Snjl    if (!GpeEventInfo)
98867754Smsmith    {
989117521Snjl        Status = AE_BAD_PARAMETER;
990117521Snjl        goto UnlockAndExit;
99167754Smsmith    }
99267754Smsmith
993129684Snjl    /* Make sure that a handler is indeed installed */
99467754Smsmith
995193267Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
996193267Sjkim            ACPI_GPE_DISPATCH_HANDLER)
99799679Siwasaki    {
998129684Snjl        Status = AE_NOT_EXIST;
999117521Snjl        goto UnlockAndExit;
100099679Siwasaki    }
100167754Smsmith
100267754Smsmith    /* Make sure that the installed handler is the same */
100367754Smsmith
1004129684Snjl    if (GpeEventInfo->Dispatch.Handler->Address != Address)
100567754Smsmith    {
100667754Smsmith        Status = AE_BAD_PARAMETER;
1007117521Snjl        goto UnlockAndExit;
100867754Smsmith    }
100967754Smsmith
101067754Smsmith    /* Remove the handler */
101167754Smsmith
1012129684Snjl    Handler = GpeEventInfo->Dispatch.Handler;
1013129684Snjl
1014129684Snjl    /* Restore Method node (if any), set dispatch flags */
1015129684Snjl
1016129684Snjl    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1017216471Sjkim    GpeEventInfo->Flags &=
1018216471Sjkim        ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1019216471Sjkim    GpeEventInfo->Flags |= Handler->OriginalFlags;
1020216471Sjkim
1021216471Sjkim    /*
1022216471Sjkim     * If the GPE was previously associated with a method and it was
1023216471Sjkim     * enabled, it should be enabled at this point to restore the
1024216471Sjkim     * post-initialization configuration.
1025216471Sjkim     */
1026216471Sjkim    if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
1027216471Sjkim        Handler->OriginallyEnabled)
1028129684Snjl    {
1029216471Sjkim        (void) AcpiEvAddGpeReference (GpeEventInfo);
1030129684Snjl    }
103167754Smsmith
1032129684Snjl    /* Now we can free the handler object */
103385756Smsmith
1034167802Sjkim    ACPI_FREE (Handler);
1035129684Snjl
1036129684Snjl
1037117521SnjlUnlockAndExit:
1038216471Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
103991116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
104067754Smsmith    return_ACPI_STATUS (Status);
104167754Smsmith}
104267754Smsmith
1043167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
104467754Smsmith
1045167802Sjkim
104677424Smsmith/*******************************************************************************
104767754Smsmith *
104867754Smsmith * FUNCTION:    AcpiAcquireGlobalLock
104967754Smsmith *
105067754Smsmith * PARAMETERS:  Timeout         - How long the caller is willing to wait
1051151937Sjkim *              Handle          - Where the handle to the lock is returned
1052151937Sjkim *                                (if acquired)
105367754Smsmith *
105467754Smsmith * RETURN:      Status
105567754Smsmith *
105667754Smsmith * DESCRIPTION: Acquire the ACPI Global Lock
105767754Smsmith *
1058167802Sjkim * Note: Allows callers with the same thread ID to acquire the global lock
1059167802Sjkim * multiple times. In other words, externally, the behavior of the global lock
1060167802Sjkim * is identical to an AML mutex. On the first acquire, a new handle is
1061167802Sjkim * returned. On any subsequent calls to acquire by the same thread, the same
1062167802Sjkim * handle is returned.
1063167802Sjkim *
106467754Smsmith ******************************************************************************/
106585756Smsmith
106667754SmsmithACPI_STATUS
106767754SmsmithAcpiAcquireGlobalLock (
1068107325Siwasaki    UINT16                  Timeout,
106991116Smsmith    UINT32                  *Handle)
107067754Smsmith{
107167754Smsmith    ACPI_STATUS             Status;
107267754Smsmith
107367754Smsmith
107491116Smsmith    if (!Handle)
107591116Smsmith    {
107691116Smsmith        return (AE_BAD_PARAMETER);
107791116Smsmith    }
107891116Smsmith
1079167802Sjkim    /* Must lock interpreter to prevent race conditions */
108077424Smsmith
1081167802Sjkim    AcpiExEnterInterpreter ();
108267754Smsmith
1083167802Sjkim    Status = AcpiExAcquireMutexObject (Timeout,
1084167802Sjkim                AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1085167802Sjkim
108691116Smsmith    if (ACPI_SUCCESS (Status))
108791116Smsmith    {
1088172314Sjkim        /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1089167802Sjkim
109091116Smsmith        *Handle = AcpiGbl_GlobalLockHandle;
109191116Smsmith    }
109291116Smsmith
1093167802Sjkim    AcpiExExitInterpreter ();
109467754Smsmith    return (Status);
109567754Smsmith}
109667754Smsmith
1097167802SjkimACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
109867754Smsmith
1099167802Sjkim
110077424Smsmith/*******************************************************************************
110167754Smsmith *
110267754Smsmith * FUNCTION:    AcpiReleaseGlobalLock
110367754Smsmith *
110467754Smsmith * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
110567754Smsmith *
110667754Smsmith * RETURN:      Status
110767754Smsmith *
1108151937Sjkim * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
110967754Smsmith *
111067754Smsmith ******************************************************************************/
111167754Smsmith
111267754SmsmithACPI_STATUS
111367754SmsmithAcpiReleaseGlobalLock (
111491116Smsmith    UINT32                  Handle)
111567754Smsmith{
111699679Siwasaki    ACPI_STATUS             Status;
111785756Smsmith
111899679Siwasaki
1119167802Sjkim    if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
112091116Smsmith    {
112191116Smsmith        return (AE_NOT_ACQUIRED);
112291116Smsmith    }
112391116Smsmith
1124167802Sjkim    Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
112599679Siwasaki    return (Status);
112667754Smsmith}
112767754Smsmith
1128167802SjkimACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
112967754Smsmith
1130231844Sjkim#endif /* !ACPI_REDUCED_HARDWARE */
1131