evmisc.c revision 138287
17055Sdg/******************************************************************************
221830Sjoerg *
321830Sjoerg * Module Name: evmisc - Miscellaneous event manager support functions
47055Sdg *              $Revision: 79 $
57055Sdg *
67055Sdg *****************************************************************************/
77055Sdg
87055Sdg/******************************************************************************
97055Sdg *
107055Sdg * 1. Copyright Notice
117055Sdg *
127055Sdg * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp.
137055Sdg * All rights reserved.
147055Sdg *
157055Sdg * 2. License
167055Sdg *
177055Sdg * 2.1. This is your license from Intel Corp. under its intellectual property
187055Sdg * rights.  You may have additional license terms from the party that provided
197055Sdg * you this software, covering your right to use that party's intellectual
207055Sdg * property rights.
217055Sdg *
227055Sdg * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
237055Sdg * copy of the source code appearing in this file ("Covered Code") an
247055Sdg * irrevocable, perpetual, worldwide license under Intel's copyrights in the
257055Sdg * base code distributed originally by Intel ("Original Intel Code") to copy,
267055Sdg * make derivatives, distribute, use and display any portion of the Covered
277055Sdg * Code in any form, with the right to sublicense such rights; and
287055Sdg *
297055Sdg * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
307055Sdg * license (with the right to sublicense), under only those claims of Intel
317055Sdg * patents that are infringed by the Original Intel Code, to make, use, sell,
327055Sdg * offer to sell, and import the Covered Code and derivative works thereof
337055Sdg * solely to the minimum extent necessary to exercise the above copyright
347055Sdg * license, and in no event shall the patent license extend to any additions
357061Sdg * to or modifications of the Original Intel Code.  No other license or right
3650477Speter * is granted directly or by implication, estoppel or otherwise;
377055Sdg *
387055Sdg * The above copyright and patent license is granted only if the following
3932356Seivind * conditions are met:
4032350Seivind *
4154263Sshin * 3. Conditions
4231742Seivind *
43105577Srwatson * 3.1. Redistribution of Source with Rights to Further Distribute Source.
4431742Seivind * Redistribution of source code of any substantial portion of the Covered
457055Sdg * Code or modification with rights to further distribute source must include
467055Sdg * the above Copyright Notice, the above License, this list of Conditions,
4793375Smdodd * and the following Disclaimer and Export Compliance provision.  In addition,
48105577Srwatson * Licensee must cause all Covered Code to which Licensee contributes to
4993375Smdodd * contain a file documenting the changes Licensee made to create that Covered
507055Sdg * Code and the date of any change.  Licensee must include in that file the
5193375Smdodd * documentation of any changes made by any predecessor Licensee.  Licensee
527055Sdg * must include a prominent statement that the modification is derived,
5393375Smdodd * directly or indirectly, from Original Intel Code.
547055Sdg *
557055Sdg * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
567055Sdg * Redistribution of source code of any substantial portion of the Covered
577055Sdg * Code or modification without rights to further distribute source must
587055Sdg * include the following Disclaimer and Export Compliance provision in the
5993375Smdodd * documentation and/or other materials provided with distribution.  In
6093375Smdodd * addition, Licensee may not authorize further sublicense of source of any
6193375Smdodd * portion of the Covered Code, and must include terms to the effect that the
6293373Smdodd * license from Licensee to its licensee is limited to the intellectual
637055Sdg * property embodied in the software Licensee provides to its licensee, and
6454263Sshin * not to intellectual property embodied in modifications its licensee may
657055Sdg * make.
667055Sdg *
6732350Seivind * 3.3. Redistribution of Executable. Redistribution in executable form of any
687055Sdg * substantial portion of the Covered Code or modification must reproduce the
6954263Sshin * above Copyright Notice, and the following Disclaimer and Export Compliance
7054263Sshin * provision in the documentation and/or other materials provided with the
7154263Sshin * distribution.
727055Sdg *
7311819Sjulian * 3.4. Intel retains all right, title, and interest in and to the Original
7421830Sjoerg * Intel Code.
7511819Sjulian *
7611819Sjulian * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7711819Sjulian * Intel shall be used in advertising or otherwise to promote the sale, use or
787055Sdg * other dealings in products derived from or relating to the Covered Code
797055Sdg * without prior written authorization from Intel.
807055Sdg *
817055Sdg * 4. Disclaimer and Export Compliance
827055Sdg *
837055Sdg * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
847055Sdg * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
857055Sdg * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
867055Sdg * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8721830Sjoerg * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8821830Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8921830Sjoerg * PARTICULAR PURPOSE.
9021830Sjoerg *
9121830Sjoerg * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9221830Sjoerg * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9321830Sjoerg * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9421830Sjoerg * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9521830Sjoerg * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9693382Smdodd * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9793382Smdodd * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9893382Smdodd * LIMITED REMEDY.
9993383Smdodd *
10093084Sbde * 4.3. Licensee shall not export, either directly or indirectly, any of this
10193383Smdodd * software or system incorporating such software without first obtaining any
10293383Smdodd * required license or other approval from the U. S. Department of Commerce or
103106939Ssam * any other agency or department of the United States Government.  In the
10468180Sume * event Licensee exports any such software from the United States or
10593383Smdodd * re-exports any such software from a foreign destination, Licensee shall
10693369Smdodd * ensure that the distribution and export/re-export of the software is in
10793369Smdodd * compliance with all laws, regulations, orders, or other restrictions of the
10893369Smdodd * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1097055Sdg * any of its subsidiaries will export/re-export any technical data, process,
1107055Sdg * software, or service, directly or indirectly, to any country for which the
1117055Sdg * United States government or any agency thereof requires an export license,
1127055Sdg * other governmental approval, or letter of assurance, without first obtaining
1137055Sdg * such license, approval or letter.
1147055Sdg *
1157055Sdg *****************************************************************************/
11693383Smdodd
11754799Sgreen#include "acpi.h"
11893367Smdodd#include "acevents.h"
11954799Sgreen#include "acnamesp.h"
1207055Sdg#include "acinterp.h"
1217055Sdg
1227055Sdg#define _COMPONENT          ACPI_EVENTS
12321830Sjoerg        ACPI_MODULE_NAME    ("evmisc")
12469152Sjlemon
12593373Smdodd
12693367Smdodd/*******************************************************************************
12793367Smdodd *
12893369Smdodd * FUNCTION:    AcpiEvIsNotifyObject
1297055Sdg *
130105577Srwatson * PARAMETERS:  Node            - Node to check
131105577Srwatson *
132105577Srwatson * RETURN:      TRUE if notifies allowed on this object
133105577Srwatson *
134105577Srwatson * DESCRIPTION: Check type of node for a object that supports notifies.
135105577Srwatson *
1367055Sdg *              TBD: This could be replaced by a flag bit in the node.
1377055Sdg *
13834961Sphk ******************************************************************************/
13943305Sdillon
1407055SdgBOOLEAN
14193369SmdoddAcpiEvIsNotifyObject (
1427055Sdg    ACPI_NAMESPACE_NODE     *Node)
14321830Sjoerg{
1447055Sdg    switch (Node->Type)
1457055Sdg    {
1467055Sdg    case ACPI_TYPE_DEVICE:
1477055Sdg    case ACPI_TYPE_PROCESSOR:
1487055Sdg    case ACPI_TYPE_POWER:
1497055Sdg    case ACPI_TYPE_THERMAL:
1507055Sdg        /*
15193369Smdodd         * These are the ONLY objects that can receive ACPI notifications
1527055Sdg         */
1537055Sdg        return (TRUE);
1547055Sdg
1557055Sdg    default:
1567055Sdg        return (FALSE);
1577055Sdg    }
15834961Sphk}
1597055Sdg
1607055Sdg
1617055Sdg/*******************************************************************************
1627055Sdg *
1637055Sdg * FUNCTION:    AcpiEvQueueNotifyRequest
16421830Sjoerg *
16593369Smdodd * PARAMETERS:  Node            - NS node for the notified object
1667055Sdg *              NotifyValue     - Value from the Notify() request
16721830Sjoerg *
1687055Sdg * RETURN:      Status
16921830Sjoerg *
1707055Sdg * DESCRIPTION: Dispatch a device notification event to a previously
17154263Sshin *              installed handler.
17254263Sshin *
17393375Smdodd ******************************************************************************/
17474093Sbmilekic
17593369Smdodd#ifdef ACPI_DEBUG_OUTPUT
17654263Sshinstatic const char        *AcpiNotifyValueNames[] =
17754263Sshin{
17854263Sshin    "Bus Check",
17954263Sshin    "Device Check",
18011819Sjulian    "Device Wake",
18111819Sjulian    "Eject request",
18221830Sjoerg    "Device Check Light",
18311819Sjulian    "Frequency Mismatch",
18493373Smdodd    "Bus Mode Mismatch",
18511819Sjulian    "Power Fault"
18611819Sjulian};
18721830Sjoerg#endif
18821830Sjoerg
18921830SjoergACPI_STATUS
19036908SjulianAcpiEvQueueNotifyRequest (
19121830Sjoerg    ACPI_NAMESPACE_NODE     *Node,
19221830Sjoerg    UINT32                  NotifyValue)
19321830Sjoerg{
19421830Sjoerg    ACPI_OPERAND_OBJECT     *ObjDesc;
19530834Sjulian    ACPI_OPERAND_OBJECT     *HandlerObj = NULL;
19621830Sjoerg    ACPI_GENERIC_STATE      *NotifyInfo;
19721830Sjoerg    ACPI_STATUS             Status = AE_OK;
19821830Sjoerg
19921830Sjoerg
20021830Sjoerg    ACPI_FUNCTION_NAME ("EvQueueNotifyRequest");
20121830Sjoerg
20221830Sjoerg
20321830Sjoerg    /*
20421830Sjoerg     * For value 3 (Ejection Request), some device method may need to be run.
20521830Sjoerg     * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
206111119Simp     * For value 0x80 (Status Change) on the power button or sleep button,
20721830Sjoerg     * initiate soft-off or sleep operation?
20821830Sjoerg     */
20921830Sjoerg    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
21021830Sjoerg        "Dispatching Notify(%X) on node %p\n", NotifyValue, Node));
21193371Smdodd
21293371Smdodd    if (NotifyValue <= 7)
21393373Smdodd    {
21421830Sjoerg        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
21521830Sjoerg                AcpiNotifyValueNames[NotifyValue]));
21621830Sjoerg    }
21721830Sjoerg    else
21821830Sjoerg    {
21921830Sjoerg        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: 0x%2.2X **Device Specific**\n",
22021830Sjoerg                NotifyValue));
2217055Sdg    }
2227055Sdg
22321830Sjoerg    /* Get the notify object attached to the NS Node */
2247055Sdg
22593373Smdodd    ObjDesc = AcpiNsGetAttachedObject (Node);
2267055Sdg    if (ObjDesc)
2277055Sdg    {
2287055Sdg        /* We have the notify object, Get the right handler */
22952248Smsmith
23052248Smsmith        switch (Node->Type)
23193376Smdodd        {
23252248Smsmith        case ACPI_TYPE_DEVICE:
23393376Smdodd        case ACPI_TYPE_THERMAL:
23493376Smdodd        case ACPI_TYPE_PROCESSOR:
23552248Smsmith        case ACPI_TYPE_POWER:
23652248Smsmith
23752248Smsmith            if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
2387055Sdg            {
2397055Sdg                HandlerObj = ObjDesc->CommonNotify.SystemNotify;
2407055Sdg            }
24136992Sjulian            else
2427055Sdg            {
24393375Smdodd                HandlerObj = ObjDesc->CommonNotify.DeviceNotify;
2447055Sdg            }
2457055Sdg            break;
2467055Sdg
2477055Sdg        default:
2487055Sdg            /* All other types are not supported */
2497055Sdg            return (AE_TYPE);
2507055Sdg        }
2517055Sdg    }
2527055Sdg
2537055Sdg    /* If there is any handler to run, schedule the dispatcher */
2547055Sdg
2557055Sdg    if ((AcpiGbl_SystemNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) ||
2567055Sdg        (AcpiGbl_DeviceNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY))  ||
2577055Sdg        HandlerObj)
2587055Sdg    {
2597055Sdg        NotifyInfo = AcpiUtCreateGenericState ();
2607055Sdg        if (!NotifyInfo)
2617055Sdg        {
2627055Sdg            return (AE_NO_MEMORY);
2637055Sdg        }
2647055Sdg
2657055Sdg        NotifyInfo->Common.DataType   = ACPI_DESC_TYPE_STATE_NOTIFY;
2667055Sdg        NotifyInfo->Notify.Node       = Node;
2677055Sdg        NotifyInfo->Notify.Value      = (UINT16) NotifyValue;
2687055Sdg        NotifyInfo->Notify.HandlerObj = HandlerObj;
2697055Sdg
2707055Sdg        Status = AcpiOsQueueForExecution (OSD_PRIORITY_HIGH,
2717055Sdg                        AcpiEvNotifyDispatch, NotifyInfo);
2727055Sdg        if (ACPI_FAILURE (Status))
2737055Sdg        {
2747055Sdg            AcpiUtDeleteGenericState (NotifyInfo);
2757055Sdg        }
2767055Sdg    }
2777055Sdg
2787055Sdg    if (!HandlerObj)
2797055Sdg    {
2807055Sdg        /*
2817055Sdg         * There is no per-device notify handler for this device.
2827055Sdg         * This may or may not be a problem.
2837055Sdg         */
284105598Sbrooks        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
2857055Sdg            "No notify handler for Notify(%4.4s, %X) node %p\n",
2867055Sdg            AcpiUtGetNodeName (Node), NotifyValue, Node));
2877055Sdg    }
28893380Smdodd
28993380Smdodd    return (Status);
29093380Smdodd}
2917055Sdg
29293367Smdodd
293111119Simp/*******************************************************************************
2947055Sdg *
2957055Sdg * FUNCTION:    AcpiEvNotifyDispatch
2967055Sdg *
2977055Sdg * PARAMETERS:  Context         - To be passsed to the notify handler
2987055Sdg *
2997055Sdg * RETURN:      None.
30093375Smdodd *
30121830Sjoerg * DESCRIPTION: Dispatch a device notification event to a previously
3027055Sdg *              installed handler.
30336908Sjulian *
3047055Sdg ******************************************************************************/
3057055Sdg
3067055Sdgvoid ACPI_SYSTEM_XFACE
3077055SdgAcpiEvNotifyDispatch (
308111119Simp    void                    *Context)
3097055Sdg{
3107055Sdg    ACPI_GENERIC_STATE      *NotifyInfo = (ACPI_GENERIC_STATE *) Context;
3117055Sdg    ACPI_NOTIFY_HANDLER     GlobalHandler = NULL;
3127055Sdg    void                    *GlobalContext = NULL;
31393375Smdodd    ACPI_OPERAND_OBJECT     *HandlerObj;
3147055Sdg
31552248Smsmith
31693375Smdodd    ACPI_FUNCTION_ENTRY ();
31752248Smsmith
31893375Smdodd
31993373Smdodd    /*
32093377Smdodd     * We will invoke a global notify handler if installed.
32136908Sjulian     * This is done _before_ we invoke the per-device handler attached to the device.
32236908Sjulian     */
32336908Sjulian    if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY)
32436908Sjulian    {
32536908Sjulian        /* Global system notification handler */
32636908Sjulian
32736908Sjulian        if (AcpiGbl_SystemNotify.Handler)
32836908Sjulian        {
32936908Sjulian            GlobalHandler = AcpiGbl_SystemNotify.Handler;
33093377Smdodd            GlobalContext = AcpiGbl_SystemNotify.Context;
33136908Sjulian        }
33236908Sjulian    }
33336908Sjulian    else
33436908Sjulian    {
33593373Smdodd        /* Global driver notification handler */
33636908Sjulian
33793373Smdodd        if (AcpiGbl_DeviceNotify.Handler)
33836908Sjulian        {
33993373Smdodd            GlobalHandler = AcpiGbl_DeviceNotify.Handler;
34093369Smdodd            GlobalContext = AcpiGbl_DeviceNotify.Context;
34136908Sjulian        }
34236908Sjulian    }
34336908Sjulian
34469152Sjlemon    /* Invoke the system handler first, if present */
3457055Sdg
3467055Sdg    if (GlobalHandler)
3477055Sdg    {
3487055Sdg        GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, GlobalContext);
34993379Smdodd    }
3507055Sdg
3517055Sdg    /* Now invoke the per-device handler, if present */
3527055Sdg
3537055Sdg    HandlerObj = NotifyInfo->Notify.HandlerObj;
3547055Sdg    if (HandlerObj)
3557055Sdg    {
3567055Sdg        HandlerObj->Notify.Handler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value,
3577055Sdg                        HandlerObj->Notify.Context);
3587055Sdg    }
3597055Sdg
360106939Ssam    /* All done with the info object */
361106939Ssam
3627055Sdg    AcpiUtDeleteGenericState (NotifyInfo);
3637055Sdg}
3647055Sdg
36593367Smdodd
36693367Smdodd/*******************************************************************************
367106939Ssam *
3687055Sdg * FUNCTION:    AcpiEvGlobalLockThread
369106939Ssam *
370106939Ssam * PARAMETERS:  Context         - From thread interface, not used
37193379Smdodd *
372106939Ssam * RETURN:      None
373106939Ssam *
374106939Ssam * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
375106939Ssam *              Global Lock.  Simply signal all threads that are waiting
376106939Ssam *              for the lock.
377106939Ssam *
37893379Smdodd ******************************************************************************/
37993379Smdodd
38093379Smdoddstatic void ACPI_SYSTEM_XFACE
38193379SmdoddAcpiEvGlobalLockThread (
38293379Smdodd    void                    *Context)
383105577Srwatson{
384105577Srwatson    ACPI_STATUS             Status;
385105577Srwatson
386105577Srwatson
38793379Smdodd    /* Signal threads that are waiting for the lock */
38893379Smdodd
38993379Smdodd    if (AcpiGbl_GlobalLockThreadCount)
39093379Smdodd    {
39193379Smdodd        /* Send sufficient units to the semaphore */
39293379Smdodd
39393379Smdodd        Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore,
39493379Smdodd                                AcpiGbl_GlobalLockThreadCount);
39593379Smdodd        if (ACPI_FAILURE (Status))
39693379Smdodd        {
39793379Smdodd            ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n"));
39893379Smdodd        }
39921830Sjoerg    }
40093381Smdodd}
40193381Smdodd
40221830Sjoerg
40321830Sjoerg/*******************************************************************************
40421830Sjoerg *
4057055Sdg * FUNCTION:    AcpiEvGlobalLockHandler
40621830Sjoerg *
4077055Sdg * PARAMETERS:  Context         - From thread interface, not used
40821830Sjoerg *
40921830Sjoerg * RETURN:      ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
41021830Sjoerg *
41121830Sjoerg * DESCRIPTION: Invoked directly from the SCI handler when a global lock
41221830Sjoerg *              release interrupt occurs.  Grab the global lock and queue
41321830Sjoerg *              the global lock thread for execution
41421830Sjoerg *
41521830Sjoerg ******************************************************************************/
41621830Sjoerg
41721830Sjoergstatic UINT32
418106939SsamAcpiEvGlobalLockHandler (
419106939Ssam    void                    *Context)
420106939Ssam{
42193379Smdodd    BOOLEAN                 Acquired = FALSE;
42293379Smdodd    ACPI_STATUS             Status;
42393379Smdodd
42493379Smdodd
42593379Smdodd    /*
4267055Sdg     * Attempt to get the lock
42793377Smdodd     * If we don't get it now, it will be marked pending and we will
4287055Sdg     * take another interrupt when it becomes free.
4297055Sdg     */
4307055Sdg    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired);
43121830Sjoerg    if (Acquired)
43293379Smdodd    {
43393379Smdodd        /* Got the lock, now wake all threads waiting for it */
4347055Sdg
43593379Smdodd        AcpiGbl_GlobalLockAcquired = TRUE;
43621830Sjoerg
43793371Smdodd        /* Run the Global Lock thread which will signal all waiting threads */
43821830Sjoerg
43993371Smdodd        Status = AcpiOsQueueForExecution (OSD_PRIORITY_HIGH,
44021830Sjoerg                        AcpiEvGlobalLockThread, Context);
44193373Smdodd        if (ACPI_FAILURE (Status))
44221830Sjoerg        {
44321830Sjoerg            ACPI_REPORT_ERROR (("Could not queue Global Lock thread, %s\n",
44421830Sjoerg                AcpiFormatException (Status)));
44521830Sjoerg
44693371Smdodd            return (ACPI_INTERRUPT_NOT_HANDLED);
44721830Sjoerg        }
44893371Smdodd    }
44993373Smdodd
45093369Smdodd    return (ACPI_INTERRUPT_HANDLED);
45121830Sjoerg}
45221830Sjoerg
45321830Sjoerg
45493377Smdodd/*******************************************************************************
45593377Smdodd *
45693379Smdodd * FUNCTION:    AcpiEvInitGlobalLockHandler
45793379Smdodd *
4587055Sdg * PARAMETERS:  None
45993379Smdodd *
46093377Smdodd * RETURN:      Status
46121830Sjoerg *
46293377Smdodd * DESCRIPTION: Install a handler for the global lock release event
46393377Smdodd *
46421830Sjoerg ******************************************************************************/
4657055Sdg
4667055SdgACPI_STATUS
46736265SdgAcpiEvInitGlobalLockHandler (void)
46836192Sdg{
4697055Sdg    ACPI_STATUS             Status;
4707055Sdg
4717055Sdg
4727055Sdg    ACPI_FUNCTION_TRACE ("EvInitGlobalLockHandler");
4737055Sdg
47478295Sjlemon
47578295Sjlemon    AcpiGbl_GlobalLockPresent = TRUE;
4767055Sdg    Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL,
4777055Sdg                                            AcpiEvGlobalLockHandler, NULL);
4787055Sdg
4797055Sdg    /*
48054263Sshin     * If the global lock does not exist on this platform, the attempt
48154263Sshin     * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)
48254263Sshin     * Map to AE_OK, but mark global lock as not present.
48354263Sshin     * Any attempt to actually use the global lock will be flagged
48454263Sshin     * with an error.
48554263Sshin     */
48621830Sjoerg    if (Status == AE_NO_HARDWARE_RESPONSE)
48721830Sjoerg    {
48821830Sjoerg        AcpiGbl_GlobalLockPresent = FALSE;
48921830Sjoerg        Status = AE_OK;
49021830Sjoerg    }
49121830Sjoerg
4927055Sdg    return_ACPI_STATUS (Status);
4937055Sdg}
4947055Sdg
4957055Sdg
4967055Sdg/******************************************************************************
4977055Sdg *
4987055Sdg * FUNCTION:    AcpiEvAcquireGlobalLock
49921830Sjoerg *
5007055Sdg * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
5017055Sdg *
5027055Sdg * RETURN:      Status
5037055Sdg *
50421830Sjoerg * DESCRIPTION: Attempt to gain ownership of the Global Lock.
50521830Sjoerg *
50621830Sjoerg *****************************************************************************/
50721830Sjoerg
50821830SjoergACPI_STATUS
50921830SjoergAcpiEvAcquireGlobalLock (
51021830Sjoerg    UINT16                  Timeout)
51193369Smdodd{
51221830Sjoerg    ACPI_STATUS             Status = AE_OK;
51321830Sjoerg    BOOLEAN                 Acquired = FALSE;
5147055Sdg
51521830Sjoerg
5167055Sdg    ACPI_FUNCTION_TRACE ("EvAcquireGlobalLock");
5177055Sdg
5187055Sdg
5197055Sdg#ifndef ACPI_APPLICATION
5207055Sdg    /* Make sure that we actually have a global lock */
52121830Sjoerg
5227055Sdg    if (!AcpiGbl_GlobalLockPresent)
52321830Sjoerg    {
5247055Sdg        return_ACPI_STATUS (AE_NO_GLOBAL_LOCK);
52593377Smdodd    }
5267055Sdg#endif
5277055Sdg
52869152Sjlemon    /* One more thread wants the global lock */
52993377Smdodd
53093377Smdodd    AcpiGbl_GlobalLockThreadCount++;
53193377Smdodd
53293377Smdodd    /* If we (OS side vs. BIOS side) have the hardware lock already, we are done */
53393377Smdodd
53493377Smdodd    if (AcpiGbl_GlobalLockAcquired)
53593377Smdodd    {
5367055Sdg        return_ACPI_STATUS (AE_OK);
53793380Smdodd    }
5387055Sdg
5397055Sdg    /* We must acquire the actual hardware lock */
5407055Sdg
5417055Sdg    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired);
54293383Smdodd    if (Acquired)
54393367Smdodd    {
54493383Smdodd       /* We got the lock */
5457055Sdg
54693367Smdodd        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired the HW Global Lock\n"));
54793367Smdodd
5487055Sdg        AcpiGbl_GlobalLockAcquired = TRUE;
5497055Sdg        return_ACPI_STATUS (AE_OK);
55093373Smdodd    }
5517055Sdg
55293379Smdodd    /*
55393379Smdodd     * Did not get the lock.  The pending bit was set above, and we must now
55493379Smdodd     * wait until we get the global lock released interrupt.
5557055Sdg     */
55693379Smdodd    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
557106939Ssam
55868180Sume    /*
55993379Smdodd     * Acquire the global lock semaphore first.
56016063Sgpalmer     * Since this wait will block, we must release the interpreter
56121830Sjoerg     */
56221830Sjoerg    Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore,
56321830Sjoerg                                            Timeout);
56483130Sjlemon    return_ACPI_STATUS (Status);
56593379Smdodd}
56693379Smdodd
56793379Smdodd
56893379Smdodd/*******************************************************************************
56993379Smdodd *
57093379Smdodd * FUNCTION:    AcpiEvReleaseGlobalLock
57121831Sjoerg *
57221831Sjoerg * PARAMETERS:  None
57321831Sjoerg *
57493369Smdodd * RETURN:      Status
57593379Smdodd *
57693383Smdodd * DESCRIPTION: Releases ownership of the Global Lock.
57793383Smdodd *
57893383Smdodd ******************************************************************************/
57993379Smdodd
5807055SdgACPI_STATUS
58168180SumeAcpiEvReleaseGlobalLock (void)
58293382Smdodd{
58393382Smdodd    BOOLEAN                 Pending = FALSE;
58493382Smdodd    ACPI_STATUS             Status = AE_OK;
58593382Smdodd
58693382Smdodd
58793382Smdodd    ACPI_FUNCTION_TRACE ("EvReleaseGlobalLock");
58893382Smdodd
58993382Smdodd
59093382Smdodd    if (!AcpiGbl_GlobalLockThreadCount)
59193382Smdodd    {
59293382Smdodd        ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
59393382Smdodd        return_ACPI_STATUS (AE_NOT_ACQUIRED);
59493382Smdodd    }
59593382Smdodd
59693382Smdodd    /* One fewer thread has the global lock */
59793382Smdodd
59893382Smdodd    AcpiGbl_GlobalLockThreadCount--;
59993382Smdodd    if (AcpiGbl_GlobalLockThreadCount)
60093382Smdodd    {
60193382Smdodd        /* There are still some threads holding the lock, cannot release */
60293382Smdodd
60393382Smdodd        return_ACPI_STATUS (AE_OK);
60493382Smdodd    }
60593382Smdodd
60693382Smdodd    /*
60793382Smdodd     * No more threads holding lock, we can do the actual hardware
60893382Smdodd     * release
60993382Smdodd     */
61093382Smdodd    ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Pending);
61193382Smdodd    AcpiGbl_GlobalLockAcquired = FALSE;
61293382Smdodd
61393382Smdodd    /*
61493382Smdodd     * If the pending bit was set, we must write GBL_RLS to the control
61593382Smdodd     * register
61693382Smdodd     */
61793382Smdodd    if (Pending)
61893382Smdodd    {
61993382Smdodd        Status = AcpiSetRegister (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK);
62093382Smdodd    }
62193382Smdodd
62293382Smdodd    return_ACPI_STATUS (Status);
62393382Smdodd}
62493382Smdodd
62593382Smdodd
62693382Smdodd/******************************************************************************
62793382Smdodd *
62893382Smdodd * FUNCTION:    AcpiEvTerminate
62993382Smdodd *
63093382Smdodd * PARAMETERS:  none
63193382Smdodd *
63293382Smdodd * RETURN:      none
63393382Smdodd *
63493382Smdodd * DESCRIPTION: Disable events and free memory allocated for table storage.
63593382Smdodd *
63693382Smdodd ******************************************************************************/
63793382Smdodd
63893382Smdoddvoid
63993382SmdoddAcpiEvTerminate (void)
64093382Smdodd{
64193382Smdodd    ACPI_NATIVE_UINT        i;
64293382Smdodd    ACPI_STATUS             Status;
64393382Smdodd
64493382Smdodd
64593382Smdodd    ACPI_FUNCTION_TRACE ("EvTerminate");
64693382Smdodd
64793382Smdodd
64893382Smdodd    if (AcpiGbl_EventsInitialized)
64993382Smdodd    {
65093382Smdodd        /*
651104302Sphk         * Disable all event-related functionality.
65293382Smdodd         * In all cases, on error, print a message but obviously we don't abort.
65393382Smdodd         */
65493382Smdodd
65593382Smdodd        /* Disable all fixed events */
65693382Smdodd
65793382Smdodd        for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
65893382Smdodd        {
65993382Smdodd            Status = AcpiDisableEvent ((UINT32) i, 0);
66093382Smdodd            if (ACPI_FAILURE (Status))
66193382Smdodd            {
66293382Smdodd                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable fixed event %d\n", (UINT32) i));
66393382Smdodd            }
66493382Smdodd        }
66593382Smdodd
66693382Smdodd        /* Disable all GPEs in all GPE blocks */
66793382Smdodd
66893382Smdodd        Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, ACPI_NOT_ISR);
66993382Smdodd
67093382Smdodd        /* Remove SCI handler */
67193382Smdodd
67293382Smdodd        Status = AcpiEvRemoveSciHandler ();
67393382Smdodd        if (ACPI_FAILURE(Status))
67493382Smdodd        {
67593382Smdodd            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not remove SCI handler\n"));
67693382Smdodd        }
67793382Smdodd    }
67868180Sume
67968180Sume    /* Deallocate all handler objects installed within GPE info structs */
68068180Sume
68168180Sume    Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, ACPI_NOT_ISR);
68268180Sume
68368180Sume    /* Return to original mode if necessary */
68468180Sume
68568180Sume    if (AcpiGbl_OriginalMode == ACPI_SYS_MODE_LEGACY)
68668180Sume    {
68768180Sume        Status = AcpiDisable ();
68868180Sume        if (ACPI_FAILURE (Status))
68968180Sume        {
69068180Sume            ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "AcpiDisable failed\n"));
69168180Sume        }
69268180Sume    }
69368180Sume    return_VOID;
69468180Sume}
69568180Sume
69668180Sume