xref: /onnv-gate/usr/src/uts/intel/io/acpica/events/evxface.c (revision 9980:13d7f3eec672)
13446Smrj /******************************************************************************
23446Smrj  *
33446Smrj  * Module Name: evxface - External interfaces for ACPI events
43446Smrj  *
53446Smrj  *****************************************************************************/
63446Smrj 
73446Smrj /******************************************************************************
83446Smrj  *
93446Smrj  * 1. Copyright Notice
103446Smrj  *
11*9980SDana.Myers@Sun.COM  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
123446Smrj  * All rights reserved.
133446Smrj  *
143446Smrj  * 2. License
153446Smrj  *
163446Smrj  * 2.1. This is your license from Intel Corp. under its intellectual property
173446Smrj  * rights.  You may have additional license terms from the party that provided
183446Smrj  * you this software, covering your right to use that party's intellectual
193446Smrj  * property rights.
203446Smrj  *
213446Smrj  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
223446Smrj  * copy of the source code appearing in this file ("Covered Code") an
233446Smrj  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
243446Smrj  * base code distributed originally by Intel ("Original Intel Code") to copy,
253446Smrj  * make derivatives, distribute, use and display any portion of the Covered
263446Smrj  * Code in any form, with the right to sublicense such rights; and
273446Smrj  *
283446Smrj  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
293446Smrj  * license (with the right to sublicense), under only those claims of Intel
303446Smrj  * patents that are infringed by the Original Intel Code, to make, use, sell,
313446Smrj  * offer to sell, and import the Covered Code and derivative works thereof
323446Smrj  * solely to the minimum extent necessary to exercise the above copyright
333446Smrj  * license, and in no event shall the patent license extend to any additions
343446Smrj  * to or modifications of the Original Intel Code.  No other license or right
353446Smrj  * is granted directly or by implication, estoppel or otherwise;
363446Smrj  *
373446Smrj  * The above copyright and patent license is granted only if the following
383446Smrj  * conditions are met:
393446Smrj  *
403446Smrj  * 3. Conditions
413446Smrj  *
423446Smrj  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
433446Smrj  * Redistribution of source code of any substantial portion of the Covered
443446Smrj  * Code or modification with rights to further distribute source must include
453446Smrj  * the above Copyright Notice, the above License, this list of Conditions,
463446Smrj  * and the following Disclaimer and Export Compliance provision.  In addition,
473446Smrj  * Licensee must cause all Covered Code to which Licensee contributes to
483446Smrj  * contain a file documenting the changes Licensee made to create that Covered
493446Smrj  * Code and the date of any change.  Licensee must include in that file the
503446Smrj  * documentation of any changes made by any predecessor Licensee.  Licensee
513446Smrj  * must include a prominent statement that the modification is derived,
523446Smrj  * directly or indirectly, from Original Intel Code.
533446Smrj  *
543446Smrj  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
553446Smrj  * Redistribution of source code of any substantial portion of the Covered
563446Smrj  * Code or modification without rights to further distribute source must
573446Smrj  * include the following Disclaimer and Export Compliance provision in the
583446Smrj  * documentation and/or other materials provided with distribution.  In
593446Smrj  * addition, Licensee may not authorize further sublicense of source of any
603446Smrj  * portion of the Covered Code, and must include terms to the effect that the
613446Smrj  * license from Licensee to its licensee is limited to the intellectual
623446Smrj  * property embodied in the software Licensee provides to its licensee, and
633446Smrj  * not to intellectual property embodied in modifications its licensee may
643446Smrj  * make.
653446Smrj  *
663446Smrj  * 3.3. Redistribution of Executable. Redistribution in executable form of any
673446Smrj  * substantial portion of the Covered Code or modification must reproduce the
683446Smrj  * above Copyright Notice, and the following Disclaimer and Export Compliance
693446Smrj  * provision in the documentation and/or other materials provided with the
703446Smrj  * distribution.
713446Smrj  *
723446Smrj  * 3.4. Intel retains all right, title, and interest in and to the Original
733446Smrj  * Intel Code.
743446Smrj  *
753446Smrj  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
763446Smrj  * Intel shall be used in advertising or otherwise to promote the sale, use or
773446Smrj  * other dealings in products derived from or relating to the Covered Code
783446Smrj  * without prior written authorization from Intel.
793446Smrj  *
803446Smrj  * 4. Disclaimer and Export Compliance
813446Smrj  *
823446Smrj  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
833446Smrj  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
843446Smrj  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
853446Smrj  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
863446Smrj  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
873446Smrj  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
883446Smrj  * PARTICULAR PURPOSE.
893446Smrj  *
903446Smrj  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
913446Smrj  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
923446Smrj  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
933446Smrj  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
943446Smrj  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
953446Smrj  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
963446Smrj  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
973446Smrj  * LIMITED REMEDY.
983446Smrj  *
993446Smrj  * 4.3. Licensee shall not export, either directly or indirectly, any of this
1003446Smrj  * software or system incorporating such software without first obtaining any
1013446Smrj  * required license or other approval from the U. S. Department of Commerce or
1023446Smrj  * any other agency or department of the United States Government.  In the
1033446Smrj  * event Licensee exports any such software from the United States or
1043446Smrj  * re-exports any such software from a foreign destination, Licensee shall
1053446Smrj  * ensure that the distribution and export/re-export of the software is in
1063446Smrj  * compliance with all laws, regulations, orders, or other restrictions of the
1073446Smrj  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1083446Smrj  * any of its subsidiaries will export/re-export any technical data, process,
1093446Smrj  * software, or service, directly or indirectly, to any country for which the
1103446Smrj  * United States government or any agency thereof requires an export license,
1113446Smrj  * other governmental approval, or letter of assurance, without first obtaining
1123446Smrj  * such license, approval or letter.
1133446Smrj  *
1143446Smrj  *****************************************************************************/
1153446Smrj 
1163446Smrj 
1173446Smrj #define __EVXFACE_C__
1183446Smrj 
1193446Smrj #include "acpi.h"
120*9980SDana.Myers@Sun.COM #include "accommon.h"
1213446Smrj #include "acnamesp.h"
1223446Smrj #include "acevents.h"
1233446Smrj #include "acinterp.h"
1243446Smrj 
1253446Smrj #define _COMPONENT          ACPI_EVENTS
1263446Smrj         ACPI_MODULE_NAME    ("evxface")
1273446Smrj 
1283446Smrj 
1293446Smrj /*******************************************************************************
1303446Smrj  *
1313446Smrj  * FUNCTION:    AcpiInstallExceptionHandler
1323446Smrj  *
1333446Smrj  * PARAMETERS:  Handler         - Pointer to the handler function for the
1343446Smrj  *                                event
1353446Smrj  *
1363446Smrj  * RETURN:      Status
1373446Smrj  *
1383446Smrj  * DESCRIPTION: Saves the pointer to the handler function
1393446Smrj  *
1403446Smrj  ******************************************************************************/
1413446Smrj 
1423446Smrj ACPI_STATUS
AcpiInstallExceptionHandler(ACPI_EXCEPTION_HANDLER Handler)1433446Smrj AcpiInstallExceptionHandler (
1443446Smrj     ACPI_EXCEPTION_HANDLER  Handler)
1453446Smrj {
1463446Smrj     ACPI_STATUS             Status;
1473446Smrj 
1483446Smrj 
1493446Smrj     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
1503446Smrj 
1513446Smrj 
1523446Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
1533446Smrj     if (ACPI_FAILURE (Status))
1543446Smrj     {
1553446Smrj         return_ACPI_STATUS (Status);
1563446Smrj     }
1573446Smrj 
1583446Smrj     /* Don't allow two handlers. */
1593446Smrj 
1603446Smrj     if (AcpiGbl_ExceptionHandler)
1613446Smrj     {
1623446Smrj         Status = AE_ALREADY_EXISTS;
1633446Smrj         goto Cleanup;
1643446Smrj     }
1653446Smrj 
1663446Smrj     /* Install the handler */
1673446Smrj 
1683446Smrj     AcpiGbl_ExceptionHandler = Handler;
1693446Smrj 
1703446Smrj Cleanup:
1713446Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1723446Smrj     return_ACPI_STATUS (Status);
1733446Smrj }
1743446Smrj 
ACPI_EXPORT_SYMBOL(AcpiInstallExceptionHandler)1753446Smrj ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
1763446Smrj 
1773446Smrj 
1783446Smrj /*******************************************************************************
1793446Smrj  *
1803446Smrj  * FUNCTION:    AcpiInstallFixedEventHandler
1813446Smrj  *
1823446Smrj  * PARAMETERS:  Event           - Event type to enable.
1833446Smrj  *              Handler         - Pointer to the handler function for the
1843446Smrj  *                                event
1853446Smrj  *              Context         - Value passed to the handler on each GPE
1863446Smrj  *
1873446Smrj  * RETURN:      Status
1883446Smrj  *
1893446Smrj  * DESCRIPTION: Saves the pointer to the handler function and then enables the
1903446Smrj  *              event.
1913446Smrj  *
1923446Smrj  ******************************************************************************/
1933446Smrj 
1943446Smrj ACPI_STATUS
1953446Smrj AcpiInstallFixedEventHandler (
1963446Smrj     UINT32                  Event,
1973446Smrj     ACPI_EVENT_HANDLER      Handler,
1983446Smrj     void                    *Context)
1993446Smrj {
2003446Smrj     ACPI_STATUS             Status;
2013446Smrj 
2023446Smrj 
2033446Smrj     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
2043446Smrj 
2053446Smrj 
2063446Smrj     /* Parameter validation */
2073446Smrj 
2083446Smrj     if (Event > ACPI_EVENT_MAX)
2093446Smrj     {
2103446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
2113446Smrj     }
2123446Smrj 
2133446Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
2143446Smrj     if (ACPI_FAILURE (Status))
2153446Smrj     {
2163446Smrj         return_ACPI_STATUS (Status);
2173446Smrj     }
2183446Smrj 
2193446Smrj     /* Don't allow two handlers. */
2203446Smrj 
2213446Smrj     if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
2223446Smrj     {
2233446Smrj         Status = AE_ALREADY_EXISTS;
2243446Smrj         goto Cleanup;
2253446Smrj     }
2263446Smrj 
2273446Smrj     /* Install the handler before enabling the event */
2283446Smrj 
2293446Smrj     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
2303446Smrj     AcpiGbl_FixedEventHandlers[Event].Context = Context;
2313446Smrj 
2323446Smrj     Status = AcpiEnableEvent (Event, 0);
2333446Smrj     if (ACPI_FAILURE (Status))
2343446Smrj     {
2353446Smrj         ACPI_WARNING ((AE_INFO, "Could not enable fixed event %X", Event));
2363446Smrj 
2373446Smrj         /* Remove the handler */
2383446Smrj 
2393446Smrj         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
2403446Smrj         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
2413446Smrj     }
2423446Smrj     else
2433446Smrj     {
2443446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
2453446Smrj             "Enabled fixed event %X, Handler=%p\n", Event, Handler));
2463446Smrj     }
2473446Smrj 
2483446Smrj 
2493446Smrj Cleanup:
2503446Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
2513446Smrj     return_ACPI_STATUS (Status);
2523446Smrj }
2533446Smrj 
ACPI_EXPORT_SYMBOL(AcpiInstallFixedEventHandler)2543446Smrj ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
2553446Smrj 
2563446Smrj 
2573446Smrj /*******************************************************************************
2583446Smrj  *
2593446Smrj  * FUNCTION:    AcpiRemoveFixedEventHandler
2603446Smrj  *
2613446Smrj  * PARAMETERS:  Event           - Event type to disable.
2623446Smrj  *              Handler         - Address of the handler
2633446Smrj  *
2643446Smrj  * RETURN:      Status
2653446Smrj  *
2663446Smrj  * DESCRIPTION: Disables the event and unregisters the event handler.
2673446Smrj  *
2683446Smrj  ******************************************************************************/
2693446Smrj 
2703446Smrj ACPI_STATUS
2713446Smrj AcpiRemoveFixedEventHandler (
2723446Smrj     UINT32                  Event,
2733446Smrj     ACPI_EVENT_HANDLER      Handler)
2743446Smrj {
2753446Smrj     ACPI_STATUS             Status = AE_OK;
2763446Smrj 
2773446Smrj 
2783446Smrj     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
2793446Smrj 
2803446Smrj 
2813446Smrj     /* Parameter validation */
2823446Smrj 
2833446Smrj     if (Event > ACPI_EVENT_MAX)
2843446Smrj     {
2853446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
2863446Smrj     }
2873446Smrj 
2883446Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
2893446Smrj     if (ACPI_FAILURE (Status))
2903446Smrj     {
2913446Smrj         return_ACPI_STATUS (Status);
2923446Smrj     }
2933446Smrj 
2943446Smrj     /* Disable the event before removing the handler */
2953446Smrj 
2963446Smrj     Status = AcpiDisableEvent (Event, 0);
2973446Smrj 
2983446Smrj     /* Always Remove the handler */
2993446Smrj 
3003446Smrj     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
3013446Smrj     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
3023446Smrj 
3033446Smrj     if (ACPI_FAILURE (Status))
3043446Smrj     {
3053446Smrj         ACPI_WARNING ((AE_INFO,
3063446Smrj             "Could not write to fixed event enable register %X", Event));
3073446Smrj     }
3083446Smrj     else
3093446Smrj     {
3103446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
3113446Smrj     }
3123446Smrj 
3133446Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
3143446Smrj     return_ACPI_STATUS (Status);
3153446Smrj }
3163446Smrj 
ACPI_EXPORT_SYMBOL(AcpiRemoveFixedEventHandler)3173446Smrj ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
3183446Smrj 
3193446Smrj 
3203446Smrj /*******************************************************************************
3213446Smrj  *
3223446Smrj  * FUNCTION:    AcpiInstallNotifyHandler
3233446Smrj  *
3243446Smrj  * PARAMETERS:  Device          - The device for which notifies will be handled
3253446Smrj  *              HandlerType     - The type of handler:
3263446Smrj  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
3273446Smrj  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
3283446Smrj  *                                  ACPI_ALL_NOTIFY:  both system and device
3293446Smrj  *              Handler         - Address of the handler
3303446Smrj  *              Context         - Value passed to the handler on each GPE
3313446Smrj  *
3323446Smrj  * RETURN:      Status
3333446Smrj  *
3343446Smrj  * DESCRIPTION: Install a handler for notifies on an ACPI device
3353446Smrj  *
3363446Smrj  ******************************************************************************/
3373446Smrj 
3383446Smrj ACPI_STATUS
3393446Smrj AcpiInstallNotifyHandler (
3403446Smrj     ACPI_HANDLE             Device,
3413446Smrj     UINT32                  HandlerType,
3423446Smrj     ACPI_NOTIFY_HANDLER     Handler,
3433446Smrj     void                    *Context)
3443446Smrj {
3453446Smrj     ACPI_OPERAND_OBJECT     *ObjDesc;
3463446Smrj     ACPI_OPERAND_OBJECT     *NotifyObj;
3473446Smrj     ACPI_NAMESPACE_NODE     *Node;
3483446Smrj     ACPI_STATUS             Status;
3493446Smrj 
3503446Smrj 
3513446Smrj     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
3523446Smrj 
3533446Smrj 
3543446Smrj     /* Parameter validation */
3553446Smrj 
3563446Smrj     if ((!Device)  ||
3573446Smrj         (!Handler) ||
3583446Smrj         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
3593446Smrj     {
3603446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
3613446Smrj     }
3623446Smrj 
3633446Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
3643446Smrj     if (ACPI_FAILURE (Status))
3653446Smrj     {
3663446Smrj         return_ACPI_STATUS (Status);
3673446Smrj     }
3683446Smrj 
3693446Smrj     /* Convert and validate the device handle */
3703446Smrj 
3713446Smrj     Node = AcpiNsMapHandleToNode (Device);
3723446Smrj     if (!Node)
3733446Smrj     {
3743446Smrj         Status = AE_BAD_PARAMETER;
3753446Smrj         goto UnlockAndExit;
3763446Smrj     }
3773446Smrj 
3783446Smrj     /*
3793446Smrj      * Root Object:
3803446Smrj      * Registering a notify handler on the root object indicates that the
381*9980SDana.Myers@Sun.COM      * caller wishes to receive notifications for all objects. Note that
3823446Smrj      * only one <external> global handler can be regsitered (per notify type).
3833446Smrj      */
3843446Smrj     if (Device == ACPI_ROOT_OBJECT)
3853446Smrj     {
3863446Smrj         /* Make sure the handler is not already installed */
3873446Smrj 
3883446Smrj         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
3893446Smrj                 AcpiGbl_SystemNotify.Handler)       ||
3903446Smrj             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
3913446Smrj                 AcpiGbl_DeviceNotify.Handler))
3923446Smrj         {
3933446Smrj             Status = AE_ALREADY_EXISTS;
3943446Smrj             goto UnlockAndExit;
3953446Smrj         }
3963446Smrj 
3973446Smrj         if (HandlerType & ACPI_SYSTEM_NOTIFY)
3983446Smrj         {
3993446Smrj             AcpiGbl_SystemNotify.Node    = Node;
4003446Smrj             AcpiGbl_SystemNotify.Handler = Handler;
4013446Smrj             AcpiGbl_SystemNotify.Context = Context;
4023446Smrj         }
4033446Smrj 
4043446Smrj         if (HandlerType & ACPI_DEVICE_NOTIFY)
4053446Smrj         {
4063446Smrj             AcpiGbl_DeviceNotify.Node    = Node;
4073446Smrj             AcpiGbl_DeviceNotify.Handler = Handler;
4083446Smrj             AcpiGbl_DeviceNotify.Context = Context;
4093446Smrj         }
4103446Smrj 
4113446Smrj         /* Global notify handler installed */
4123446Smrj     }
4133446Smrj 
4143446Smrj     /*
4153446Smrj      * All Other Objects:
4163446Smrj      * Caller will only receive notifications specific to the target object.
4173446Smrj      * Note that only certain object types can receive notifications.
4183446Smrj      */
4193446Smrj     else
4203446Smrj     {
4213446Smrj         /* Notifies allowed on this object? */
4223446Smrj 
4233446Smrj         if (!AcpiEvIsNotifyObject (Node))
4243446Smrj         {
4253446Smrj             Status = AE_TYPE;
4263446Smrj             goto UnlockAndExit;
4273446Smrj         }
4283446Smrj 
4293446Smrj         /* Check for an existing internal object */
4303446Smrj 
4313446Smrj         ObjDesc = AcpiNsGetAttachedObject (Node);
4323446Smrj         if (ObjDesc)
4333446Smrj         {
4343446Smrj             /* Object exists - make sure there's no handler */
4353446Smrj 
4363446Smrj             if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
4373446Smrj                     ObjDesc->CommonNotify.SystemNotify)   ||
4383446Smrj                 ((HandlerType & ACPI_DEVICE_NOTIFY) &&
4393446Smrj                     ObjDesc->CommonNotify.DeviceNotify))
4403446Smrj             {
4413446Smrj                 Status = AE_ALREADY_EXISTS;
4423446Smrj                 goto UnlockAndExit;
4433446Smrj             }
4443446Smrj         }
4453446Smrj         else
4463446Smrj         {
4473446Smrj             /* Create a new object */
4483446Smrj 
4493446Smrj             ObjDesc = AcpiUtCreateInternalObject (Node->Type);
4503446Smrj             if (!ObjDesc)
4513446Smrj             {
4523446Smrj                 Status = AE_NO_MEMORY;
4533446Smrj                 goto UnlockAndExit;
4543446Smrj             }
4553446Smrj 
4563446Smrj             /* Attach new object to the Node */
4573446Smrj 
4583446Smrj             Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
4593446Smrj 
4603446Smrj             /* Remove local reference to the object */
4613446Smrj 
4623446Smrj             AcpiUtRemoveReference (ObjDesc);
4633446Smrj             if (ACPI_FAILURE (Status))
4643446Smrj             {
4653446Smrj                 goto UnlockAndExit;
4663446Smrj             }
4673446Smrj         }
4683446Smrj 
4693446Smrj         /* Install the handler */
4703446Smrj 
4713446Smrj         NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
4723446Smrj         if (!NotifyObj)
4733446Smrj         {
4743446Smrj             Status = AE_NO_MEMORY;
4753446Smrj             goto UnlockAndExit;
4763446Smrj         }
4773446Smrj 
4783446Smrj         NotifyObj->Notify.Node    = Node;
4793446Smrj         NotifyObj->Notify.Handler = Handler;
4803446Smrj         NotifyObj->Notify.Context = Context;
4813446Smrj 
4823446Smrj         if (HandlerType & ACPI_SYSTEM_NOTIFY)
4833446Smrj         {
4843446Smrj             ObjDesc->CommonNotify.SystemNotify = NotifyObj;
4853446Smrj         }
4863446Smrj 
4873446Smrj         if (HandlerType & ACPI_DEVICE_NOTIFY)
4883446Smrj         {
4893446Smrj             ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
4903446Smrj         }
4913446Smrj 
4923446Smrj         if (HandlerType == ACPI_ALL_NOTIFY)
4933446Smrj         {
4943446Smrj             /* Extra ref if installed in both */
4953446Smrj 
4963446Smrj             AcpiUtAddReference (NotifyObj);
4973446Smrj         }
4983446Smrj     }
4993446Smrj 
5003446Smrj 
5013446Smrj UnlockAndExit:
5023446Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
5033446Smrj     return_ACPI_STATUS (Status);
5043446Smrj }
5053446Smrj 
ACPI_EXPORT_SYMBOL(AcpiInstallNotifyHandler)5063446Smrj ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
5073446Smrj 
5083446Smrj 
5093446Smrj /*******************************************************************************
5103446Smrj  *
5113446Smrj  * FUNCTION:    AcpiRemoveNotifyHandler
5123446Smrj  *
5133446Smrj  * PARAMETERS:  Device          - The device for which notifies will be handled
5143446Smrj  *              HandlerType     - The type of handler:
5153446Smrj  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
5163446Smrj  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
5173446Smrj  *                                  ACPI_ALL_NOTIFY:  both system and device
5183446Smrj  *              Handler         - Address of the handler
5193446Smrj  *
5203446Smrj  * RETURN:      Status
5213446Smrj  *
5223446Smrj  * DESCRIPTION: Remove a handler for notifies on an ACPI device
5233446Smrj  *
5243446Smrj  ******************************************************************************/
5253446Smrj 
5263446Smrj ACPI_STATUS
5273446Smrj AcpiRemoveNotifyHandler (
5283446Smrj     ACPI_HANDLE             Device,
5293446Smrj     UINT32                  HandlerType,
5303446Smrj     ACPI_NOTIFY_HANDLER     Handler)
5313446Smrj {
5323446Smrj     ACPI_OPERAND_OBJECT     *NotifyObj;
5333446Smrj     ACPI_OPERAND_OBJECT     *ObjDesc;
5343446Smrj     ACPI_NAMESPACE_NODE     *Node;
5353446Smrj     ACPI_STATUS             Status;
5363446Smrj 
5373446Smrj 
5383446Smrj     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
5393446Smrj 
5403446Smrj 
5413446Smrj     /* Parameter validation */
5423446Smrj 
5433446Smrj     if ((!Device)  ||
5443446Smrj         (!Handler) ||
5453446Smrj         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
5463446Smrj     {
5473446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
5483446Smrj     }
5493446Smrj 
5503446Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
5513446Smrj     if (ACPI_FAILURE (Status))
5523446Smrj     {
5533446Smrj         return_ACPI_STATUS (Status);
5543446Smrj     }
5553446Smrj 
5563446Smrj     /* Convert and validate the device handle */
5573446Smrj 
5583446Smrj     Node = AcpiNsMapHandleToNode (Device);
5593446Smrj     if (!Node)
5603446Smrj     {
5613446Smrj         Status = AE_BAD_PARAMETER;
5623446Smrj         goto UnlockAndExit;
5633446Smrj     }
5643446Smrj 
5653446Smrj     /* Root Object */
5663446Smrj 
5673446Smrj     if (Device == ACPI_ROOT_OBJECT)
5683446Smrj     {
5693446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
5703446Smrj             "Removing notify handler for namespace root object\n"));
5713446Smrj 
5723446Smrj         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
5733446Smrj               !AcpiGbl_SystemNotify.Handler)        ||
5743446Smrj             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
5753446Smrj               !AcpiGbl_DeviceNotify.Handler))
5763446Smrj         {
5773446Smrj             Status = AE_NOT_EXIST;
5783446Smrj             goto UnlockAndExit;
5793446Smrj         }
5803446Smrj 
5813446Smrj         if (HandlerType & ACPI_SYSTEM_NOTIFY)
5823446Smrj         {
5833446Smrj             AcpiGbl_SystemNotify.Node    = NULL;
5843446Smrj             AcpiGbl_SystemNotify.Handler = NULL;
5853446Smrj             AcpiGbl_SystemNotify.Context = NULL;
5863446Smrj         }
5873446Smrj 
5883446Smrj         if (HandlerType & ACPI_DEVICE_NOTIFY)
5893446Smrj         {
5903446Smrj             AcpiGbl_DeviceNotify.Node    = NULL;
5913446Smrj             AcpiGbl_DeviceNotify.Handler = NULL;
5923446Smrj             AcpiGbl_DeviceNotify.Context = NULL;
5933446Smrj         }
5943446Smrj     }
5953446Smrj 
5963446Smrj     /* All Other Objects */
5973446Smrj 
5983446Smrj     else
5993446Smrj     {
6003446Smrj         /* Notifies allowed on this object? */
6013446Smrj 
6023446Smrj         if (!AcpiEvIsNotifyObject (Node))
6033446Smrj         {
6043446Smrj             Status = AE_TYPE;
6053446Smrj             goto UnlockAndExit;
6063446Smrj         }
6073446Smrj 
6083446Smrj         /* Check for an existing internal object */
6093446Smrj 
6103446Smrj         ObjDesc = AcpiNsGetAttachedObject (Node);
6113446Smrj         if (!ObjDesc)
6123446Smrj         {
6133446Smrj             Status = AE_NOT_EXIST;
6143446Smrj             goto UnlockAndExit;
6153446Smrj         }
6163446Smrj 
6173446Smrj         /* Object exists - make sure there's an existing handler */
6183446Smrj 
6193446Smrj         if (HandlerType & ACPI_SYSTEM_NOTIFY)
6203446Smrj         {
6213446Smrj             NotifyObj = ObjDesc->CommonNotify.SystemNotify;
6223446Smrj             if (!NotifyObj)
6233446Smrj             {
6243446Smrj                 Status = AE_NOT_EXIST;
6253446Smrj                 goto UnlockAndExit;
6263446Smrj             }
6273446Smrj 
6283446Smrj             if (NotifyObj->Notify.Handler != Handler)
6293446Smrj             {
6303446Smrj                 Status = AE_BAD_PARAMETER;
6313446Smrj                 goto UnlockAndExit;
6323446Smrj             }
6333446Smrj 
6343446Smrj             /* Remove the handler */
6353446Smrj 
6363446Smrj             ObjDesc->CommonNotify.SystemNotify = NULL;
6373446Smrj             AcpiUtRemoveReference (NotifyObj);
6383446Smrj         }
6393446Smrj 
6403446Smrj         if (HandlerType & ACPI_DEVICE_NOTIFY)
6413446Smrj         {
6423446Smrj             NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
6433446Smrj             if (!NotifyObj)
6443446Smrj             {
6453446Smrj                 Status = AE_NOT_EXIST;
6463446Smrj                 goto UnlockAndExit;
6473446Smrj             }
6483446Smrj 
6493446Smrj             if (NotifyObj->Notify.Handler != Handler)
6503446Smrj             {
6513446Smrj                 Status = AE_BAD_PARAMETER;
6523446Smrj                 goto UnlockAndExit;
6533446Smrj             }
6543446Smrj 
6553446Smrj             /* Remove the handler */
6563446Smrj 
6573446Smrj             ObjDesc->CommonNotify.DeviceNotify = NULL;
6583446Smrj             AcpiUtRemoveReference (NotifyObj);
6593446Smrj         }
6603446Smrj     }
6613446Smrj 
6623446Smrj 
6633446Smrj UnlockAndExit:
6643446Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
6653446Smrj     return_ACPI_STATUS (Status);
6663446Smrj }
6673446Smrj 
ACPI_EXPORT_SYMBOL(AcpiRemoveNotifyHandler)6683446Smrj ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
6693446Smrj 
6703446Smrj 
6713446Smrj /*******************************************************************************
6723446Smrj  *
6733446Smrj  * FUNCTION:    AcpiInstallGpeHandler
6743446Smrj  *
6753446Smrj  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
6763446Smrj  *                                defined GPEs)
6773446Smrj  *              GpeNumber       - The GPE number within the GPE block
6783446Smrj  *              Type            - Whether this GPE should be treated as an
6793446Smrj  *                                edge- or level-triggered interrupt.
6803446Smrj  *              Address         - Address of the handler
6813446Smrj  *              Context         - Value passed to the handler on each GPE
6823446Smrj  *
6833446Smrj  * RETURN:      Status
6843446Smrj  *
6853446Smrj  * DESCRIPTION: Install a handler for a General Purpose Event.
6863446Smrj  *
6873446Smrj  ******************************************************************************/
6883446Smrj 
6893446Smrj ACPI_STATUS
6903446Smrj AcpiInstallGpeHandler (
6913446Smrj     ACPI_HANDLE             GpeDevice,
6923446Smrj     UINT32                  GpeNumber,
6933446Smrj     UINT32                  Type,
6943446Smrj     ACPI_EVENT_HANDLER      Address,
6953446Smrj     void                    *Context)
6963446Smrj {
6973446Smrj     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
6983446Smrj     ACPI_HANDLER_INFO       *Handler;
6993446Smrj     ACPI_STATUS             Status;
7003446Smrj     ACPI_CPU_FLAGS          Flags;
7013446Smrj 
7023446Smrj 
7033446Smrj     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
7043446Smrj 
7053446Smrj 
7063446Smrj     /* Parameter validation */
7073446Smrj 
7083446Smrj     if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK))
7093446Smrj     {
7103446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
7113446Smrj     }
7123446Smrj 
7133446Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
7143446Smrj     if (ACPI_FAILURE (Status))
7153446Smrj     {
7163446Smrj         return_ACPI_STATUS (Status);
7173446Smrj     }
7183446Smrj 
7193446Smrj     /* Ensure that we have a valid GPE number */
7203446Smrj 
7213446Smrj     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
7223446Smrj     if (!GpeEventInfo)
7233446Smrj     {
7243446Smrj         Status = AE_BAD_PARAMETER;
7253446Smrj         goto UnlockAndExit;
7263446Smrj     }
7273446Smrj 
7283446Smrj     /* Make sure that there isn't a handler there already */
7293446Smrj 
730*9980SDana.Myers@Sun.COM     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
731*9980SDana.Myers@Sun.COM             ACPI_GPE_DISPATCH_HANDLER)
7323446Smrj     {
7333446Smrj         Status = AE_ALREADY_EXISTS;
7343446Smrj         goto UnlockAndExit;
7353446Smrj     }
7363446Smrj 
7373446Smrj     /* Allocate and init handler object */
7383446Smrj 
7393446Smrj     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_HANDLER_INFO));
7403446Smrj     if (!Handler)
7413446Smrj     {
7423446Smrj         Status = AE_NO_MEMORY;
7433446Smrj         goto UnlockAndExit;
7443446Smrj     }
7453446Smrj 
7463446Smrj     Handler->Address    = Address;
7473446Smrj     Handler->Context    = Context;
7483446Smrj     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
7493446Smrj 
7503446Smrj     /* Disable the GPE before installing the handler */
7513446Smrj 
7523446Smrj     Status = AcpiEvDisableGpe (GpeEventInfo);
7533446Smrj     if (ACPI_FAILURE (Status))
7543446Smrj     {
7553446Smrj         goto UnlockAndExit;
7563446Smrj     }
7573446Smrj 
7583446Smrj     /* Install the handler */
7593446Smrj 
7603446Smrj     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
7613446Smrj     GpeEventInfo->Dispatch.Handler = Handler;
7623446Smrj 
7633446Smrj     /* Setup up dispatch flags to indicate handler (vs. method) */
7643446Smrj 
765*9980SDana.Myers@Sun.COM     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
7663446Smrj     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
7673446Smrj 
7683446Smrj     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
7693446Smrj 
7703446Smrj 
7713446Smrj UnlockAndExit:
7723446Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
7733446Smrj     return_ACPI_STATUS (Status);
7743446Smrj }
7753446Smrj 
ACPI_EXPORT_SYMBOL(AcpiInstallGpeHandler)7763446Smrj ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
7773446Smrj 
7783446Smrj 
7793446Smrj /*******************************************************************************
7803446Smrj  *
7813446Smrj  * FUNCTION:    AcpiRemoveGpeHandler
7823446Smrj  *
7833446Smrj  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
7843446Smrj  *                                defined GPEs)
7853446Smrj  *              GpeNumber       - The event to remove a handler
7863446Smrj  *              Address         - Address of the handler
7873446Smrj  *
7883446Smrj  * RETURN:      Status
7893446Smrj  *
7903446Smrj  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
7913446Smrj  *
7923446Smrj  ******************************************************************************/
7933446Smrj 
7943446Smrj ACPI_STATUS
7953446Smrj AcpiRemoveGpeHandler (
7963446Smrj     ACPI_HANDLE             GpeDevice,
7973446Smrj     UINT32                  GpeNumber,
7983446Smrj     ACPI_EVENT_HANDLER      Address)
7993446Smrj {
8003446Smrj     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
8013446Smrj     ACPI_HANDLER_INFO       *Handler;
8023446Smrj     ACPI_STATUS             Status;
8033446Smrj     ACPI_CPU_FLAGS          Flags;
8043446Smrj 
8053446Smrj 
8063446Smrj     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
8073446Smrj 
8083446Smrj 
8093446Smrj     /* Parameter validation */
8103446Smrj 
8113446Smrj     if (!Address)
8123446Smrj     {
8133446Smrj         return_ACPI_STATUS (AE_BAD_PARAMETER);
8143446Smrj     }
8153446Smrj 
8163446Smrj     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
8173446Smrj     if (ACPI_FAILURE (Status))
8183446Smrj     {
8193446Smrj         return_ACPI_STATUS (Status);
8203446Smrj     }
8213446Smrj 
8223446Smrj     /* Ensure that we have a valid GPE number */
8233446Smrj 
8243446Smrj     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
8253446Smrj     if (!GpeEventInfo)
8263446Smrj     {
8273446Smrj         Status = AE_BAD_PARAMETER;
8283446Smrj         goto UnlockAndExit;
8293446Smrj     }
8303446Smrj 
8313446Smrj     /* Make sure that a handler is indeed installed */
8323446Smrj 
833*9980SDana.Myers@Sun.COM     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
834*9980SDana.Myers@Sun.COM             ACPI_GPE_DISPATCH_HANDLER)
8353446Smrj     {
8363446Smrj         Status = AE_NOT_EXIST;
8373446Smrj         goto UnlockAndExit;
8383446Smrj     }
8393446Smrj 
8403446Smrj     /* Make sure that the installed handler is the same */
8413446Smrj 
8423446Smrj     if (GpeEventInfo->Dispatch.Handler->Address != Address)
8433446Smrj     {
8443446Smrj         Status = AE_BAD_PARAMETER;
8453446Smrj         goto UnlockAndExit;
8463446Smrj     }
8473446Smrj 
8483446Smrj     /* Disable the GPE before removing the handler */
8493446Smrj 
8503446Smrj     Status = AcpiEvDisableGpe (GpeEventInfo);
8513446Smrj     if (ACPI_FAILURE (Status))
8523446Smrj     {
8533446Smrj         goto UnlockAndExit;
8543446Smrj     }
8553446Smrj 
8563446Smrj     /* Remove the handler */
8573446Smrj 
8583446Smrj     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
8593446Smrj     Handler = GpeEventInfo->Dispatch.Handler;
8603446Smrj 
8613446Smrj     /* Restore Method node (if any), set dispatch flags */
8623446Smrj 
8633446Smrj     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
8643446Smrj     GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;  /* Clear bits */
8653446Smrj     if (Handler->MethodNode)
8663446Smrj     {
8673446Smrj         GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD;
8683446Smrj     }
8693446Smrj     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
8703446Smrj 
8713446Smrj     /* Now we can free the handler object */
8723446Smrj 
8733446Smrj     ACPI_FREE (Handler);
8743446Smrj 
8753446Smrj 
8763446Smrj UnlockAndExit:
8773446Smrj     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
8783446Smrj     return_ACPI_STATUS (Status);
8793446Smrj }
8803446Smrj 
ACPI_EXPORT_SYMBOL(AcpiRemoveGpeHandler)8813446Smrj ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
8823446Smrj 
8833446Smrj 
8843446Smrj /*******************************************************************************
8853446Smrj  *
8863446Smrj  * FUNCTION:    AcpiAcquireGlobalLock
8873446Smrj  *
8883446Smrj  * PARAMETERS:  Timeout         - How long the caller is willing to wait
8893446Smrj  *              Handle          - Where the handle to the lock is returned
8903446Smrj  *                                (if acquired)
8913446Smrj  *
8923446Smrj  * RETURN:      Status
8933446Smrj  *
8943446Smrj  * DESCRIPTION: Acquire the ACPI Global Lock
8953446Smrj  *
8967851SDana.Myers@Sun.COM  * Note: Allows callers with the same thread ID to acquire the global lock
8977851SDana.Myers@Sun.COM  * multiple times. In other words, externally, the behavior of the global lock
8987851SDana.Myers@Sun.COM  * is identical to an AML mutex. On the first acquire, a new handle is
8997851SDana.Myers@Sun.COM  * returned. On any subsequent calls to acquire by the same thread, the same
9007851SDana.Myers@Sun.COM  * handle is returned.
9017851SDana.Myers@Sun.COM  *
9023446Smrj  ******************************************************************************/
9033446Smrj 
9043446Smrj ACPI_STATUS
9053446Smrj AcpiAcquireGlobalLock (
9063446Smrj     UINT16                  Timeout,
9073446Smrj     UINT32                  *Handle)
9083446Smrj {
9093446Smrj     ACPI_STATUS             Status;
9103446Smrj 
9113446Smrj 
9123446Smrj     if (!Handle)
9133446Smrj     {
9143446Smrj         return (AE_BAD_PARAMETER);
9153446Smrj     }
9163446Smrj 
9177851SDana.Myers@Sun.COM     /* Must lock interpreter to prevent race conditions */
9183446Smrj 
9197851SDana.Myers@Sun.COM     AcpiExEnterInterpreter ();
9207851SDana.Myers@Sun.COM 
9217851SDana.Myers@Sun.COM     Status = AcpiExAcquireMutexObject (Timeout,
9227851SDana.Myers@Sun.COM                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
9233446Smrj 
9243446Smrj     if (ACPI_SUCCESS (Status))
9253446Smrj     {
9267851SDana.Myers@Sun.COM         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
9277851SDana.Myers@Sun.COM 
9283446Smrj         *Handle = AcpiGbl_GlobalLockHandle;
9293446Smrj     }
9303446Smrj 
9317851SDana.Myers@Sun.COM     AcpiExExitInterpreter ();
9323446Smrj     return (Status);
9333446Smrj }
9343446Smrj 
ACPI_EXPORT_SYMBOL(AcpiAcquireGlobalLock)9353446Smrj ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
9363446Smrj 
9373446Smrj 
9383446Smrj /*******************************************************************************
9393446Smrj  *
9403446Smrj  * FUNCTION:    AcpiReleaseGlobalLock
9413446Smrj  *
9423446Smrj  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
9433446Smrj  *
9443446Smrj  * RETURN:      Status
9453446Smrj  *
9463446Smrj  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
9473446Smrj  *
9483446Smrj  ******************************************************************************/
9493446Smrj 
9503446Smrj ACPI_STATUS
9513446Smrj AcpiReleaseGlobalLock (
9523446Smrj     UINT32                  Handle)
9533446Smrj {
9543446Smrj     ACPI_STATUS             Status;
9553446Smrj 
9563446Smrj 
9577851SDana.Myers@Sun.COM     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
9583446Smrj     {
9593446Smrj         return (AE_NOT_ACQUIRED);
9603446Smrj     }
9613446Smrj 
9627851SDana.Myers@Sun.COM     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
9633446Smrj     return (Status);
9643446Smrj }
9653446Smrj 
9663446Smrj ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
9673446Smrj 
968