evxface.c revision 206117
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: evxface - External interfaces for ACPI events
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
767754Smsmith/******************************************************************************
867754Smsmith *
967754Smsmith * 1. Copyright Notice
1067754Smsmith *
11202771Sjkim * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
1270243Smsmith * All rights reserved.
1367754Smsmith *
1467754Smsmith * 2. License
1567754Smsmith *
1667754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property
1767754Smsmith * rights.  You may have additional license terms from the party that provided
1867754Smsmith * you this software, covering your right to use that party's intellectual
1967754Smsmith * property rights.
2067754Smsmith *
2167754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
2267754Smsmith * copy of the source code appearing in this file ("Covered Code") an
2367754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the
2467754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy,
2567754Smsmith * make derivatives, distribute, use and display any portion of the Covered
2667754Smsmith * Code in any form, with the right to sublicense such rights; and
2767754Smsmith *
2867754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
2967754Smsmith * license (with the right to sublicense), under only those claims of Intel
3067754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell,
3167754Smsmith * offer to sell, and import the Covered Code and derivative works thereof
3267754Smsmith * solely to the minimum extent necessary to exercise the above copyright
3367754Smsmith * license, and in no event shall the patent license extend to any additions
3467754Smsmith * to or modifications of the Original Intel Code.  No other license or right
3567754Smsmith * is granted directly or by implication, estoppel or otherwise;
3667754Smsmith *
3767754Smsmith * The above copyright and patent license is granted only if the following
3867754Smsmith * conditions are met:
3967754Smsmith *
4067754Smsmith * 3. Conditions
4167754Smsmith *
4267754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43167802Sjkim * Redistribution of source code of any substantial portion of the Covered
4467754Smsmith * Code or modification with rights to further distribute source must include
4567754Smsmith * the above Copyright Notice, the above License, this list of Conditions,
4667754Smsmith * and the following Disclaimer and Export Compliance provision.  In addition,
4767754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to
4867754Smsmith * contain a file documenting the changes Licensee made to create that Covered
4967754Smsmith * Code and the date of any change.  Licensee must include in that file the
5067754Smsmith * documentation of any changes made by any predecessor Licensee.  Licensee
5167754Smsmith * must include a prominent statement that the modification is derived,
5267754Smsmith * directly or indirectly, from Original Intel Code.
5367754Smsmith *
5467754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
5567754Smsmith * Redistribution of source code of any substantial portion of the Covered
5667754Smsmith * Code or modification without rights to further distribute source must
5767754Smsmith * include the following Disclaimer and Export Compliance provision in the
5867754Smsmith * documentation and/or other materials provided with distribution.  In
5967754Smsmith * addition, Licensee may not authorize further sublicense of source of any
6067754Smsmith * portion of the Covered Code, and must include terms to the effect that the
6167754Smsmith * license from Licensee to its licensee is limited to the intellectual
6267754Smsmith * property embodied in the software Licensee provides to its licensee, and
6367754Smsmith * not to intellectual property embodied in modifications its licensee may
6467754Smsmith * make.
6567754Smsmith *
6667754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any
6767754Smsmith * substantial portion of the Covered Code or modification must reproduce the
6867754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance
6967754Smsmith * provision in the documentation and/or other materials provided with the
7067754Smsmith * distribution.
7167754Smsmith *
7267754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original
7367754Smsmith * Intel Code.
7467754Smsmith *
7567754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by
7667754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or
7767754Smsmith * other dealings in products derived from or relating to the Covered Code
7867754Smsmith * without prior written authorization from Intel.
7967754Smsmith *
8067754Smsmith * 4. Disclaimer and Export Compliance
8167754Smsmith *
8267754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
8367754Smsmith * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
8467754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
8567754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
8667754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
8767754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
8867754Smsmith * PARTICULAR PURPOSE.
8967754Smsmith *
9067754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
9167754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
9267754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
9367754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
9467754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
9567754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
9667754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
9767754Smsmith * LIMITED REMEDY.
9867754Smsmith *
9967754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this
10067754Smsmith * software or system incorporating such software without first obtaining any
10167754Smsmith * required license or other approval from the U. S. Department of Commerce or
10267754Smsmith * any other agency or department of the United States Government.  In the
10367754Smsmith * event Licensee exports any such software from the United States or
10467754Smsmith * re-exports any such software from a foreign destination, Licensee shall
10567754Smsmith * ensure that the distribution and export/re-export of the software is in
10667754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the
10767754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor
10867754Smsmith * any of its subsidiaries will export/re-export any technical data, process,
10967754Smsmith * software, or service, directly or indirectly, to any country for which the
11067754Smsmith * United States government or any agency thereof requires an export license,
11167754Smsmith * other governmental approval, or letter of assurance, without first obtaining
11267754Smsmith * such license, approval or letter.
11367754Smsmith *
11467754Smsmith *****************************************************************************/
11567754Smsmith
11667754Smsmith
11767754Smsmith#define __EVXFACE_C__
11867754Smsmith
119193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
120193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
121193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
122193341Sjkim#include <contrib/dev/acpica/include/acevents.h>
123193341Sjkim#include <contrib/dev/acpica/include/acinterp.h>
12467754Smsmith
12577424Smsmith#define _COMPONENT          ACPI_EVENTS
12691116Smsmith        ACPI_MODULE_NAME    ("evxface")
12767754Smsmith
12867754Smsmith
12977424Smsmith/*******************************************************************************
13067754Smsmith *
131138287Smarks * FUNCTION:    AcpiInstallExceptionHandler
132138287Smarks *
133138287Smarks * PARAMETERS:  Handler         - Pointer to the handler function for the
134138287Smarks *                                event
135138287Smarks *
136138287Smarks * RETURN:      Status
137138287Smarks *
138138287Smarks * DESCRIPTION: Saves the pointer to the handler function
139138287Smarks *
140138287Smarks ******************************************************************************/
141138287Smarks
142138287SmarksACPI_STATUS
143138287SmarksAcpiInstallExceptionHandler (
144138287Smarks    ACPI_EXCEPTION_HANDLER  Handler)
145138287Smarks{
146138287Smarks    ACPI_STATUS             Status;
147138287Smarks
148138287Smarks
149167802Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
150138287Smarks
151138287Smarks
152138287Smarks    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
153138287Smarks    if (ACPI_FAILURE (Status))
154138287Smarks    {
155138287Smarks        return_ACPI_STATUS (Status);
156138287Smarks    }
157138287Smarks
158138287Smarks    /* Don't allow two handlers. */
159138287Smarks
160138287Smarks    if (AcpiGbl_ExceptionHandler)
161138287Smarks    {
162138287Smarks        Status = AE_ALREADY_EXISTS;
163138287Smarks        goto Cleanup;
164138287Smarks    }
165138287Smarks
166138287Smarks    /* Install the handler */
167138287Smarks
168138287Smarks    AcpiGbl_ExceptionHandler = Handler;
169138287Smarks
170138287SmarksCleanup:
171138287Smarks    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
172138287Smarks    return_ACPI_STATUS (Status);
173138287Smarks}
174138287Smarks
175167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
176138287Smarks
177167802Sjkim
178138287Smarks/*******************************************************************************
179138287Smarks *
18067754Smsmith * FUNCTION:    AcpiInstallFixedEventHandler
18167754Smsmith *
18267754Smsmith * PARAMETERS:  Event           - Event type to enable.
18367754Smsmith *              Handler         - Pointer to the handler function for the
18467754Smsmith *                                event
18567754Smsmith *              Context         - Value passed to the handler on each GPE
18667754Smsmith *
18767754Smsmith * RETURN:      Status
18867754Smsmith *
18967754Smsmith * DESCRIPTION: Saves the pointer to the handler function and then enables the
19067754Smsmith *              event.
19167754Smsmith *
19267754Smsmith ******************************************************************************/
19367754Smsmith
19467754SmsmithACPI_STATUS
19567754SmsmithAcpiInstallFixedEventHandler (
19667754Smsmith    UINT32                  Event,
19777424Smsmith    ACPI_EVENT_HANDLER      Handler,
19867754Smsmith    void                    *Context)
19967754Smsmith{
20077424Smsmith    ACPI_STATUS             Status;
20167754Smsmith
20267754Smsmith
203167802Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
20467754Smsmith
20567754Smsmith
20677424Smsmith    /* Parameter validation */
20777424Smsmith
20877424Smsmith    if (Event > ACPI_EVENT_MAX)
20977424Smsmith    {
21067754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
21167754Smsmith    }
21267754Smsmith
21391116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
21491116Smsmith    if (ACPI_FAILURE (Status))
21591116Smsmith    {
21691116Smsmith        return_ACPI_STATUS (Status);
21791116Smsmith    }
21867754Smsmith
21967754Smsmith    /* Don't allow two handlers. */
22067754Smsmith
22167754Smsmith    if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
22267754Smsmith    {
22387031Smsmith        Status = AE_ALREADY_EXISTS;
22467754Smsmith        goto Cleanup;
22567754Smsmith    }
22667754Smsmith
22785756Smsmith    /* Install the handler before enabling the event */
22867754Smsmith
22967754Smsmith    AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
23067754Smsmith    AcpiGbl_FixedEventHandlers[Event].Context = Context;
23167754Smsmith
232117521Snjl    Status = AcpiEnableEvent (Event, 0);
23391116Smsmith    if (ACPI_FAILURE (Status))
23467754Smsmith    {
235204773Sjkim        ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
23667754Smsmith
23767754Smsmith        /* Remove the handler */
23867754Smsmith
23967754Smsmith        AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
24067754Smsmith        AcpiGbl_FixedEventHandlers[Event].Context = NULL;
24177424Smsmith    }
24277424Smsmith    else
24377424Smsmith    {
24482367Smsmith        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
24582367Smsmith            "Enabled fixed event %X, Handler=%p\n", Event, Handler));
24667754Smsmith    }
24767754Smsmith
24867754Smsmith
24967754SmsmithCleanup:
25091116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
25167754Smsmith    return_ACPI_STATUS (Status);
25267754Smsmith}
25367754Smsmith
254167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
25567754Smsmith
256167802Sjkim
25777424Smsmith/*******************************************************************************
25867754Smsmith *
25967754Smsmith * FUNCTION:    AcpiRemoveFixedEventHandler
26067754Smsmith *
26167754Smsmith * PARAMETERS:  Event           - Event type to disable.
26267754Smsmith *              Handler         - Address of the handler
26367754Smsmith *
26467754Smsmith * RETURN:      Status
26567754Smsmith *
26667754Smsmith * DESCRIPTION: Disables the event and unregisters the event handler.
26767754Smsmith *
26867754Smsmith ******************************************************************************/
26967754Smsmith
27067754SmsmithACPI_STATUS
27167754SmsmithAcpiRemoveFixedEventHandler (
27267754Smsmith    UINT32                  Event,
27377424Smsmith    ACPI_EVENT_HANDLER      Handler)
27467754Smsmith{
27567754Smsmith    ACPI_STATUS             Status = AE_OK;
27667754Smsmith
27767754Smsmith
278167802Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
27967754Smsmith
28067754Smsmith
28177424Smsmith    /* Parameter validation */
28277424Smsmith
28377424Smsmith    if (Event > ACPI_EVENT_MAX)
28477424Smsmith    {
28567754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
28667754Smsmith    }
28767754Smsmith
28891116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
28991116Smsmith    if (ACPI_FAILURE (Status))
29091116Smsmith    {
29191116Smsmith        return_ACPI_STATUS (Status);
29291116Smsmith    }
29367754Smsmith
29485756Smsmith    /* Disable the event before removing the handler */
29567754Smsmith
296117521Snjl    Status = AcpiDisableEvent (Event, 0);
29769450Smsmith
29877424Smsmith    /* Always Remove the handler */
29977424Smsmith
30077424Smsmith    AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
30177424Smsmith    AcpiGbl_FixedEventHandlers[Event].Context = NULL;
30277424Smsmith
30391116Smsmith    if (ACPI_FAILURE (Status))
30467754Smsmith    {
305167802Sjkim        ACPI_WARNING ((AE_INFO,
306204773Sjkim            "Could not write to fixed event enable register 0x%X", Event));
30777424Smsmith    }
30877424Smsmith    else
30977424Smsmith    {
310167802Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
31167754Smsmith    }
31267754Smsmith
31391116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
31467754Smsmith    return_ACPI_STATUS (Status);
31567754Smsmith}
31667754Smsmith
317167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
31867754Smsmith
319167802Sjkim
32077424Smsmith/*******************************************************************************
32167754Smsmith *
32267754Smsmith * FUNCTION:    AcpiInstallNotifyHandler
32367754Smsmith *
32467754Smsmith * PARAMETERS:  Device          - The device for which notifies will be handled
32567754Smsmith *              HandlerType     - The type of handler:
32667754Smsmith *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
32767754Smsmith *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
328129684Snjl *                                  ACPI_ALL_NOTIFY:  both system and device
32967754Smsmith *              Handler         - Address of the handler
33067754Smsmith *              Context         - Value passed to the handler on each GPE
33167754Smsmith *
33267754Smsmith * RETURN:      Status
33367754Smsmith *
33467754Smsmith * DESCRIPTION: Install a handler for notifies on an ACPI device
33567754Smsmith *
33667754Smsmith ******************************************************************************/
33767754Smsmith
33867754SmsmithACPI_STATUS
33967754SmsmithAcpiInstallNotifyHandler (
34067754Smsmith    ACPI_HANDLE             Device,
34167754Smsmith    UINT32                  HandlerType,
34277424Smsmith    ACPI_NOTIFY_HANDLER     Handler,
34367754Smsmith    void                    *Context)
34467754Smsmith{
34567754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
34667754Smsmith    ACPI_OPERAND_OBJECT     *NotifyObj;
34799146Siwasaki    ACPI_NAMESPACE_NODE     *Node;
34891116Smsmith    ACPI_STATUS             Status;
34967754Smsmith
35067754Smsmith
351167802Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
35267754Smsmith
35367754Smsmith
35467754Smsmith    /* Parameter validation */
35567754Smsmith
35699146Siwasaki    if ((!Device)  ||
35799146Siwasaki        (!Handler) ||
35867754Smsmith        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
35967754Smsmith    {
36067754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
36167754Smsmith    }
36267754Smsmith
36391116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
36491116Smsmith    if (ACPI_FAILURE (Status))
36591116Smsmith    {
36691116Smsmith        return_ACPI_STATUS (Status);
36791116Smsmith    }
36871867Smsmith
36967754Smsmith    /* Convert and validate the device handle */
37067754Smsmith
371200553Sjkim    Node = AcpiNsValidateHandle (Device);
37299146Siwasaki    if (!Node)
37367754Smsmith    {
37467754Smsmith        Status = AE_BAD_PARAMETER;
37567754Smsmith        goto UnlockAndExit;
37667754Smsmith    }
37767754Smsmith
37867754Smsmith    /*
37971867Smsmith     * Root Object:
38071867Smsmith     * Registering a notify handler on the root object indicates that the
381193267Sjkim     * caller wishes to receive notifications for all objects. Note that
38271867Smsmith     * only one <external> global handler can be regsitered (per notify type).
38367754Smsmith     */
38467754Smsmith    if (Device == ACPI_ROOT_OBJECT)
38567754Smsmith    {
38671867Smsmith        /* Make sure the handler is not already installed */
38767754Smsmith
388129684Snjl        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
389129684Snjl                AcpiGbl_SystemNotify.Handler)       ||
390129684Snjl            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
391117521Snjl                AcpiGbl_DeviceNotify.Handler))
39267754Smsmith        {
39387031Smsmith            Status = AE_ALREADY_EXISTS;
39467754Smsmith            goto UnlockAndExit;
39567754Smsmith        }
39667754Smsmith
397129684Snjl        if (HandlerType & ACPI_SYSTEM_NOTIFY)
39867754Smsmith        {
399117521Snjl            AcpiGbl_SystemNotify.Node    = Node;
400117521Snjl            AcpiGbl_SystemNotify.Handler = Handler;
401117521Snjl            AcpiGbl_SystemNotify.Context = Context;
40267754Smsmith        }
403129684Snjl
404129684Snjl        if (HandlerType & ACPI_DEVICE_NOTIFY)
40567754Smsmith        {
406117521Snjl            AcpiGbl_DeviceNotify.Node    = Node;
407117521Snjl            AcpiGbl_DeviceNotify.Handler = Handler;
408117521Snjl            AcpiGbl_DeviceNotify.Context = Context;
40967754Smsmith        }
41067754Smsmith
41167754Smsmith        /* Global notify handler installed */
41267754Smsmith    }
41367754Smsmith
41467754Smsmith    /*
41585756Smsmith     * All Other Objects:
41671867Smsmith     * Caller will only receive notifications specific to the target object.
41771867Smsmith     * Note that only certain object types can receive notifications.
41867754Smsmith     */
41987031Smsmith    else
42085756Smsmith    {
42199146Siwasaki        /* Notifies allowed on this object? */
42299146Siwasaki
42399146Siwasaki        if (!AcpiEvIsNotifyObject (Node))
42467754Smsmith        {
42599146Siwasaki            Status = AE_TYPE;
42667754Smsmith            goto UnlockAndExit;
42767754Smsmith        }
42867754Smsmith
42971867Smsmith        /* Check for an existing internal object */
43067754Smsmith
43199146Siwasaki        ObjDesc = AcpiNsGetAttachedObject (Node);
43271867Smsmith        if (ObjDesc)
43367754Smsmith        {
43471867Smsmith            /* Object exists - make sure there's no handler */
43571867Smsmith
436129684Snjl            if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
437117521Snjl                    ObjDesc->CommonNotify.SystemNotify)   ||
438129684Snjl                ((HandlerType & ACPI_DEVICE_NOTIFY) &&
439117521Snjl                    ObjDesc->CommonNotify.DeviceNotify))
44071867Smsmith            {
44187031Smsmith                Status = AE_ALREADY_EXISTS;
44271867Smsmith                goto UnlockAndExit;
44371867Smsmith            }
44467754Smsmith        }
44571867Smsmith        else
44671867Smsmith        {
44771867Smsmith            /* Create a new object */
44867754Smsmith
44999146Siwasaki            ObjDesc = AcpiUtCreateInternalObject (Node->Type);
45071867Smsmith            if (!ObjDesc)
45171867Smsmith            {
45271867Smsmith                Status = AE_NO_MEMORY;
45371867Smsmith                goto UnlockAndExit;
45471867Smsmith            }
45567754Smsmith
45671867Smsmith            /* Attach new object to the Node */
45771867Smsmith
45899146Siwasaki            Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
459117521Snjl
460117521Snjl            /* Remove local reference to the object */
461117521Snjl
462117521Snjl            AcpiUtRemoveReference (ObjDesc);
46371867Smsmith            if (ACPI_FAILURE (Status))
46471867Smsmith            {
46571867Smsmith                goto UnlockAndExit;
46671867Smsmith            }
46771867Smsmith        }
46871867Smsmith
46971867Smsmith        /* Install the handler */
47071867Smsmith
471107325Siwasaki        NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
47271867Smsmith        if (!NotifyObj)
47367754Smsmith        {
47471867Smsmith            Status = AE_NO_MEMORY;
47567754Smsmith            goto UnlockAndExit;
47667754Smsmith        }
47767754Smsmith
478117521Snjl        NotifyObj->Notify.Node    = Node;
479117521Snjl        NotifyObj->Notify.Handler = Handler;
480117521Snjl        NotifyObj->Notify.Context = Context;
48167754Smsmith
482129684Snjl        if (HandlerType & ACPI_SYSTEM_NOTIFY)
48371867Smsmith        {
484117521Snjl            ObjDesc->CommonNotify.SystemNotify = NotifyObj;
48571867Smsmith        }
486129684Snjl
487129684Snjl        if (HandlerType & ACPI_DEVICE_NOTIFY)
48871867Smsmith        {
489117521Snjl            ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
49071867Smsmith        }
491129684Snjl
492129684Snjl        if (HandlerType == ACPI_ALL_NOTIFY)
493129684Snjl        {
494129684Snjl            /* Extra ref if installed in both */
495129684Snjl
496129684Snjl            AcpiUtAddReference (NotifyObj);
497129684Snjl        }
49867754Smsmith    }
49967754Smsmith
50085756Smsmith
50167754SmsmithUnlockAndExit:
50291116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
50367754Smsmith    return_ACPI_STATUS (Status);
50467754Smsmith}
50567754Smsmith
506167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
50767754Smsmith
508167802Sjkim
50977424Smsmith/*******************************************************************************
51067754Smsmith *
51167754Smsmith * FUNCTION:    AcpiRemoveNotifyHandler
51267754Smsmith *
51367754Smsmith * PARAMETERS:  Device          - The device for which notifies will be handled
51467754Smsmith *              HandlerType     - The type of handler:
51567754Smsmith *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
51667754Smsmith *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
517129684Snjl *                                  ACPI_ALL_NOTIFY:  both system and device
51867754Smsmith *              Handler         - Address of the handler
519138287Smarks *
52067754Smsmith * RETURN:      Status
52167754Smsmith *
52267754Smsmith * DESCRIPTION: Remove a handler for notifies on an ACPI device
52367754Smsmith *
52467754Smsmith ******************************************************************************/
52567754Smsmith
52667754SmsmithACPI_STATUS
52767754SmsmithAcpiRemoveNotifyHandler (
52867754Smsmith    ACPI_HANDLE             Device,
52967754Smsmith    UINT32                  HandlerType,
53077424Smsmith    ACPI_NOTIFY_HANDLER     Handler)
53167754Smsmith{
53267754Smsmith    ACPI_OPERAND_OBJECT     *NotifyObj;
53367754Smsmith    ACPI_OPERAND_OBJECT     *ObjDesc;
53499146Siwasaki    ACPI_NAMESPACE_NODE     *Node;
53591116Smsmith    ACPI_STATUS             Status;
53667754Smsmith
53777424Smsmith
538167802Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
53967754Smsmith
54077424Smsmith
54167754Smsmith    /* Parameter validation */
54267754Smsmith
54399146Siwasaki    if ((!Device)  ||
54499146Siwasaki        (!Handler) ||
54567754Smsmith        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
54667754Smsmith    {
54767754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
54867754Smsmith    }
54967754Smsmith
55091116Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
55191116Smsmith    if (ACPI_FAILURE (Status))
55291116Smsmith    {
55391116Smsmith        return_ACPI_STATUS (Status);
55491116Smsmith    }
55567754Smsmith
55667754Smsmith    /* Convert and validate the device handle */
55767754Smsmith
558200553Sjkim    Node = AcpiNsValidateHandle (Device);
55999146Siwasaki    if (!Node)
56067754Smsmith    {
56167754Smsmith        Status = AE_BAD_PARAMETER;
56267754Smsmith        goto UnlockAndExit;
56367754Smsmith    }
56467754Smsmith
565138287Smarks    /* Root Object */
566138287Smarks
56787031Smsmith    if (Device == ACPI_ROOT_OBJECT)
56885756Smsmith    {
569151937Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
570167802Sjkim            "Removing notify handler for namespace root object\n"));
57167754Smsmith
572129684Snjl        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
573129684Snjl              !AcpiGbl_SystemNotify.Handler)        ||
574129684Snjl            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
575117521Snjl              !AcpiGbl_DeviceNotify.Handler))
57671867Smsmith        {
57771867Smsmith            Status = AE_NOT_EXIST;
57871867Smsmith            goto UnlockAndExit;
57971867Smsmith        }
58067754Smsmith
581129684Snjl        if (HandlerType & ACPI_SYSTEM_NOTIFY)
58285756Smsmith        {
583117521Snjl            AcpiGbl_SystemNotify.Node    = NULL;
584117521Snjl            AcpiGbl_SystemNotify.Handler = NULL;
585117521Snjl            AcpiGbl_SystemNotify.Context = NULL;
58671867Smsmith        }
587129684Snjl
588129684Snjl        if (HandlerType & ACPI_DEVICE_NOTIFY)
58985756Smsmith        {
590117521Snjl            AcpiGbl_DeviceNotify.Node    = NULL;
591117521Snjl            AcpiGbl_DeviceNotify.Handler = NULL;
592117521Snjl            AcpiGbl_DeviceNotify.Context = NULL;
59371867Smsmith        }
59467754Smsmith    }
59567754Smsmith
596138287Smarks    /* All Other Objects */
597138287Smarks
59887031Smsmith    else
59985756Smsmith    {
60099146Siwasaki        /* Notifies allowed on this object? */
60199146Siwasaki
60299146Siwasaki        if (!AcpiEvIsNotifyObject (Node))
60371867Smsmith        {
60499146Siwasaki            Status = AE_TYPE;
60571867Smsmith            goto UnlockAndExit;
60671867Smsmith        }
60767754Smsmith
60871867Smsmith        /* Check for an existing internal object */
60967754Smsmith
61099146Siwasaki        ObjDesc = AcpiNsGetAttachedObject (Node);
61171867Smsmith        if (!ObjDesc)
61271867Smsmith        {
61371867Smsmith            Status = AE_NOT_EXIST;
61471867Smsmith            goto UnlockAndExit;
61571867Smsmith        }
61667754Smsmith
61771867Smsmith        /* Object exists - make sure there's an existing handler */
61871867Smsmith
619129684Snjl        if (HandlerType & ACPI_SYSTEM_NOTIFY)
62071867Smsmith        {
621117521Snjl            NotifyObj = ObjDesc->CommonNotify.SystemNotify;
622167802Sjkim            if (!NotifyObj)
623129684Snjl            {
624167802Sjkim                Status = AE_NOT_EXIST;
625167802Sjkim                goto UnlockAndExit;
626167802Sjkim            }
627167802Sjkim
628167802Sjkim            if (NotifyObj->Notify.Handler != Handler)
629167802Sjkim            {
630129684Snjl                Status = AE_BAD_PARAMETER;
631129684Snjl                goto UnlockAndExit;
632129684Snjl            }
633129684Snjl
634129684Snjl            /* Remove the handler */
635129684Snjl
636129684Snjl            ObjDesc->CommonNotify.SystemNotify = NULL;
637129684Snjl            AcpiUtRemoveReference (NotifyObj);
63871867Smsmith        }
639129684Snjl
640129684Snjl        if (HandlerType & ACPI_DEVICE_NOTIFY)
64171867Smsmith        {
642117521Snjl            NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
643167802Sjkim            if (!NotifyObj)
644129684Snjl            {
645167802Sjkim                Status = AE_NOT_EXIST;
646167802Sjkim                goto UnlockAndExit;
647167802Sjkim            }
648167802Sjkim
649167802Sjkim            if (NotifyObj->Notify.Handler != Handler)
650167802Sjkim            {
651129684Snjl                Status = AE_BAD_PARAMETER;
652129684Snjl                goto UnlockAndExit;
653129684Snjl            }
65471867Smsmith
655129684Snjl            /* Remove the handler */
65671867Smsmith
657117521Snjl            ObjDesc->CommonNotify.DeviceNotify = NULL;
658129684Snjl            AcpiUtRemoveReference (NotifyObj);
65971867Smsmith        }
66067754Smsmith    }
66167754Smsmith
66267754Smsmith
66367754SmsmithUnlockAndExit:
66491116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
66567754Smsmith    return_ACPI_STATUS (Status);
66667754Smsmith}
66767754Smsmith
668167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
66971867Smsmith
670167802Sjkim
67177424Smsmith/*******************************************************************************
67267754Smsmith *
67367754Smsmith * FUNCTION:    AcpiInstallGpeHandler
67467754Smsmith *
675151937Sjkim * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
676151937Sjkim *                                defined GPEs)
677151937Sjkim *              GpeNumber       - The GPE number within the GPE block
67867754Smsmith *              Type            - Whether this GPE should be treated as an
67967754Smsmith *                                edge- or level-triggered interrupt.
680129684Snjl *              Address         - Address of the handler
68167754Smsmith *              Context         - Value passed to the handler on each GPE
68267754Smsmith *
68367754Smsmith * RETURN:      Status
68467754Smsmith *
68567754Smsmith * DESCRIPTION: Install a handler for a General Purpose Event.
68667754Smsmith *
68767754Smsmith ******************************************************************************/
68867754Smsmith
68967754SmsmithACPI_STATUS
69067754SmsmithAcpiInstallGpeHandler (
691117521Snjl    ACPI_HANDLE             GpeDevice,
69267754Smsmith    UINT32                  GpeNumber,
69367754Smsmith    UINT32                  Type,
694129684Snjl    ACPI_EVENT_HANDLER      Address,
69567754Smsmith    void                    *Context)
69667754Smsmith{
697129684Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
698129684Snjl    ACPI_HANDLER_INFO       *Handler;
69991116Smsmith    ACPI_STATUS             Status;
700167802Sjkim    ACPI_CPU_FLAGS          Flags;
70167754Smsmith
70277424Smsmith
703167802Sjkim    ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
70467754Smsmith
70577424Smsmith
70667754Smsmith    /* Parameter validation */
70767754Smsmith
708206117Sjkim    if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
70967754Smsmith    {
71067754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
71167754Smsmith    }
71267754Smsmith
713117521Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
714117521Snjl    if (ACPI_FAILURE (Status))
715117521Snjl    {
716117521Snjl        return_ACPI_STATUS (Status);
717117521Snjl    }
718117521Snjl
71967754Smsmith    /* Ensure that we have a valid GPE number */
72067754Smsmith
721117521Snjl    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
722114237Snjl    if (!GpeEventInfo)
72367754Smsmith    {
724117521Snjl        Status = AE_BAD_PARAMETER;
725117521Snjl        goto UnlockAndExit;
72667754Smsmith    }
72767754Smsmith
72867754Smsmith    /* Make sure that there isn't a handler there already */
72967754Smsmith
730193267Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
731193267Sjkim            ACPI_GPE_DISPATCH_HANDLER)
73267754Smsmith    {
73387031Smsmith        Status = AE_ALREADY_EXISTS;
734117521Snjl        goto UnlockAndExit;
73567754Smsmith    }
73667754Smsmith
737129684Snjl    /* Allocate and init handler object */
73867754Smsmith
739167802Sjkim    Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_HANDLER_INFO));
740129684Snjl    if (!Handler)
741129684Snjl    {
742129684Snjl        Status = AE_NO_MEMORY;
743129684Snjl        goto UnlockAndExit;
744129684Snjl    }
74567754Smsmith
746129684Snjl    Handler->Address    = Address;
747129684Snjl    Handler->Context    = Context;
748129684Snjl    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
74967754Smsmith
750129684Snjl    /* Disable the GPE before installing the handler */
751129684Snjl
752129684Snjl    Status = AcpiEvDisableGpe (GpeEventInfo);
75399679Siwasaki    if (ACPI_FAILURE (Status))
75499679Siwasaki    {
755117521Snjl        goto UnlockAndExit;
75699679Siwasaki    }
75767754Smsmith
758129684Snjl    /* Install the handler */
75985756Smsmith
760151937Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
761129684Snjl    GpeEventInfo->Dispatch.Handler = Handler;
76299679Siwasaki
763129684Snjl    /* Setup up dispatch flags to indicate handler (vs. method) */
764129684Snjl
765193267Sjkim    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
766129684Snjl    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
767129684Snjl
768151937Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
769129684Snjl
770129684Snjl
771117521SnjlUnlockAndExit:
77291116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
77367754Smsmith    return_ACPI_STATUS (Status);
77467754Smsmith}
77567754Smsmith
776167802SjkimACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
77767754Smsmith
778167802Sjkim
77977424Smsmith/*******************************************************************************
78067754Smsmith *
78167754Smsmith * FUNCTION:    AcpiRemoveGpeHandler
78267754Smsmith *
783151937Sjkim * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
784151937Sjkim *                                defined GPEs)
785151937Sjkim *              GpeNumber       - The event to remove a handler
786129684Snjl *              Address         - Address of the handler
78767754Smsmith *
78867754Smsmith * RETURN:      Status
78967754Smsmith *
79067754Smsmith * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
79167754Smsmith *
79267754Smsmith ******************************************************************************/
79367754Smsmith
79467754SmsmithACPI_STATUS
79567754SmsmithAcpiRemoveGpeHandler (
796117521Snjl    ACPI_HANDLE             GpeDevice,
79767754Smsmith    UINT32                  GpeNumber,
798129684Snjl    ACPI_EVENT_HANDLER      Address)
79967754Smsmith{
800129684Snjl    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
801129684Snjl    ACPI_HANDLER_INFO       *Handler;
80291116Smsmith    ACPI_STATUS             Status;
803167802Sjkim    ACPI_CPU_FLAGS          Flags;
80467754Smsmith
80567754Smsmith
806167802Sjkim    ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
80767754Smsmith
80867754Smsmith
80967754Smsmith    /* Parameter validation */
81067754Smsmith
811129684Snjl    if (!Address)
81267754Smsmith    {
81367754Smsmith        return_ACPI_STATUS (AE_BAD_PARAMETER);
81467754Smsmith    }
81567754Smsmith
816117521Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
817117521Snjl    if (ACPI_FAILURE (Status))
818117521Snjl    {
819117521Snjl        return_ACPI_STATUS (Status);
820117521Snjl    }
821117521Snjl
82267754Smsmith    /* Ensure that we have a valid GPE number */
82367754Smsmith
824117521Snjl    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
825114237Snjl    if (!GpeEventInfo)
82667754Smsmith    {
827117521Snjl        Status = AE_BAD_PARAMETER;
828117521Snjl        goto UnlockAndExit;
82967754Smsmith    }
83067754Smsmith
831129684Snjl    /* Make sure that a handler is indeed installed */
83267754Smsmith
833193267Sjkim    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
834193267Sjkim            ACPI_GPE_DISPATCH_HANDLER)
83599679Siwasaki    {
836129684Snjl        Status = AE_NOT_EXIST;
837117521Snjl        goto UnlockAndExit;
83899679Siwasaki    }
83967754Smsmith
84067754Smsmith    /* Make sure that the installed handler is the same */
84167754Smsmith
842129684Snjl    if (GpeEventInfo->Dispatch.Handler->Address != Address)
84367754Smsmith    {
84467754Smsmith        Status = AE_BAD_PARAMETER;
845117521Snjl        goto UnlockAndExit;
84667754Smsmith    }
84767754Smsmith
848129684Snjl    /* Disable the GPE before removing the handler */
849129684Snjl
850129684Snjl    Status = AcpiEvDisableGpe (GpeEventInfo);
851129684Snjl    if (ACPI_FAILURE (Status))
852129684Snjl    {
853129684Snjl        goto UnlockAndExit;
854129684Snjl    }
855129684Snjl
85667754Smsmith    /* Remove the handler */
85767754Smsmith
858151937Sjkim    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
859129684Snjl    Handler = GpeEventInfo->Dispatch.Handler;
860129684Snjl
861129684Snjl    /* Restore Method node (if any), set dispatch flags */
862129684Snjl
863129684Snjl    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
864129684Snjl    GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;  /* Clear bits */
865129684Snjl    if (Handler->MethodNode)
866129684Snjl    {
867129684Snjl        GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD;
868129684Snjl    }
869151937Sjkim    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
87067754Smsmith
871129684Snjl    /* Now we can free the handler object */
87285756Smsmith
873167802Sjkim    ACPI_FREE (Handler);
874129684Snjl
875129684Snjl
876117521SnjlUnlockAndExit:
87791116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
87867754Smsmith    return_ACPI_STATUS (Status);
87967754Smsmith}
88067754Smsmith
881167802SjkimACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
88267754Smsmith
883167802Sjkim
88477424Smsmith/*******************************************************************************
88567754Smsmith *
88667754Smsmith * FUNCTION:    AcpiAcquireGlobalLock
88767754Smsmith *
88867754Smsmith * PARAMETERS:  Timeout         - How long the caller is willing to wait
889151937Sjkim *              Handle          - Where the handle to the lock is returned
890151937Sjkim *                                (if acquired)
89167754Smsmith *
89267754Smsmith * RETURN:      Status
89367754Smsmith *
89467754Smsmith * DESCRIPTION: Acquire the ACPI Global Lock
89567754Smsmith *
896167802Sjkim * Note: Allows callers with the same thread ID to acquire the global lock
897167802Sjkim * multiple times. In other words, externally, the behavior of the global lock
898167802Sjkim * is identical to an AML mutex. On the first acquire, a new handle is
899167802Sjkim * returned. On any subsequent calls to acquire by the same thread, the same
900167802Sjkim * handle is returned.
901167802Sjkim *
90267754Smsmith ******************************************************************************/
90385756Smsmith
90467754SmsmithACPI_STATUS
90567754SmsmithAcpiAcquireGlobalLock (
906107325Siwasaki    UINT16                  Timeout,
90791116Smsmith    UINT32                  *Handle)
90867754Smsmith{
90967754Smsmith    ACPI_STATUS             Status;
91067754Smsmith
91167754Smsmith
91291116Smsmith    if (!Handle)
91391116Smsmith    {
91491116Smsmith        return (AE_BAD_PARAMETER);
91591116Smsmith    }
91691116Smsmith
917167802Sjkim    /* Must lock interpreter to prevent race conditions */
91877424Smsmith
919167802Sjkim    AcpiExEnterInterpreter ();
92067754Smsmith
921167802Sjkim    Status = AcpiExAcquireMutexObject (Timeout,
922167802Sjkim                AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
923167802Sjkim
92491116Smsmith    if (ACPI_SUCCESS (Status))
92591116Smsmith    {
926172314Sjkim        /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
927167802Sjkim
92891116Smsmith        *Handle = AcpiGbl_GlobalLockHandle;
92991116Smsmith    }
93091116Smsmith
931167802Sjkim    AcpiExExitInterpreter ();
93267754Smsmith    return (Status);
93367754Smsmith}
93467754Smsmith
935167802SjkimACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
93667754Smsmith
937167802Sjkim
93877424Smsmith/*******************************************************************************
93967754Smsmith *
94067754Smsmith * FUNCTION:    AcpiReleaseGlobalLock
94167754Smsmith *
94267754Smsmith * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
94367754Smsmith *
94467754Smsmith * RETURN:      Status
94567754Smsmith *
946151937Sjkim * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
94767754Smsmith *
94867754Smsmith ******************************************************************************/
94967754Smsmith
95067754SmsmithACPI_STATUS
95167754SmsmithAcpiReleaseGlobalLock (
95291116Smsmith    UINT32                  Handle)
95367754Smsmith{
95499679Siwasaki    ACPI_STATUS             Status;
95585756Smsmith
95699679Siwasaki
957167802Sjkim    if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
95891116Smsmith    {
95991116Smsmith        return (AE_NOT_ACQUIRED);
96091116Smsmith    }
96191116Smsmith
962167802Sjkim    Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
96399679Siwasaki    return (Status);
96467754Smsmith}
96567754Smsmith
966167802SjkimACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
96767754Smsmith
968