evmisc.c revision 151600
150276Speter/******************************************************************************
2178866Srafan *
350276Speter * Module Name: evmisc - Miscellaneous event manager support functions
450276Speter *              $Revision: 79 $
550276Speter *
650276Speter *****************************************************************************/
750276Speter
850276Speter/******************************************************************************
950276Speter *
1050276Speter * 1. Copyright Notice
1150276Speter *
1250276Speter * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp.
1350276Speter * All rights reserved.
1450276Speter *
1550276Speter * 2. License
1650276Speter *
1750276Speter * 2.1. This is your license from Intel Corp. under its intellectual property
1850276Speter * rights.  You may have additional license terms from the party that provided
1950276Speter * you this software, covering your right to use that party's intellectual
2050276Speter * property rights.
2150276Speter *
2250276Speter * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2350276Speter * copy of the source code appearing in this file ("Covered Code") an
2450276Speter * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2550276Speter * base code distributed originally by Intel ("Original Intel Code") to copy,
2650276Speter * make derivatives, distribute, use and display any portion of the Covered
2750276Speter * Code in any form, with the right to sublicense such rights; and
2850276Speter *
29166124Srafan * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
3050276Speter * license (with the right to sublicense), under only those claims of Intel
31184989Srafan * patents that are infringed by the Original Intel Code, to make, use, sell,
3250276Speter * offer to sell, and import the Covered Code and derivative works thereof
3350276Speter * solely to the minimum extent necessary to exercise the above copyright
34166124Srafan * license, and in no event shall the patent license extend to any additions
35166124Srafan * to or modifications of the Original Intel Code.  No other license or right
36166124Srafan * is granted directly or by implication, estoppel or otherwise;
3766963Speter *
38166124Srafan * The above copyright and patent license is granted only if the following
39166124Srafan * conditions are met:
4050276Speter *
4150276Speter * 3. Conditions
42166124Srafan *
43166124Srafan * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44166124Srafan * Redistribution of source code of any substantial portion of the Covered
45166124Srafan * Code or modification with rights to further distribute source must include
46166124Srafan * the above Copyright Notice, the above License, this list of Conditions,
47166124Srafan * and the following Disclaimer and Export Compliance provision.  In addition,
48166124Srafan * Licensee must cause all Covered Code to which Licensee contributes to
49166124Srafan * contain a file documenting the changes Licensee made to create that Covered
50166124Srafan * Code and the date of any change.  Licensee must include in that file the
51166124Srafan * documentation of any changes made by any predecessor Licensee.  Licensee
52166124Srafan * must include a prominent statement that the modification is derived,
53166124Srafan * directly or indirectly, from Original Intel Code.
54166124Srafan *
55166124Srafan * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56166124Srafan * Redistribution of source code of any substantial portion of the Covered
57166124Srafan * Code or modification without rights to further distribute source must
58166124Srafan * include the following Disclaimer and Export Compliance provision in the
59166124Srafan * documentation and/or other materials provided with distribution.  In
60166124Srafan * addition, Licensee may not authorize further sublicense of source of any
61166124Srafan * portion of the Covered Code, and must include terms to the effect that the
62166124Srafan * license from Licensee to its licensee is limited to the intellectual
63166124Srafan * property embodied in the software Licensee provides to its licensee, and
64166124Srafan * not to intellectual property embodied in modifications its licensee may
65166124Srafan * make.
66166124Srafan *
6750276Speter * 3.3. Redistribution of Executable. Redistribution in executable form of any
6850276Speter * substantial portion of the Covered Code or modification must reproduce the
6950276Speter * above Copyright Notice, and the following Disclaimer and Export Compliance
7050276Speter * provision in the documentation and/or other materials provided with the
71166124Srafan * distribution.
7250276Speter *
73166124Srafan * 3.4. Intel retains all right, title, and interest in and to the Original
7450276Speter * Intel Code.
7566963Speter *
76166124Srafan * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7750276Speter * Intel shall be used in advertising or otherwise to promote the sale, use or
7850276Speter * other dealings in products derived from or relating to the Covered Code
7950276Speter * without prior written authorization from Intel.
80166124Srafan *
8150276Speter * 4. Disclaimer and Export Compliance
8250276Speter *
83166124Srafan * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8450276Speter * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8550276Speter * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8650276Speter * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8750276Speter * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8850276Speter * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89166124Srafan * PARTICULAR PURPOSE.
90166124Srafan *
9176726Speter * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9297049Speter * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93166124Srafan * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94166124Srafan * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95166124Srafan * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96166124Srafan * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9776726Speter * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9876726Speter * LIMITED REMEDY.
99166124Srafan *
10097049Speter * 4.3. Licensee shall not export, either directly or indirectly, any of this
10197049Speter * software or system incorporating such software without first obtaining any
102166124Srafan * required license or other approval from the U. S. Department of Commerce or
103166124Srafan * any other agency or department of the United States Government.  In the
10476726Speter * event Licensee exports any such software from the United States or
10576726Speter * re-exports any such software from a foreign destination, Licensee shall
106166124Srafan * ensure that the distribution and export/re-export of the software is in
107166124Srafan * compliance with all laws, regulations, orders, or other restrictions of the
10876726Speter * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10976726Speter * any of its subsidiaries will export/re-export any technical data, process,
110166124Srafan * software, or service, directly or indirectly, to any country for which the
111166124Srafan * United States government or any agency thereof requires an export license,
112166124Srafan * other governmental approval, or letter of assurance, without first obtaining
113166124Srafan * such license, approval or letter.
114166124Srafan *
115166124Srafan *****************************************************************************/
116166124Srafan
117166124Srafan#include <contrib/dev/acpica/acpi.h>
118166124Srafan#include <contrib/dev/acpica/acevents.h>
119166124Srafan#include <contrib/dev/acpica/acnamesp.h>
120166124Srafan#include <contrib/dev/acpica/acinterp.h>
121166124Srafan
122166124Srafan#define _COMPONENT          ACPI_EVENTS
123166124Srafan        ACPI_MODULE_NAME    ("evmisc")
124166124Srafan
125166124Srafan
126166124Srafan/*******************************************************************************
12776726Speter *
12897049Speter * FUNCTION:    AcpiEvIsNotifyObject
12976726Speter *
13097049Speter * PARAMETERS:  Node            - Node to check
13197049Speter *
13276726Speter * RETURN:      TRUE if notifies allowed on this object
13376726Speter *
13476726Speter * DESCRIPTION: Check type of node for a object that supports notifies.
13576726Speter *
13697049Speter *              TBD: This could be replaced by a flag bit in the node.
13776726Speter *
13876726Speter ******************************************************************************/
139166124Srafan
140166124SrafanBOOLEAN
141166124SrafanAcpiEvIsNotifyObject (
142166124Srafan    ACPI_NAMESPACE_NODE     *Node)
143166124Srafan{
144166124Srafan    switch (Node->Type)
145166124Srafan    {
146166124Srafan    case ACPI_TYPE_DEVICE:
147166124Srafan    case ACPI_TYPE_PROCESSOR:
148166124Srafan    case ACPI_TYPE_POWER:
149166124Srafan    case ACPI_TYPE_THERMAL:
15076726Speter        /*
15197049Speter         * These are the ONLY objects that can receive ACPI notifications
15297049Speter         */
15397049Speter        return (TRUE);
15497049Speter
15597049Speter    default:
15697049Speter        return (FALSE);
15797049Speter    }
15897049Speter}
159166124Srafan
16097049Speter
16197049Speter/*******************************************************************************
162166124Srafan *
163166124Srafan * FUNCTION:    AcpiEvQueueNotifyRequest
164166124Srafan *
165166124Srafan * PARAMETERS:  Node            - NS node for the notified object
166166124Srafan *              NotifyValue     - Value from the Notify() request
167166124Srafan *
168166124Srafan * RETURN:      Status
16976726Speter *
17076726Speter * DESCRIPTION: Dispatch a device notification event to a previously
171178866Srafan *              installed handler.
172174993Srafan *
173174993Srafan ******************************************************************************/
174174993Srafan
175174993Srafan#ifdef ACPI_DEBUG_OUTPUT
176174993Srafanstatic const char        *AcpiNotifyValueNames[] =
177174993Srafan{
178174993Srafan    "Bus Check",
179174993Srafan    "Device Check",
180174993Srafan    "Device Wake",
181174993Srafan    "Eject request",
182174993Srafan    "Device Check Light",
183174993Srafan    "Frequency Mismatch",
184174993Srafan    "Bus Mode Mismatch",
185174993Srafan    "Power Fault"
186174993Srafan};
187174993Srafan#endif
188174993Srafan
189174993SrafanACPI_STATUS
190174993SrafanAcpiEvQueueNotifyRequest (
191174993Srafan    ACPI_NAMESPACE_NODE     *Node,
192174993Srafan    UINT32                  NotifyValue)
193174993Srafan{
194174993Srafan    ACPI_OPERAND_OBJECT     *ObjDesc;
195174993Srafan    ACPI_OPERAND_OBJECT     *HandlerObj = NULL;
196174993Srafan    ACPI_GENERIC_STATE      *NotifyInfo;
197174993Srafan    ACPI_STATUS             Status = AE_OK;
198174993Srafan
199174993Srafan
200174993Srafan    ACPI_FUNCTION_NAME ("EvQueueNotifyRequest");
201174993Srafan
202174993Srafan
203174993Srafan    /*
204174993Srafan     * For value 3 (Ejection Request), some device method may need to be run.
205174993Srafan     * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
206174993Srafan     * For value 0x80 (Status Change) on the power button or sleep button,
207174993Srafan     * initiate soft-off or sleep operation?
208174993Srafan     */
209174993Srafan    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
210174993Srafan        "Dispatching Notify(%X) on node %p\n", NotifyValue, Node));
211174993Srafan
212174993Srafan    if (NotifyValue <= 7)
213178866Srafan    {
214174993Srafan        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
215174993Srafan                AcpiNotifyValueNames[NotifyValue]));
216174993Srafan    }
217174993Srafan    else
218174993Srafan    {
219174993Srafan        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: 0x%2.2X **Device Specific**\n",
220174993Srafan                NotifyValue));
221174993Srafan    }
222174993Srafan
223174993Srafan    /* Get the notify object attached to the NS Node */
224174993Srafan
225174993Srafan    ObjDesc = AcpiNsGetAttachedObject (Node);
226174993Srafan    if (ObjDesc)
227174993Srafan    {
228178866Srafan        /* We have the notify object, Get the right handler */
229174993Srafan
230174993Srafan        switch (Node->Type)
231174993Srafan        {
232174993Srafan        case ACPI_TYPE_DEVICE:
233174993Srafan        case ACPI_TYPE_THERMAL:
234174993Srafan        case ACPI_TYPE_PROCESSOR:
235174993Srafan        case ACPI_TYPE_POWER:
236174993Srafan
237174993Srafan            if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
238174993Srafan            {
239174993Srafan                HandlerObj = ObjDesc->CommonNotify.SystemNotify;
240174993Srafan            }
241174993Srafan            else
242174993Srafan            {
243174993Srafan                HandlerObj = ObjDesc->CommonNotify.DeviceNotify;
244174993Srafan            }
245174993Srafan            break;
246174993Srafan
247174993Srafan        default:
248174993Srafan            /* All other types are not supported */
249174993Srafan            return (AE_TYPE);
250174993Srafan        }
251174993Srafan    }
252174993Srafan
253174993Srafan    /* If there is any handler to run, schedule the dispatcher */
254174993Srafan
255174993Srafan    if ((AcpiGbl_SystemNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) ||
256178866Srafan        (AcpiGbl_DeviceNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY))  ||
257174993Srafan        HandlerObj)
258174993Srafan    {
259174993Srafan        NotifyInfo = AcpiUtCreateGenericState ();
260174993Srafan        if (!NotifyInfo)
261174993Srafan        {
262174993Srafan            return (AE_NO_MEMORY);
263174993Srafan        }
264184989Srafan
265184989Srafan        NotifyInfo->Common.DataType   = ACPI_DESC_TYPE_STATE_NOTIFY;
266184989Srafan        NotifyInfo->Notify.Node       = Node;
267184989Srafan        NotifyInfo->Notify.Value      = (UINT16) NotifyValue;
268184989Srafan        NotifyInfo->Notify.HandlerObj = HandlerObj;
269184989Srafan
270184989Srafan        Status = AcpiOsQueueForExecution (OSD_PRIORITY_HIGH,
271184989Srafan                        AcpiEvNotifyDispatch, NotifyInfo);
272184989Srafan        if (ACPI_FAILURE (Status))
273184989Srafan        {
274184989Srafan            AcpiUtDeleteGenericState (NotifyInfo);
275184989Srafan        }
276184989Srafan    }
277184989Srafan
278184989Srafan    if (!HandlerObj)
279184989Srafan    {
280184989Srafan        /*
281184989Srafan         * There is no per-device notify handler for this device.
282184989Srafan         * This may or may not be a problem.
283184989Srafan         */
284184989Srafan        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
285184989Srafan            "No notify handler for Notify(%4.4s, %X) node %p\n",
286166124Srafan            AcpiUtGetNodeName (Node), NotifyValue, Node));
287166124Srafan    }
28850276Speter
28950276Speter    return (Status);
29050276Speter}
29150276Speter
29297049Speter
29350276Speter/*******************************************************************************
29450276Speter *
29576726Speter * FUNCTION:    AcpiEvNotifyDispatch
29650276Speter *
29750276Speter * PARAMETERS:  Context         - To be passsed to the notify handler
29850276Speter *
29950276Speter * RETURN:      None.
30050276Speter *
30150276Speter * DESCRIPTION: Dispatch a device notification event to a previously
30250276Speter *              installed handler.
30350276Speter *
30450276Speter ******************************************************************************/
30550276Speter
30650276Spetervoid ACPI_SYSTEM_XFACE
30762449SpeterAcpiEvNotifyDispatch (
30850276Speter    void                    *Context)
30950276Speter{
31050276Speter    ACPI_GENERIC_STATE      *NotifyInfo = (ACPI_GENERIC_STATE *) Context;
31176726Speter    ACPI_NOTIFY_HANDLER     GlobalHandler = NULL;
31250276Speter    void                    *GlobalContext = NULL;
31350276Speter    ACPI_OPERAND_OBJECT     *HandlerObj;
31450276Speter
31550276Speter
31650276Speter    ACPI_FUNCTION_ENTRY ();
31750276Speter
31850276Speter
31950276Speter    /*
32050276Speter     * We will invoke a global notify handler if installed.
32150276Speter     * This is done _before_ we invoke the per-device handler attached to the device.
32250276Speter     */
32350276Speter    if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY)
32450276Speter    {
32550276Speter        /* Global system notification handler */
32676726Speter
32750276Speter        if (AcpiGbl_SystemNotify.Handler)
32850276Speter        {
32950276Speter            GlobalHandler = AcpiGbl_SystemNotify.Handler;
33050276Speter            GlobalContext = AcpiGbl_SystemNotify.Context;
33176726Speter        }
33250276Speter    }
33350276Speter    else
33450276Speter    {
33550276Speter        /* Global driver notification handler */
33650276Speter
33750276Speter        if (AcpiGbl_DeviceNotify.Handler)
338178866Srafan        {
339166124Srafan            GlobalHandler = AcpiGbl_DeviceNotify.Handler;
34050276Speter            GlobalContext = AcpiGbl_DeviceNotify.Context;
34150276Speter        }
34250276Speter    }
34350276Speter
34450276Speter    /* Invoke the system handler first, if present */
34550276Speter
34650276Speter    if (GlobalHandler)
347178866Srafan    {
34850276Speter        GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, GlobalContext);
34950276Speter    }
35050276Speter
35150276Speter    /* Now invoke the per-device handler, if present */
35250276Speter
35350276Speter    HandlerObj = NotifyInfo->Notify.HandlerObj;
35450276Speter    if (HandlerObj)
35550276Speter    {
356184989Srafan        HandlerObj->Notify.Handler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value,
357184989Srafan                        HandlerObj->Notify.Context);
358184989Srafan    }
359184989Srafan
360184989Srafan    /* All done with the info object */
361184989Srafan
362184989Srafan    AcpiUtDeleteGenericState (NotifyInfo);
363184989Srafan}
364184989Srafan
365184989Srafan
366184989Srafan/*******************************************************************************
367184989Srafan *
368184989Srafan * FUNCTION:    AcpiEvGlobalLockThread
369184989Srafan *
370184989Srafan * PARAMETERS:  Context         - From thread interface, not used
371184989Srafan *
372184989Srafan * RETURN:      None
373184989Srafan *
374184989Srafan * DESCRIPTION: Invoked by SCI interrupt handler upon acquisition of the
375184989Srafan *              Global Lock.  Simply signal all threads that are waiting
376184989Srafan *              for the lock.
377184989Srafan *
378184989Srafan ******************************************************************************/
379184989Srafan
380166124Srafanstatic void ACPI_SYSTEM_XFACE
381166124SrafanAcpiEvGlobalLockThread (
38250276Speter    void                    *Context)
38350276Speter{
38450276Speter    ACPI_STATUS             Status;
38550276Speter
38650276Speter
38750276Speter    /* Signal threads that are waiting for the lock */
388166124Srafan
389166124Srafan    if (AcpiGbl_GlobalLockThreadCount)
39050276Speter    {
39150276Speter        /* Send sufficient units to the semaphore */
392166124Srafan
393166124Srafan        Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore,
394166124Srafan                                AcpiGbl_GlobalLockThreadCount);
395166124Srafan        if (ACPI_FAILURE (Status))
396166124Srafan        {
397166124Srafan            ACPI_REPORT_ERROR (("Could not signal Global Lock semaphore\n"));
398166124Srafan        }
399166124Srafan    }
400166124Srafan}
401166124Srafan
402166124Srafan
403166124Srafan/*******************************************************************************
404166124Srafan *
405166124Srafan * FUNCTION:    AcpiEvGlobalLockHandler
406166124Srafan *
407166124Srafan * PARAMETERS:  Context         - From thread interface, not used
408166124Srafan *
409166124Srafan * RETURN:      ACPI_INTERRUPT_HANDLED or ACPI_INTERRUPT_NOT_HANDLED
41066963Speter *
411166124Srafan * DESCRIPTION: Invoked directly from the SCI handler when a global lock
41250276Speter *              release interrupt occurs.  Grab the global lock and queue
41350276Speter *              the global lock thread for execution
41450276Speter *
41550276Speter ******************************************************************************/
41650276Speter
41750276Speterstatic UINT32
41850276SpeterAcpiEvGlobalLockHandler (
41950276Speter    void                    *Context)
420166124Srafan{
42166963Speter    BOOLEAN                 Acquired = FALSE;
42250276Speter    ACPI_STATUS             Status;
42350276Speter
42450276Speter
42550276Speter    /*
42650276Speter     * Attempt to get the lock
427166124Srafan     * If we don't get it now, it will be marked pending and we will
428166124Srafan     * take another interrupt when it becomes free.
42950276Speter     */
43050276Speter    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired);
43197049Speter    if (Acquired)
43297049Speter    {
43397049Speter        /* Got the lock, now wake all threads waiting for it */
43450276Speter
43550276Speter        AcpiGbl_GlobalLockAcquired = TRUE;
43666963Speter
43750276Speter        /* Run the Global Lock thread which will signal all waiting threads */
43850276Speter
43950276Speter        Status = AcpiOsQueueForExecution (OSD_PRIORITY_HIGH,
44050276Speter                        AcpiEvGlobalLockThread, Context);
44150276Speter        if (ACPI_FAILURE (Status))
44297049Speter        {
44397049Speter            ACPI_REPORT_ERROR (("Could not queue Global Lock thread, %s\n",
44497049Speter                AcpiFormatException (Status)));
44566963Speter
44656639Speter            return (ACPI_INTERRUPT_NOT_HANDLED);
44756639Speter        }
44856639Speter    }
44956639Speter
45050276Speter    return (ACPI_INTERRUPT_HANDLED);
45150276Speter}
45297049Speter
45397049Speter
45497049Speter/*******************************************************************************
45597049Speter *
45697049Speter * FUNCTION:    AcpiEvInitGlobalLockHandler
45797049Speter *
45897049Speter * PARAMETERS:  None
45997049Speter *
46097049Speter * RETURN:      Status
46150276Speter *
46250276Speter * DESCRIPTION: Install a handler for the global lock release event
46350276Speter *
46450276Speter ******************************************************************************/
46550276Speter
46650276SpeterACPI_STATUS
46750276SpeterAcpiEvInitGlobalLockHandler (void)
46850276Speter{
46950276Speter    ACPI_STATUS             Status;
47050276Speter
47150276Speter
47250276Speter    ACPI_FUNCTION_TRACE ("EvInitGlobalLockHandler");
47350276Speter
474166124Srafan
47550276Speter    AcpiGbl_GlobalLockPresent = TRUE;
47650276Speter    Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL,
47797049Speter                                            AcpiEvGlobalLockHandler, NULL);
47897049Speter
47997049Speter    /*
48097049Speter     * If the global lock does not exist on this platform, the attempt
48150276Speter     * to enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick)
48250276Speter     * Map to AE_OK, but mark global lock as not present.
48350276Speter     * Any attempt to actually use the global lock will be flagged
48450276Speter     * with an error.
48550276Speter     */
48650276Speter    if (Status == AE_NO_HARDWARE_RESPONSE)
48797049Speter    {
48897049Speter        AcpiGbl_GlobalLockPresent = FALSE;
48997049Speter        Status = AE_OK;
49097049Speter    }
49197049Speter
49250276Speter    return_ACPI_STATUS (Status);
49350276Speter}
49450276Speter
495166124Srafan
496166124Srafan/******************************************************************************
497166124Srafan *
498166124Srafan * FUNCTION:    AcpiEvAcquireGlobalLock
499166124Srafan *
500166124Srafan * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
501166124Srafan *
502166124Srafan * RETURN:      Status
503166124Srafan *
504166124Srafan * DESCRIPTION: Attempt to gain ownership of the Global Lock.
505166124Srafan *
506166124Srafan *****************************************************************************/
507166124Srafan
508166124SrafanACPI_STATUS
509166124SrafanAcpiEvAcquireGlobalLock (
510166124Srafan    UINT16                  Timeout)
511166124Srafan{
512166124Srafan    ACPI_STATUS             Status = AE_OK;
513166124Srafan    BOOLEAN                 Acquired = FALSE;
514166124Srafan
515166124Srafan
516166124Srafan    ACPI_FUNCTION_TRACE ("EvAcquireGlobalLock");
517166124Srafan
518166124Srafan
519166124Srafan#ifndef ACPI_APPLICATION
520166124Srafan    /* Make sure that we actually have a global lock */
521166124Srafan
522166124Srafan    if (!AcpiGbl_GlobalLockPresent)
523166124Srafan    {
524166124Srafan        return_ACPI_STATUS (AE_NO_GLOBAL_LOCK);
525166124Srafan    }
526166124Srafan#endif
527166124Srafan
528166124Srafan    /* One more thread wants the global lock */
529166124Srafan
530166124Srafan    AcpiGbl_GlobalLockThreadCount++;
531166124Srafan
532166124Srafan    /* If we (OS side vs. BIOS side) have the hardware lock already, we are done */
533166124Srafan
534166124Srafan    if (AcpiGbl_GlobalLockAcquired)
535166124Srafan    {
536166124Srafan        return_ACPI_STATUS (AE_OK);
537166124Srafan    }
538166124Srafan
539166124Srafan    /* We must acquire the actual hardware lock */
540166124Srafan
541166124Srafan    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Acquired);
542166124Srafan    if (Acquired)
543166124Srafan    {
544166124Srafan       /* We got the lock */
545166124Srafan
546166124Srafan        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired the HW Global Lock\n"));
547166124Srafan
548166124Srafan        AcpiGbl_GlobalLockAcquired = TRUE;
549166124Srafan        return_ACPI_STATUS (AE_OK);
550166124Srafan    }
551166124Srafan
552166124Srafan    /*
553166124Srafan     * Did not get the lock.  The pending bit was set above, and we must now
554166124Srafan     * wait until we get the global lock released interrupt.
555166124Srafan     */
556166124Srafan    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for the HW Global Lock\n"));
557166124Srafan
558166124Srafan    /*
559166124Srafan     * Acquire the global lock semaphore first.
560166124Srafan     * Since this wait will block, we must release the interpreter
561166124Srafan     */
562166124Srafan    Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore,
563166124Srafan                                            Timeout);
564166124Srafan    return_ACPI_STATUS (Status);
565166124Srafan}
566166124Srafan
567166124Srafan
568166124Srafan/*******************************************************************************
569166124Srafan *
570166124Srafan * FUNCTION:    AcpiEvReleaseGlobalLock
571166124Srafan *
572166124Srafan * PARAMETERS:  None
573166124Srafan *
574166124Srafan * RETURN:      Status
575166124Srafan *
576166124Srafan * DESCRIPTION: Releases ownership of the Global Lock.
577166124Srafan *
578166124Srafan ******************************************************************************/
579166124Srafan
580166124SrafanACPI_STATUS
581166124SrafanAcpiEvReleaseGlobalLock (void)
582166124Srafan{
583166124Srafan    BOOLEAN                 Pending = FALSE;
584166124Srafan    ACPI_STATUS             Status = AE_OK;
585166124Srafan
586166124Srafan
587166124Srafan    ACPI_FUNCTION_TRACE ("EvReleaseGlobalLock");
58850276Speter
58950276Speter
59050276Speter    if (!AcpiGbl_GlobalLockThreadCount)
59150276Speter    {
59250276Speter        ACPI_REPORT_WARNING(("Cannot release HW Global Lock, it has not been acquired\n"));
59350276Speter        return_ACPI_STATUS (AE_NOT_ACQUIRED);
59450276Speter    }
59550276Speter
59650276Speter    /* One fewer thread has the global lock */
59750276Speter
59850276Speter    AcpiGbl_GlobalLockThreadCount--;
59950276Speter    if (AcpiGbl_GlobalLockThreadCount)
60050276Speter    {
60150276Speter        /* There are still some threads holding the lock, cannot release */
60250276Speter
60350276Speter        return_ACPI_STATUS (AE_OK);
604166124Srafan    }
60550276Speter
60650276Speter    /*
60750276Speter     * No more threads holding lock, we can do the actual hardware
60850276Speter     * release
60950276Speter     */
61050276Speter    ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_CommonFACS.GlobalLock, Pending);
61150276Speter    AcpiGbl_GlobalLockAcquired = FALSE;
61250276Speter
61350276Speter    /*
61450276Speter     * If the pending bit was set, we must write GBL_RLS to the control
61550276Speter     * register
61650276Speter     */
61750276Speter    if (Pending)
61850276Speter    {
61950276Speter        Status = AcpiSetRegister (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1, ACPI_MTX_LOCK);
62050276Speter    }
62150276Speter
62250276Speter    return_ACPI_STATUS (Status);
62350276Speter}
62450276Speter
62550276Speter
62650276Speter/******************************************************************************
62750276Speter *
62850276Speter * FUNCTION:    AcpiEvTerminate
62950276Speter *
63050276Speter * PARAMETERS:  none
63150276Speter *
63250276Speter * RETURN:      none
63350276Speter *
63450276Speter * DESCRIPTION: Disable events and free memory allocated for table storage.
63550276Speter *
63650276Speter ******************************************************************************/
63750276Speter
63850276Spetervoid
63950276SpeterAcpiEvTerminate (void)
640166124Srafan{
641166124Srafan    ACPI_NATIVE_UINT        i;
64250276Speter    ACPI_STATUS             Status;
64350276Speter
64450276Speter
64550276Speter    ACPI_FUNCTION_TRACE ("EvTerminate");
64650276Speter
64750276Speter
64850276Speter    if (AcpiGbl_EventsInitialized)
64950276Speter    {
65050276Speter        /*
65150276Speter         * Disable all event-related functionality.
65250276Speter         * In all cases, on error, print a message but obviously we don't abort.
65350276Speter         */
65450276Speter
65550276Speter        /* Disable all fixed events */
65650276Speter
65750276Speter        for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
65850276Speter        {
65950276Speter            Status = AcpiDisableEvent ((UINT32) i, 0);
66066963Speter            if (ACPI_FAILURE (Status))
66150276Speter            {
66250276Speter                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable fixed event %d\n", (UINT32) i));
663178866Srafan            }
664166124Srafan        }
66550276Speter
66650276Speter        /* Disable all GPEs in all GPE blocks */
66750276Speter
66850276Speter        Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, ACPI_NOT_ISR);
66966963Speter
67066963Speter        /* Remove SCI handler */
67166963Speter
672166124Srafan        Status = AcpiEvRemoveSciHandler ();
673166124Srafan        if (ACPI_FAILURE(Status))
674166124Srafan        {
67550276Speter            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not remove SCI handler\n"));
67650276Speter        }
677166124Srafan    }
67866963Speter
67950276Speter    /* Deallocate all handler objects installed within GPE info structs */
68050276Speter
68150276Speter    Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, ACPI_NOT_ISR);
68250276Speter
68350276Speter    /* Return to original mode if necessary */
68450276Speter
68550276Speter    if (AcpiGbl_OriginalMode == ACPI_SYS_MODE_LEGACY)
68650276Speter    {
68750276Speter        Status = AcpiDisable ();
68850276Speter        if (ACPI_FAILURE (Status))
68950276Speter        {
69097049Speter            ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "AcpiDisable failed\n"));
69150276Speter        }
69250276Speter    }
69350276Speter    return_VOID;
694178866Srafan}
69550276Speter
69650276Speter