evmisc.c revision 99146
129088Smarkm/******************************************************************************
229088Smarkm *
329088Smarkm * Module Name: evmisc - Miscellaneous event manager support functions
429088Smarkm *              $Revision: 48 $
529088Smarkm *
629088Smarkm *****************************************************************************/
729088Smarkm
829088Smarkm/******************************************************************************
929088Smarkm *
1029088Smarkm * 1. Copyright Notice
1129088Smarkm *
1229088Smarkm * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp.
1329088Smarkm * All rights reserved.
1429088Smarkm *
1529088Smarkm * 2. License
1629088Smarkm *
1729088Smarkm * 2.1. This is your license from Intel Corp. under its intellectual property
1829088Smarkm * rights.  You may have additional license terms from the party that provided
1929088Smarkm * you this software, covering your right to use that party's intellectual
2029088Smarkm * property rights.
2129088Smarkm *
2229088Smarkm * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2329088Smarkm * copy of the source code appearing in this file ("Covered Code") an
2429088Smarkm * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2529088Smarkm * base code distributed originally by Intel ("Original Intel Code") to copy,
2629088Smarkm * make derivatives, distribute, use and display any portion of the Covered
2729088Smarkm * Code in any form, with the right to sublicense such rights; and
2829088Smarkm *
2929088Smarkm * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3029088Smarkm * license (with the right to sublicense), under only those claims of Intel
3129088Smarkm * patents that are infringed by the Original Intel Code, to make, use, sell,
3229088Smarkm * offer to sell, and import the Covered Code and derivative works thereof
3329088Smarkm * solely to the minimum extent necessary to exercise the above copyright
3429088Smarkm * license, and in no event shall the patent license extend to any additions
3563248Speter * to or modifications of the Original Intel Code.  No other license or right
3629181Smarkm * is granted directly or by implication, estoppel or otherwise;
3763248Speter *
3863248Speter * The above copyright and patent license is granted only if the following
3963248Speter * conditions are met:
4063248Speter *
4129088Smarkm * 3. Conditions
4229088Smarkm *
4329088Smarkm * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4429088Smarkm * Redistribution of source code of any substantial portion of the Covered
4529088Smarkm * Code or modification with rights to further distribute source must include
4629088Smarkm * the above Copyright Notice, the above License, this list of Conditions,
4729088Smarkm * and the following Disclaimer and Export Compliance provision.  In addition,
4829088Smarkm * Licensee must cause all Covered Code to which Licensee contributes to
4929088Smarkm * contain a file documenting the changes Licensee made to create that Covered
5029088Smarkm * Code and the date of any change.  Licensee must include in that file the
5129088Smarkm * documentation of any changes made by any predecessor Licensee.  Licensee
5229088Smarkm * must include a prominent statement that the modification is derived,
5329088Smarkm * directly or indirectly, from Original Intel Code.
5429088Smarkm *
5529088Smarkm * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5629088Smarkm * Redistribution of source code of any substantial portion of the Covered
5729181Smarkm * Code or modification without rights to further distribute source must
5829181Smarkm * include the following Disclaimer and Export Compliance provision in the
5929181Smarkm * documentation and/or other materials provided with distribution.  In
6029088Smarkm * addition, Licensee may not authorize further sublicense of source of any
6129088Smarkm * portion of the Covered Code, and must include terms to the effect that the
6229088Smarkm * license from Licensee to its licensee is limited to the intellectual
6329088Smarkm * property embodied in the software Licensee provides to its licensee, and
6429088Smarkm * not to intellectual property embodied in modifications its licensee may
6529088Smarkm * make.
6629088Smarkm *
6729181Smarkm * 3.3. Redistribution of Executable. Redistribution in executable form of any
6829181Smarkm * substantial portion of the Covered Code or modification must reproduce the
6929181Smarkm * above Copyright Notice, and the following Disclaimer and Export Compliance
7029181Smarkm * provision in the documentation and/or other materials provided with the
7129181Smarkm * distribution.
7229181Smarkm *
7329181Smarkm * 3.4. Intel retains all right, title, and interest in and to the Original
7429088Smarkm * Intel Code.
7529088Smarkm *
7629088Smarkm * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7729088Smarkm * Intel shall be used in advertising or otherwise to promote the sale, use or
7829088Smarkm * other dealings in products derived from or relating to the Covered Code
7929088Smarkm * without prior written authorization from Intel.
8029088Smarkm *
8129088Smarkm * 4. Disclaimer and Export Compliance
8229088Smarkm *
8329088Smarkm * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8429088Smarkm * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8529088Smarkm * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8629088Smarkm * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8729088Smarkm * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8829088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8929088Smarkm * PARTICULAR PURPOSE.
9029088Smarkm *
9129088Smarkm * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9229088Smarkm * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9329088Smarkm * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9429088Smarkm * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9529088Smarkm * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9629088Smarkm * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9729088Smarkm * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9829088Smarkm * LIMITED REMEDY.
9929088Smarkm *
10029088Smarkm * 4.3. Licensee shall not export, either directly or indirectly, any of this
10129088Smarkm * software or system incorporating such software without first obtaining any
10229088Smarkm * required license or other approval from the U. S. Department of Commerce or
10329088Smarkm * any other agency or department of the United States Government.  In the
10429088Smarkm * event Licensee exports any such software from the United States or
10529088Smarkm * re-exports any such software from a foreign destination, Licensee shall
10629088Smarkm * ensure that the distribution and export/re-export of the software is in
10729088Smarkm * compliance with all laws, regulations, orders, or other restrictions of the
10829088Smarkm * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10929088Smarkm * any of its subsidiaries will export/re-export any technical data, process,
11029088Smarkm * software, or service, directly or indirectly, to any country for which the
11129088Smarkm * United States government or any agency thereof requires an export license,
11229088Smarkm * other governmental approval, or letter of assurance, without first obtaining
11329088Smarkm * such license, approval or letter.
11429088Smarkm *
11529088Smarkm *****************************************************************************/
11629088Smarkm
11729088Smarkm#include "acpi.h"
11829088Smarkm#include "acevents.h"
11929088Smarkm#include "acnamesp.h"
12029088Smarkm#include "acinterp.h"
12129088Smarkm#include "achware.h"
12229181Smarkm
12347973Sru#define _COMPONENT          ACPI_EVENTS
12429181Smarkm        ACPI_MODULE_NAME    ("evmisc")
12529088Smarkm
12629088Smarkm
12729088Smarkm/*******************************************************************************
12829088Smarkm *
12929088Smarkm * FUNCTION:    AcpiEvIsNotifyObject
13029088Smarkm *
13129088Smarkm * PARAMETERS:  Node            - Node to check
13229088Smarkm *
13329088Smarkm * RETURN:      TRUE if notifies allowed on this object
13429088Smarkm *
13529088Smarkm * DESCRIPTION: Check type of node for a object that supports notifies.
13629088Smarkm *
13729088Smarkm *              TBD: This could be replaced by a flag bit in the node.
13829088Smarkm *
13929088Smarkm ******************************************************************************/
14029088Smarkm
14129088SmarkmBOOLEAN
14229088SmarkmAcpiEvIsNotifyObject (
14329088Smarkm    ACPI_NAMESPACE_NODE     *Node)
14429088Smarkm{
14529088Smarkm    switch (Node->Type)
14629088Smarkm    {
14729088Smarkm    case ACPI_TYPE_DEVICE:
14829088Smarkm    case ACPI_TYPE_PROCESSOR:
14929088Smarkm    case ACPI_TYPE_POWER:
15029088Smarkm    case ACPI_TYPE_THERMAL:
15129088Smarkm        /*
15229088Smarkm         * These are the ONLY objects that can receive ACPI notifications
15329088Smarkm         */
15429088Smarkm        return (TRUE);
15529088Smarkm
15629088Smarkm    default:
15729088Smarkm        return (FALSE);
15829088Smarkm    }
15929088Smarkm}
16029088Smarkm
16129088Smarkm
16229088Smarkm/*******************************************************************************
16329088Smarkm *
16429088Smarkm * FUNCTION:    AcpiEvGetGpeRegisterIndex
16529088Smarkm *
16629088Smarkm * PARAMETERS:  GpeNumber       - Raw GPE number
16729088Smarkm *
16829088Smarkm * RETURN:      None.
16929088Smarkm *
17029088Smarkm * DESCRIPTION: Returns the register index (index into the GPE register info
17129088Smarkm *              table) associated with this GPE.
17229088Smarkm *
17329088Smarkm ******************************************************************************/
17429088Smarkm
17529088SmarkmUINT32
17629088SmarkmAcpiEvGetGpeRegisterIndex (
17729088Smarkm    UINT32                  GpeNumber)
17829088Smarkm{
17929088Smarkm
18029088Smarkm    if (GpeNumber > AcpiGbl_GpeNumberMax)
18129088Smarkm    {
18229088Smarkm        return (ACPI_GPE_INVALID);
18329088Smarkm    }
18429088Smarkm
18529088Smarkm    return (ACPI_DIV_8 (AcpiGbl_GpeNumberToIndex[GpeNumber].NumberIndex));
18629088Smarkm}
18729088Smarkm
18829088Smarkm
18929088Smarkm/*******************************************************************************
19029088Smarkm *
19129088Smarkm * FUNCTION:    AcpiEvGetGpeNumberIndex
19229088Smarkm *
19329088Smarkm * PARAMETERS:  GpeNumber       - Raw GPE number
19429088Smarkm *
19529088Smarkm * RETURN:      None.
19629088Smarkm *
19729088Smarkm * DESCRIPTION: Returns the number index (index into the GPE number info table)
19829088Smarkm *              associated with this GPE.
19929088Smarkm *
20029088Smarkm ******************************************************************************/
20129088Smarkm
20229088SmarkmUINT32
20329088SmarkmAcpiEvGetGpeNumberIndex (
20429088Smarkm    UINT32                  GpeNumber)
20529088Smarkm{
20629088Smarkm
20729088Smarkm    if (GpeNumber > AcpiGbl_GpeNumberMax)
20829088Smarkm    {
20929088Smarkm        return (ACPI_GPE_INVALID);
21029088Smarkm    }
21129088Smarkm
21229088Smarkm    return (AcpiGbl_GpeNumberToIndex[GpeNumber].NumberIndex);
21329088Smarkm}
21429088Smarkm
21529088Smarkm
21629088Smarkm/*******************************************************************************
21729088Smarkm *
21829088Smarkm * FUNCTION:    AcpiEvQueueNotifyRequest
21929088Smarkm *
22029088Smarkm * PARAMETERS:
22129088Smarkm *
22229088Smarkm * RETURN:      None.
22329088Smarkm *
22429088Smarkm * DESCRIPTION: Dispatch a device notification event to a previously
22529088Smarkm *              installed handler.
22629088Smarkm *
22729088Smarkm ******************************************************************************/
22829088Smarkm
22929088SmarkmACPI_STATUS
23029088SmarkmAcpiEvQueueNotifyRequest (
23129088Smarkm    ACPI_NAMESPACE_NODE     *Node,
23229088Smarkm    UINT32                  NotifyValue)
23329088Smarkm{
23429088Smarkm    ACPI_OPERAND_OBJECT     *ObjDesc;
23529088Smarkm    ACPI_OPERAND_OBJECT     *HandlerObj = NULL;
23629088Smarkm    ACPI_GENERIC_STATE      *NotifyInfo;
23729088Smarkm    ACPI_STATUS             Status = AE_OK;
23829088Smarkm
23929088Smarkm
24029088Smarkm    ACPI_FUNCTION_NAME ("EvQueueNotifyRequest");
24129088Smarkm
24229088Smarkm
24329088Smarkm    /*
24429088Smarkm     * For value 1 (Ejection Request), some device method may need to be run.
24529088Smarkm     * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
24629088Smarkm     * For value 0x80 (Status Change) on the power button or sleep button,
24729088Smarkm     * initiate soft-off or sleep operation?
24829088Smarkm     */
24929088Smarkm    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
25029088Smarkm        "Dispatching Notify(%X) on node %p\n", NotifyValue, Node));
25129088Smarkm
25229088Smarkm    switch (NotifyValue)
25329088Smarkm    {
25429088Smarkm    case 0:
25529088Smarkm        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Re-enumerate Devices\n"));
25629088Smarkm        break;
25729088Smarkm
25829088Smarkm    case 1:
25929088Smarkm        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Ejection Request\n"));
26029088Smarkm        break;
26129088Smarkm
26229088Smarkm    case 2:
26329088Smarkm        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Device Wake\n"));
26429088Smarkm        break;
26529088Smarkm
26629088Smarkm    case 0x80:
26729088Smarkm        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: Status Change\n"));
26829088Smarkm        break;
26929088Smarkm
27029088Smarkm    default:
27129088Smarkm        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Unknown Notify Value: %X \n", NotifyValue));
27229088Smarkm        break;
27329088Smarkm    }
27429088Smarkm
27529088Smarkm    /*
27629088Smarkm     * Get the notify object attached to the device Node
27729088Smarkm     */
27829088Smarkm    ObjDesc = AcpiNsGetAttachedObject (Node);
27929088Smarkm    if (ObjDesc)
28029088Smarkm    {
28129088Smarkm        /* We have the notify object, Get the right handler */
28229088Smarkm
28329088Smarkm        switch (Node->Type)
28429088Smarkm        {
28529088Smarkm        case ACPI_TYPE_DEVICE:
28629088Smarkm
28729088Smarkm            if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
28829088Smarkm            {
28929088Smarkm                HandlerObj = ObjDesc->Device.SysHandler;
29029088Smarkm            }
29129088Smarkm            else
29229088Smarkm            {
29329088Smarkm                HandlerObj = ObjDesc->Device.DrvHandler;
29429088Smarkm            }
29529088Smarkm            break;
29629088Smarkm
29729088Smarkm
29829088Smarkm        case ACPI_TYPE_THERMAL:
29929088Smarkm
30029088Smarkm            if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
30129088Smarkm            {
30229088Smarkm                HandlerObj = ObjDesc->ThermalZone.SysHandler;
30329088Smarkm            }
30429088Smarkm            else
30529088Smarkm            {
30629088Smarkm                HandlerObj = ObjDesc->ThermalZone.DrvHandler;
30729088Smarkm            }
30829088Smarkm            break;
30929088Smarkm        }
31029088Smarkm    }
31129088Smarkm
31229088Smarkm    /* If there is any handler to run, schedule the dispatcher */
31329088Smarkm
31429088Smarkm    if ((AcpiGbl_SysNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) ||
31529088Smarkm        (AcpiGbl_DrvNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY))  ||
31629088Smarkm        HandlerObj)
31729088Smarkm    {
31829088Smarkm        NotifyInfo = AcpiUtCreateGenericState ();
31929088Smarkm        if (!NotifyInfo)
32029088Smarkm        {
32129088Smarkm            return (AE_NO_MEMORY);
32229088Smarkm        }
32329088Smarkm
32429088Smarkm        NotifyInfo->Common.DataType   = ACPI_DESC_TYPE_STATE_NOTIFY;
32529088Smarkm        NotifyInfo->Notify.Node       = Node;
32629088Smarkm        NotifyInfo->Notify.Value      = (UINT16) NotifyValue;
32729088Smarkm        NotifyInfo->Notify.HandlerObj = HandlerObj;
32829088Smarkm
32929088Smarkm        Status = AcpiOsQueueForExecution (OSD_PRIORITY_HIGH,
33029088Smarkm                        AcpiEvNotifyDispatch, NotifyInfo);
33129088Smarkm        if (ACPI_FAILURE (Status))
33229088Smarkm        {
33329088Smarkm            AcpiUtDeleteGenericState (NotifyInfo);
33429088Smarkm        }
33529088Smarkm    }
33629088Smarkm
33729088Smarkm    if (!HandlerObj)
33829088Smarkm    {
33929088Smarkm        /* There is no per-device notify handler for this device */
34029088Smarkm
34129088Smarkm        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for node %p \n", Node));
34229088Smarkm    }
34329088Smarkm
34429088Smarkm    return (Status);
34529088Smarkm}
34629088Smarkm
34729088Smarkm
34829088Smarkm/*******************************************************************************
34929088Smarkm *
35029088Smarkm * FUNCTION:    AcpiEvNotifyDispatch
35129088Smarkm *
35229088Smarkm * PARAMETERS:
35329088Smarkm *
35429088Smarkm * RETURN:      None.
35529088Smarkm *
35629088Smarkm * DESCRIPTION: Dispatch a device notification event to a previously
35729088Smarkm *              installed handler.
35829088Smarkm *
35929088Smarkm ******************************************************************************/
36029088Smarkm
36129088Smarkmvoid ACPI_SYSTEM_XFACE
36229088SmarkmAcpiEvNotifyDispatch (
36329088Smarkm    void                    *Context)
36429088Smarkm{
36529088Smarkm    ACPI_GENERIC_STATE      *NotifyInfo = (ACPI_GENERIC_STATE *) Context;
36629088Smarkm    ACPI_NOTIFY_HANDLER     GlobalHandler = NULL;
36729088Smarkm    void                    *GlobalContext = NULL;
36829088Smarkm    ACPI_OPERAND_OBJECT     *HandlerObj;
36929088Smarkm
37029088Smarkm
37129088Smarkm    ACPI_FUNCTION_ENTRY ();
37229088Smarkm
37329088Smarkm
37429088Smarkm    /*
37529088Smarkm     * We will invoke a global notify handler if installed.
37629088Smarkm     * This is done _before_ we invoke the per-device handler attached to the device.
37729088Smarkm     */
37829088Smarkm    if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY)
37929088Smarkm    {
38029088Smarkm        /* Global system notification handler */
38129088Smarkm
38229088Smarkm        if (AcpiGbl_SysNotify.Handler)
38329088Smarkm        {
38429088Smarkm            GlobalHandler = AcpiGbl_SysNotify.Handler;
38529088Smarkm            GlobalContext = AcpiGbl_SysNotify.Context;
38629088Smarkm        }
38729088Smarkm    }
38829088Smarkm    else
38929088Smarkm    {
39029088Smarkm        /* Global driver notification handler */
39129088Smarkm
39229088Smarkm        if (AcpiGbl_DrvNotify.Handler)
39329088Smarkm        {
39429088Smarkm            GlobalHandler = AcpiGbl_DrvNotify.Handler;
39529088Smarkm            GlobalContext = AcpiGbl_DrvNotify.Context;
39629088Smarkm        }
39729088Smarkm    }
39829088Smarkm
39929088Smarkm    /* Invoke the system handler first, if present */
40029088Smarkm
40129088Smarkm    if (GlobalHandler)
40229088Smarkm    {
40329088Smarkm        GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, GlobalContext);
40429088Smarkm    }
40529088Smarkm
40629088Smarkm    /* Now invoke the per-device handler, if present */
40729088Smarkm
40829088Smarkm    HandlerObj = NotifyInfo->Notify.HandlerObj;
40929088Smarkm    if (HandlerObj)
41029088Smarkm    {
41129088Smarkm        HandlerObj->NotifyHandler.Handler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value,
41229088Smarkm                        HandlerObj->NotifyHandler.Context);
41329088Smarkm    }
41429088Smarkm
41529088Smarkm    /* All done with the info object */
41629088Smarkm
41729088Smarkm    AcpiUtDeleteGenericState (NotifyInfo);
41829088Smarkm}
41929088Smarkm
42029088Smarkm
42129088Smarkm/*******************************************************************************
42229088Smarkm *
42329088Smarkm * FUNCTION:    AcpiEvGlobalLockThread
42429088Smarkm *
42529088Smarkm * RETURN:      None
42629088Smarkm *
42729088Smarkm * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
42829088Smarkm *              Global Lock.  Simply signal all threads that are waiting
42929088Smarkm *              for the lock.
43029088Smarkm *
43129088Smarkm ******************************************************************************/
43229088Smarkm
43329088Smarkmstatic void ACPI_SYSTEM_XFACE
43429088SmarkmAcpiEvGlobalLockThread (
43529088Smarkm    void                    *Context)
43629088Smarkm{
43729088Smarkm
43829088Smarkm    /* Signal threads that are waiting for the lock */
43929088Smarkm
44029088Smarkm    if (AcpiGbl_GlobalLockThreadCount)
44129088Smarkm    {
44229088Smarkm        /* Send sufficient units to the semaphore */
44329088Smarkm
44429088Smarkm        AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore,
44529088Smarkm                                AcpiGbl_GlobalLockThreadCount);
44629088Smarkm    }
44729088Smarkm}
44829088Smarkm
44929088Smarkm
45029088Smarkm/*******************************************************************************
45129088Smarkm *
45229088Smarkm * FUNCTION:    AcpiEvGlobalLockHandler
45329088Smarkm *
45429088Smarkm * RETURN:      Status
45529088Smarkm *
45629088Smarkm * DESCRIPTION: Invoked directly from the SCI handler when a global lock
45729088Smarkm *              release interrupt occurs.  Grab the global lock and queue
45829088Smarkm *              the global lock thread for execution
45929088Smarkm *
46029088Smarkm ******************************************************************************/
46129088Smarkm
46229088Smarkmstatic UINT32
46329088SmarkmAcpiEvGlobalLockHandler (
46429088Smarkm    void                    *Context)
46529088Smarkm{
46629088Smarkm    BOOLEAN                 Acquired = FALSE;
46729088Smarkm
46829088Smarkm
46929088Smarkm    /*
47029088Smarkm     * Attempt to get the lock
47129088Smarkm     * If we don't get it now, it will be marked pending and we will
47229088Smarkm     * take another interrupt when it becomes free.
47329088Smarkm     */
47429088Smarkm    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired);
47529088Smarkm    if (Acquired)
47629088Smarkm    {
47729088Smarkm        /* Got the lock, now wake all threads waiting for it */
47829088Smarkm
47929088Smarkm        AcpiGbl_GlobalLockAcquired = TRUE;
48029088Smarkm
48129088Smarkm        /* Run the Global Lock thread which will signal all waiting threads */
48229088Smarkm
48329088Smarkm        AcpiOsQueueForExecution (OSD_PRIORITY_HIGH, AcpiEvGlobalLockThread,
48429088Smarkm                                    Context);
48529088Smarkm    }
48629088Smarkm
48729088Smarkm    return (ACPI_INTERRUPT_HANDLED);
48829088Smarkm}
48929088Smarkm
49029088Smarkm
49129088Smarkm/*******************************************************************************
49229088Smarkm *
49329088Smarkm * FUNCTION:    AcpiEvInitGlobalLockHandler
49429088Smarkm *
49529088Smarkm * RETURN:      Status
49629088Smarkm *
49729088Smarkm * DESCRIPTION: Install a handler for the global lock release event
49829088Smarkm *
49929088Smarkm ******************************************************************************/
50029088Smarkm
50129088SmarkmACPI_STATUS
50229088SmarkmAcpiEvInitGlobalLockHandler (void)
50329088Smarkm{
50429088Smarkm    ACPI_STATUS             Status;
50529088Smarkm
50629088Smarkm
50729088Smarkm    ACPI_FUNCTION_TRACE ("EvInitGlobalLockHandler");
50829088Smarkm
50929088Smarkm
51029088Smarkm    AcpiGbl_GlobalLockPresent = TRUE;
51129088Smarkm    Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL,
51229088Smarkm                                            AcpiEvGlobalLockHandler, NULL);
51329088Smarkm
51429088Smarkm    /*
51529088Smarkm     * If the global lock does not exist on this platform, the attempt
51629088Smarkm     * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)
51729088Smarkm     * Map to AE_OK, but mark global lock as not present.
51829088Smarkm     * Any attempt to actually use the global lock will be flagged
51929088Smarkm     * with an error.
52029088Smarkm     */
52129088Smarkm    if (Status == AE_NO_HARDWARE_RESPONSE)
52229088Smarkm    {
52329088Smarkm        AcpiGbl_GlobalLockPresent = FALSE;
52429088Smarkm        Status = AE_OK;
52529088Smarkm    }
52629088Smarkm
52729088Smarkm    return_ACPI_STATUS (Status);
52829088Smarkm}
52929088Smarkm
53029088Smarkm
53129088Smarkm/******************************************************************************
53229088Smarkm *
53329088Smarkm * FUNCTION:    AcpiEvAcquireGlobalLock
53429088Smarkm *
53529088Smarkm * RETURN:      Status
53629088Smarkm *
53729088Smarkm * DESCRIPTION: Attempt to gain ownership of the Global Lock.
53829088Smarkm *
53929088Smarkm *****************************************************************************/
54029088Smarkm
54129088SmarkmACPI_STATUS
54229088SmarkmAcpiEvAcquireGlobalLock (
54329088Smarkm    UINT32                  Timeout)
54429088Smarkm{
54529088Smarkm    ACPI_STATUS             Status = AE_OK;
54629088Smarkm    BOOLEAN                 Acquired = FALSE;
54729088Smarkm
54829088Smarkm
54929088Smarkm    ACPI_FUNCTION_TRACE ("EvAcquireGlobalLock");
55029088Smarkm
55129088Smarkm
55229088Smarkm    /* Make sure that we actually have a global lock */
55329088Smarkm
55429088Smarkm    if (!AcpiGbl_GlobalLockPresent)
55529088Smarkm    {
55629088Smarkm        return_ACPI_STATUS (AE_NO_GLOBAL_LOCK);
55729088Smarkm    }
55829088Smarkm
55929088Smarkm    /* One more thread wants the global lock */
56029088Smarkm
56129088Smarkm    AcpiGbl_GlobalLockThreadCount++;
56229088Smarkm
56329088Smarkm    /* If we (OS side vs. BIOS side) have the hardware lock already, we are done */
56429088Smarkm
56529088Smarkm    if (AcpiGbl_GlobalLockAcquired)
56629088Smarkm    {
56729088Smarkm        return_ACPI_STATUS (AE_OK);
56829088Smarkm    }
56929088Smarkm
57029088Smarkm    /* We must acquire the actual hardware lock */
57129088Smarkm
57229088Smarkm    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired);
57329088Smarkm    if (Acquired)
57429088Smarkm    {
57529088Smarkm       /* We got the lock */
57629088Smarkm
57729088Smarkm        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Acquired the HW Global Lock\n"));
57829088Smarkm
57929088Smarkm        AcpiGbl_GlobalLockAcquired = TRUE;
58029088Smarkm        return_ACPI_STATUS (AE_OK);
58129088Smarkm    }
58229088Smarkm
58329088Smarkm    /*
58429088Smarkm     * Did not get the lock.  The pending bit was set above, and we must now
58529088Smarkm     * wait until we get the global lock released interrupt.
58629088Smarkm     */
58729088Smarkm    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Waiting for the HW Global Lock\n"));
58829088Smarkm
58929088Smarkm    /*
59029088Smarkm     * Acquire the global lock semaphore first.
59129088Smarkm     * Since this wait will block, we must release the interpreter
59229088Smarkm     */
59329088Smarkm    Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore,
59429088Smarkm                                            Timeout);
59529088Smarkm    return_ACPI_STATUS (Status);
59629088Smarkm}
59729088Smarkm
59829088Smarkm
59929088Smarkm/*******************************************************************************
60029088Smarkm *
60129088Smarkm * FUNCTION:    AcpiEvReleaseGlobalLock
60229088Smarkm *
60329088Smarkm * DESCRIPTION: Releases ownership of the Global Lock.
60429088Smarkm *
60529088Smarkm ******************************************************************************/
60629088Smarkm
60729088Smarkmvoid
60829088SmarkmAcpiEvReleaseGlobalLock (void)
60929088Smarkm{
61029088Smarkm    BOOLEAN                 Pending = FALSE;
61129088Smarkm
61229088Smarkm
61329088Smarkm    ACPI_FUNCTION_TRACE ("EvReleaseGlobalLock");
61429088Smarkm
61529088Smarkm
61629088Smarkm    if (!AcpiGbl_GlobalLockThreadCount)
61729088Smarkm    {
61829088Smarkm        ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
61929088Smarkm        return_VOID;
62029088Smarkm    }
62129088Smarkm
62229088Smarkm    /* One fewer thread has the global lock */
62329088Smarkm
62429088Smarkm    AcpiGbl_GlobalLockThreadCount--;
62529088Smarkm    if (AcpiGbl_GlobalLockThreadCount)
62629088Smarkm    {
62729088Smarkm        /* There are still some threads holding the lock, cannot release */
62829088Smarkm
62929088Smarkm        return_VOID;
63029088Smarkm    }
63129088Smarkm
63229088Smarkm    /*
63329088Smarkm     * No more threads holding lock, we can do the actual hardware
63429088Smarkm     * release
63529088Smarkm     */
63629088Smarkm    ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Pending);
63729088Smarkm    AcpiGbl_GlobalLockAcquired = FALSE;
63829088Smarkm
63929088Smarkm    /*
64029088Smarkm     * If the pending bit was set, we must write GBL_RLS to the control
64129088Smarkm     * register
64229088Smarkm     */
64329088Smarkm    if (Pending)
64429088Smarkm    {
64529088Smarkm        AcpiHwBitRegisterWrite (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK);
64629088Smarkm    }
64729088Smarkm
64829088Smarkm    return_VOID;
64929088Smarkm}
65029088Smarkm
65129088Smarkm
65229088Smarkm/******************************************************************************
65329088Smarkm *
65429088Smarkm * FUNCTION:    AcpiEvTerminate
65529088Smarkm *
65629088Smarkm * PARAMETERS:  none
65729088Smarkm *
65829088Smarkm * RETURN:      none
65929088Smarkm *
66029088Smarkm * DESCRIPTION: free memory allocated for table storage.
66129088Smarkm *
66229088Smarkm ******************************************************************************/
66329088Smarkm
66429088Smarkmvoid
66529088SmarkmAcpiEvTerminate (void)
66629088Smarkm{
66729088Smarkm
66829088Smarkm    ACPI_FUNCTION_TRACE ("EvTerminate");
66929088Smarkm
67029088Smarkm
67129088Smarkm    /*
67229088Smarkm     * Free global tables, etc.
67329088Smarkm     */
67429088Smarkm    if (AcpiGbl_GpeRegisterInfo)
67529088Smarkm    {
67629088Smarkm        ACPI_MEM_FREE (AcpiGbl_GpeRegisterInfo);
67729088Smarkm        AcpiGbl_GpeRegisterInfo = NULL;
67829088Smarkm    }
67929088Smarkm
68029088Smarkm    if (AcpiGbl_GpeNumberInfo)
68129088Smarkm    {
68229088Smarkm        ACPI_MEM_FREE (AcpiGbl_GpeNumberInfo);
68329088Smarkm        AcpiGbl_GpeNumberInfo = NULL;
68429088Smarkm    }
68529088Smarkm
68629088Smarkm    if (AcpiGbl_GpeNumberToIndex)
68729088Smarkm    {
68829088Smarkm        ACPI_MEM_FREE (AcpiGbl_GpeNumberToIndex);
68929088Smarkm        AcpiGbl_GpeNumberToIndex = NULL;
69029088Smarkm    }
69129088Smarkm
69229088Smarkm    return_VOID;
69329088Smarkm}
69429088Smarkm
69529088Smarkm