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