evxface.c revision 172314
1193323Sed/****************************************************************************** 2193323Sed * 3193323Sed * Module Name: evxface - External interfaces for ACPI events 4193323Sed * $Revision: 1.165 $ 5193323Sed * 6193323Sed *****************************************************************************/ 7193323Sed 8193323Sed/****************************************************************************** 9193323Sed * 10193323Sed * 1. Copyright Notice 11193323Sed * 12193323Sed * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. 13193323Sed * All rights reserved. 14193323Sed * 15193323Sed * 2. License 16193323Sed * 17193323Sed * 2.1. This is your license from Intel Corp. under its intellectual property 18198090Srdivacky * rights. You may have additional license terms from the party that provided 19198090Srdivacky * you this software, covering your right to use that party's intellectual 20193323Sed * property rights. 21193323Sed * 22193323Sed * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23193323Sed * copy of the source code appearing in this file ("Covered Code") an 24249423Sdim * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25198090Srdivacky * base code distributed originally by Intel ("Original Intel Code") to copy, 26198090Srdivacky * make derivatives, distribute, use and display any portion of the Covered 27193323Sed * Code in any form, with the right to sublicense such rights; and 28193323Sed * 29193323Sed * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30193323Sed * license (with the right to sublicense), under only those claims of Intel 31193323Sed * patents that are infringed by the Original Intel Code, to make, use, sell, 32193323Sed * offer to sell, and import the Covered Code and derivative works thereof 33193323Sed * solely to the minimum extent necessary to exercise the above copyright 34202375Srdivacky * license, and in no event shall the patent license extend to any additions 35198090Srdivacky * to or modifications of the Original Intel Code. No other license or right 36202375Srdivacky * is granted directly or by implication, estoppel or otherwise; 37193323Sed * 38193323Sed * The above copyright and patent license is granted only if the following 39193323Sed * conditions are met: 40193323Sed * 41193323Sed * 3. Conditions 42202375Srdivacky * 43198090Srdivacky * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44202375Srdivacky * Redistribution of source code of any substantial portion of the Covered 45193323Sed * Code or modification with rights to further distribute source must include 46226633Sdim * the above Copyright Notice, the above License, this list of Conditions, 47226633Sdim * and the following Disclaimer and Export Compliance provision. In addition, 48193323Sed * Licensee must cause all Covered Code to which Licensee contributes to 49226633Sdim * contain a file documenting the changes Licensee made to create that Covered 50218893Sdim * Code and the date of any change. Licensee must include in that file the 51239462Sdim * documentation of any changes made by any predecessor Licensee. Licensee 52193323Sed * must include a prominent statement that the modification is derived, 53193323Sed * directly or indirectly, from Original Intel Code. 54221345Sdim * 55202375Srdivacky * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56193323Sed * Redistribution of source code of any substantial portion of the Covered 57193323Sed * Code or modification without rights to further distribute source must 58193323Sed * include the following Disclaimer and Export Compliance provision in the 59193323Sed * documentation and/or other materials provided with distribution. In 60202375Srdivacky * addition, Licensee may not authorize further sublicense of source of any 61234353Sdim * portion of the Covered Code, and must include terms to the effect that the 62193323Sed * license from Licensee to its licensee is limited to the intellectual 63193323Sed * property embodied in the software Licensee provides to its licensee, and 64198090Srdivacky * not to intellectual property embodied in modifications its licensee may 65193323Sed * make. 66193323Sed * 67221345Sdim * 3.3. Redistribution of Executable. Redistribution in executable form of any 68193323Sed * substantial portion of the Covered Code or modification must reproduce the 69193323Sed * above Copyright Notice, and the following Disclaimer and Export Compliance 70193323Sed * provision in the documentation and/or other materials provided with the 71193323Sed * distribution. 72221345Sdim * 73193323Sed * 3.4. Intel retains all right, title, and interest in and to the Original 74221345Sdim * Intel Code. 75221345Sdim * 76221345Sdim * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77221345Sdim * Intel shall be used in advertising or otherwise to promote the sale, use or 78221345Sdim * other dealings in products derived from or relating to the Covered Code 79221345Sdim * without prior written authorization from Intel. 80221345Sdim * 81193323Sed * 4. Disclaimer and Export Compliance 82221345Sdim * 83193323Sed * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84193323Sed * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85221345Sdim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86193323Sed * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87193323Sed * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89221345Sdim * PARTICULAR PURPOSE. 90193323Sed * 91193323Sed * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92221345Sdim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93198090Srdivacky * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94198090Srdivacky * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95198090Srdivacky * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96193323Sed * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97193323Sed * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98193323Sed * LIMITED REMEDY. 99193323Sed * 100193323Sed * 4.3. Licensee shall not export, either directly or indirectly, any of this 101193323Sed * software or system incorporating such software without first obtaining any 102193323Sed * required license or other approval from the U. S. Department of Commerce or 103193323Sed * any other agency or department of the United States Government. In the 104193323Sed * event Licensee exports any such software from the United States or 105193323Sed * re-exports any such software from a foreign destination, Licensee shall 106193323Sed * ensure that the distribution and export/re-export of the software is in 107193323Sed * compliance with all laws, regulations, orders, or other restrictions of the 108193323Sed * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109193323Sed * any of its subsidiaries will export/re-export any technical data, process, 110193323Sed * software, or service, directly or indirectly, to any country for which the 111193323Sed * United States government or any agency thereof requires an export license, 112198090Srdivacky * other governmental approval, or letter of assurance, without first obtaining 113193323Sed * such license, approval or letter. 114193323Sed * 115198090Srdivacky *****************************************************************************/ 116198090Srdivacky 117198090Srdivacky 118239462Sdim#define __EVXFACE_C__ 119239462Sdim 120239462Sdim#include <contrib/dev/acpica/acpi.h> 121193323Sed#include <contrib/dev/acpica/acnamesp.h> 122193323Sed#include <contrib/dev/acpica/acevents.h> 123193323Sed#include <contrib/dev/acpica/acinterp.h> 124193323Sed 125193323Sed#define _COMPONENT ACPI_EVENTS 126193323Sed ACPI_MODULE_NAME ("evxface") 127193323Sed 128193323Sed 129193323Sed/******************************************************************************* 130193323Sed * 131193323Sed * FUNCTION: AcpiInstallExceptionHandler 132193323Sed * 133193323Sed * PARAMETERS: Handler - Pointer to the handler function for the 134193323Sed * event 135239462Sdim * 136239462Sdim * RETURN: Status 137239462Sdim * 138239462Sdim * DESCRIPTION: Saves the pointer to the handler function 139239462Sdim * 140239462Sdim ******************************************************************************/ 141239462Sdim 142239462SdimACPI_STATUS 143226633SdimAcpiInstallExceptionHandler ( 144226633Sdim ACPI_EXCEPTION_HANDLER Handler) 145226633Sdim{ 146226633Sdim ACPI_STATUS Status; 147226633Sdim 148226633Sdim 149218893Sdim ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); 150198090Srdivacky 151218893Sdim 152193323Sed Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 153193323Sed if (ACPI_FAILURE (Status)) 154193323Sed { 155239462Sdim return_ACPI_STATUS (Status); 156239462Sdim } 157239462Sdim 158239462Sdim /* Don't allow two handlers. */ 159239462Sdim 160239462Sdim if (AcpiGbl_ExceptionHandler) 161239462Sdim { 162239462Sdim Status = AE_ALREADY_EXISTS; 163239462Sdim goto Cleanup; 164239462Sdim } 165193323Sed 166198090Srdivacky /* Install the handler */ 167193323Sed 168193323Sed AcpiGbl_ExceptionHandler = Handler; 169193323Sed 170193323SedCleanup: 171193323Sed (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 172193323Sed return_ACPI_STATUS (Status); 173193323Sed} 174193323Sed 175193323SedACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) 176193323Sed 177193323Sed 178193323Sed/******************************************************************************* 179193323Sed * 180193323Sed * FUNCTION: AcpiInstallFixedEventHandler 181193323Sed * 182221345Sdim * PARAMETERS: Event - Event type to enable. 183221345Sdim * Handler - Pointer to the handler function for the 184221345Sdim * event 185221345Sdim * Context - Value passed to the handler on each GPE 186221345Sdim * 187221345Sdim * RETURN: Status 188221345Sdim * 189193323Sed * DESCRIPTION: Saves the pointer to the handler function and then enables the 190193323Sed * event. 191193323Sed * 192193323Sed ******************************************************************************/ 193193323Sed 194193323SedACPI_STATUS 195193323SedAcpiInstallFixedEventHandler ( 196193323Sed UINT32 Event, 197193323Sed ACPI_EVENT_HANDLER Handler, 198193323Sed void *Context) 199198090Srdivacky{ 200193323Sed ACPI_STATUS Status; 201193323Sed 202193323Sed 203193323Sed ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); 204193323Sed 205193323Sed 206193323Sed /* Parameter validation */ 207193323Sed 208193323Sed if (Event > ACPI_EVENT_MAX) 209210299Sed { 210193323Sed return_ACPI_STATUS (AE_BAD_PARAMETER); 211193323Sed } 212210299Sed 213193323Sed Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 214193323Sed if (ACPI_FAILURE (Status)) 215218893Sdim { 216193323Sed return_ACPI_STATUS (Status); 217203954Srdivacky } 218234353Sdim 219193323Sed /* Don't allow two handlers. */ 220193323Sed 221193323Sed if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler) 222193323Sed { 223193323Sed Status = AE_ALREADY_EXISTS; 224193323Sed goto Cleanup; 225193323Sed } 226193323Sed 227193323Sed /* Install the handler before enabling the event */ 228198090Srdivacky 229193323Sed AcpiGbl_FixedEventHandlers[Event].Handler = Handler; 230193323Sed AcpiGbl_FixedEventHandlers[Event].Context = Context; 231193323Sed 232193323Sed Status = AcpiEnableEvent (Event, 0); 233202375Srdivacky if (ACPI_FAILURE (Status)) 234202375Srdivacky { 235202375Srdivacky ACPI_WARNING ((AE_INFO, "Could not enable fixed event %X", Event)); 236202375Srdivacky 237202375Srdivacky /* Remove the handler */ 238202375Srdivacky 239202375Srdivacky AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 240202375Srdivacky AcpiGbl_FixedEventHandlers[Event].Context = NULL; 241193323Sed } 242193323Sed else 243193323Sed { 244198090Srdivacky ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 245193323Sed "Enabled fixed event %X, Handler=%p\n", Event, Handler)); 246193323Sed } 247193323Sed 248193323Sed 249193323SedCleanup: 250193323Sed (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 251234353Sdim return_ACPI_STATUS (Status); 252234353Sdim} 253234353Sdim 254234353SdimACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) 255234353Sdim 256234353Sdim 257234353Sdim/******************************************************************************* 258234353Sdim * 259234353Sdim * FUNCTION: AcpiRemoveFixedEventHandler 260234353Sdim * 261234353Sdim * PARAMETERS: Event - Event type to disable. 262234353Sdim * Handler - Address of the handler 263234353Sdim * 264234353Sdim * RETURN: Status 265234353Sdim * 266234353Sdim * DESCRIPTION: Disables the event and unregisters the event handler. 267234353Sdim * 268234353Sdim ******************************************************************************/ 269234353Sdim 270234353SdimACPI_STATUS 271234353SdimAcpiRemoveFixedEventHandler ( 272234353Sdim UINT32 Event, 273234353Sdim ACPI_EVENT_HANDLER Handler) 274234353Sdim{ 275234353Sdim ACPI_STATUS Status = AE_OK; 276234353Sdim 277234353Sdim 278234353Sdim ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); 279234353Sdim 280234353Sdim 281234353Sdim /* Parameter validation */ 282193323Sed 283193323Sed if (Event > ACPI_EVENT_MAX) 284193323Sed { 285193323Sed return_ACPI_STATUS (AE_BAD_PARAMETER); 286193323Sed } 287193323Sed 288193323Sed Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 289193323Sed if (ACPI_FAILURE (Status)) 290193323Sed { 291193323Sed return_ACPI_STATUS (Status); 292193323Sed } 293193323Sed 294193323Sed /* Disable the event before removing the handler */ 295193323Sed 296193323Sed Status = AcpiDisableEvent (Event, 0); 297198090Srdivacky 298226633Sdim /* Always Remove the handler */ 299226633Sdim 300226633Sdim AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 301226633Sdim AcpiGbl_FixedEventHandlers[Event].Context = NULL; 302226633Sdim 303226633Sdim if (ACPI_FAILURE (Status)) 304198090Srdivacky { 305198090Srdivacky ACPI_WARNING ((AE_INFO, 306198090Srdivacky "Could not write to fixed event enable register %X", Event)); 307198090Srdivacky } 308198090Srdivacky else 309198090Srdivacky { 310198090Srdivacky ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event)); 311198090Srdivacky } 312193323Sed 313193323Sed (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 314193323Sed return_ACPI_STATUS (Status); 315193323Sed} 316193323Sed 317193323SedACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) 318193323Sed 319193323Sed 320193323Sed/******************************************************************************* 321193323Sed * 322193323Sed * FUNCTION: AcpiInstallNotifyHandler 323193323Sed * 324193323Sed * PARAMETERS: Device - The device for which notifies will be handled 325193323Sed * HandlerType - The type of handler: 326226633Sdim * ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f) 327226633Sdim * ACPI_DEVICE_NOTIFY: DriverHandler (80-ff) 328226633Sdim * ACPI_ALL_NOTIFY: both system and device 329226633Sdim * Handler - Address of the handler 330193323Sed * Context - Value passed to the handler on each GPE 331193323Sed * 332198090Srdivacky * RETURN: Status 333198090Srdivacky * 334193323Sed * DESCRIPTION: Install a handler for notifies on an ACPI device 335193323Sed * 336226633Sdim ******************************************************************************/ 337226633Sdim 338226633SdimACPI_STATUS 339226633SdimAcpiInstallNotifyHandler ( 340226633Sdim ACPI_HANDLE Device, 341226633Sdim UINT32 HandlerType, 342226633Sdim ACPI_NOTIFY_HANDLER Handler, 343193323Sed void *Context) 344193323Sed{ 345193323Sed ACPI_OPERAND_OBJECT *ObjDesc; 346193323Sed ACPI_OPERAND_OBJECT *NotifyObj; 347193323Sed ACPI_NAMESPACE_NODE *Node; 348193323Sed ACPI_STATUS Status; 349193323Sed 350193323Sed 351202375Srdivacky ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); 352198090Srdivacky 353202375Srdivacky 354193323Sed /* Parameter validation */ 355193323Sed 356193323Sed if ((!Device) || 357193323Sed (!Handler) || 358193323Sed (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) 359193323Sed { 360202375Srdivacky return_ACPI_STATUS (AE_BAD_PARAMETER); 361198090Srdivacky } 362202375Srdivacky 363193323Sed Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 364198090Srdivacky if (ACPI_FAILURE (Status)) 365218893Sdim { 366218893Sdim return_ACPI_STATUS (Status); 367198090Srdivacky } 368249423Sdim 369249423Sdim /* Convert and validate the device handle */ 370249423Sdim 371249423Sdim Node = AcpiNsMapHandleToNode (Device); 372249423Sdim if (!Node) 373193323Sed { 374198090Srdivacky Status = AE_BAD_PARAMETER; 375198090Srdivacky goto UnlockAndExit; 376193323Sed } 377198090Srdivacky 378198090Srdivacky /* 379193323Sed * Root Object: 380198090Srdivacky * Registering a notify handler on the root object indicates that the 381198090Srdivacky * caller wishes to receive notifications for all objects. Note that 382193323Sed * only one <external> global handler can be regsitered (per notify type). 383193323Sed */ 384193323Sed if (Device == ACPI_ROOT_OBJECT) 385193323Sed { 386193323Sed /* Make sure the handler is not already installed */ 387193323Sed 388193323Sed if (((HandlerType & ACPI_SYSTEM_NOTIFY) && 389193323Sed AcpiGbl_SystemNotify.Handler) || 390193323Sed ((HandlerType & ACPI_DEVICE_NOTIFY) && 391193323Sed AcpiGbl_DeviceNotify.Handler)) 392193323Sed { 393193323Sed Status = AE_ALREADY_EXISTS; 394193323Sed goto UnlockAndExit; 395193323Sed } 396193323Sed 397193323Sed if (HandlerType & ACPI_SYSTEM_NOTIFY) 398193323Sed { 399193323Sed AcpiGbl_SystemNotify.Node = Node; 400218893Sdim AcpiGbl_SystemNotify.Handler = Handler; 401193323Sed AcpiGbl_SystemNotify.Context = Context; 402218893Sdim } 403193323Sed 404218893Sdim if (HandlerType & ACPI_DEVICE_NOTIFY) 405193323Sed { 406193323Sed AcpiGbl_DeviceNotify.Node = Node; 407193323Sed AcpiGbl_DeviceNotify.Handler = Handler; 408249423Sdim AcpiGbl_DeviceNotify.Context = Context; 409249423Sdim } 410249423Sdim 411249423Sdim /* Global notify handler installed */ 412249423Sdim } 413249423Sdim 414249423Sdim /* 415249423Sdim * All Other Objects: 416249423Sdim * Caller will only receive notifications specific to the target object. 417249423Sdim * Note that only certain object types can receive notifications. 418249423Sdim */ 419249423Sdim else 420249423Sdim { 421249423Sdim /* Notifies allowed on this object? */ 422249423Sdim 423193323Sed if (!AcpiEvIsNotifyObject (Node)) 424193323Sed { 425193323Sed Status = AE_TYPE; 426193323Sed goto UnlockAndExit; 427193323Sed } 428193323Sed 429193323Sed /* Check for an existing internal object */ 430193323Sed 431193323Sed ObjDesc = AcpiNsGetAttachedObject (Node); 432193323Sed if (ObjDesc) 433193323Sed { 434193323Sed /* Object exists - make sure there's no handler */ 435193323Sed 436193323Sed if (((HandlerType & ACPI_SYSTEM_NOTIFY) && 437198090Srdivacky ObjDesc->CommonNotify.SystemNotify) || 438198090Srdivacky ((HandlerType & ACPI_DEVICE_NOTIFY) && 439198090Srdivacky ObjDesc->CommonNotify.DeviceNotify)) 440198090Srdivacky { 441198090Srdivacky Status = AE_ALREADY_EXISTS; 442193323Sed goto UnlockAndExit; 443193323Sed } 444193323Sed } 445193323Sed else 446193323Sed { 447193323Sed /* Create a new object */ 448193323Sed 449193323Sed ObjDesc = AcpiUtCreateInternalObject (Node->Type); 450193323Sed if (!ObjDesc) 451193323Sed { 452193323Sed Status = AE_NO_MEMORY; 453193323Sed goto UnlockAndExit; 454218893Sdim } 455193323Sed 456203954Srdivacky /* Attach new object to the Node */ 457203954Srdivacky 458193323Sed Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); 459193323Sed 460218893Sdim /* Remove local reference to the object */ 461203954Srdivacky 462203954Srdivacky AcpiUtRemoveReference (ObjDesc); 463193323Sed if (ACPI_FAILURE (Status)) 464193323Sed { 465193323Sed goto UnlockAndExit; 466193323Sed } 467193323Sed } 468193323Sed 469193323Sed /* Install the handler */ 470193323Sed 471193323Sed NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); 472193323Sed if (!NotifyObj) 473193323Sed { 474193323Sed Status = AE_NO_MEMORY; 475193323Sed goto UnlockAndExit; 476202375Srdivacky } 477198090Srdivacky 478202375Srdivacky NotifyObj->Notify.Node = Node; 479193323Sed NotifyObj->Notify.Handler = Handler; 480239462Sdim NotifyObj->Notify.Context = Context; 481234353Sdim 482234353Sdim if (HandlerType & ACPI_SYSTEM_NOTIFY) 483234353Sdim { 484193323Sed ObjDesc->CommonNotify.SystemNotify = NotifyObj; 485193323Sed } 486193323Sed 487193323Sed if (HandlerType & ACPI_DEVICE_NOTIFY) 488202375Srdivacky { 489198090Srdivacky ObjDesc->CommonNotify.DeviceNotify = NotifyObj; 490202375Srdivacky } 491193323Sed 492239462Sdim if (HandlerType == ACPI_ALL_NOTIFY) 493239462Sdim { 494193323Sed /* Extra ref if installed in both */ 495226633Sdim 496226633Sdim AcpiUtAddReference (NotifyObj); 497193323Sed } 498193323Sed } 499193323Sed 500218893Sdim 501193323SedUnlockAndExit: 502193323Sed (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 503193323Sed return_ACPI_STATUS (Status); 504202375Srdivacky} 505193323Sed 506193323SedACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler) 507193323Sed 508202375Srdivacky 509198090Srdivacky/******************************************************************************* 510198090Srdivacky * 511198090Srdivacky * FUNCTION: AcpiRemoveNotifyHandler 512198090Srdivacky * 513198090Srdivacky * PARAMETERS: Device - The device for which notifies will be handled 514198090Srdivacky * HandlerType - The type of handler: 515193323Sed * ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f) 516198090Srdivacky * ACPI_DEVICE_NOTIFY: DriverHandler (80-ff) 517198090Srdivacky * ACPI_ALL_NOTIFY: both system and device 518193323Sed * Handler - Address of the handler 519221345Sdim * 520221345Sdim * RETURN: Status 521193323Sed * 522234353Sdim * DESCRIPTION: Remove a handler for notifies on an ACPI device 523234353Sdim * 524234353Sdim ******************************************************************************/ 525193323Sed 526193323SedACPI_STATUS 527221345SdimAcpiRemoveNotifyHandler ( 528193323Sed ACPI_HANDLE Device, 529221345Sdim UINT32 HandlerType, 530221345Sdim ACPI_NOTIFY_HANDLER Handler) 531193323Sed{ 532221345Sdim ACPI_OPERAND_OBJECT *NotifyObj; 533221345Sdim ACPI_OPERAND_OBJECT *ObjDesc; 534221345Sdim ACPI_NAMESPACE_NODE *Node; 535193323Sed ACPI_STATUS Status; 536221345Sdim 537221345Sdim 538221345Sdim ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); 539193323Sed 540193323Sed 541221345Sdim /* Parameter validation */ 542221345Sdim 543221345Sdim if ((!Device) || 544221345Sdim (!Handler) || 545221345Sdim (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) 546193323Sed { 547221345Sdim return_ACPI_STATUS (AE_BAD_PARAMETER); 548198090Srdivacky } 549198090Srdivacky 550198090Srdivacky Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 551198090Srdivacky if (ACPI_FAILURE (Status)) 552193323Sed { 553193323Sed return_ACPI_STATUS (Status); 554193323Sed } 555193323Sed 556193323Sed /* Convert and validate the device handle */ 557193323Sed 558193323Sed Node = AcpiNsMapHandleToNode (Device); 559193323Sed if (!Node) 560193323Sed { 561193323Sed Status = AE_BAD_PARAMETER; 562193323Sed goto UnlockAndExit; 563193323Sed } 564193323Sed 565193323Sed /* Root Object */ 566193323Sed 567193323Sed if (Device == ACPI_ROOT_OBJECT) 568193323Sed { 569193323Sed ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 570193323Sed "Removing notify handler for namespace root object\n")); 571198090Srdivacky 572198090Srdivacky if (((HandlerType & ACPI_SYSTEM_NOTIFY) && 573198090Srdivacky !AcpiGbl_SystemNotify.Handler) || 574239462Sdim ((HandlerType & ACPI_DEVICE_NOTIFY) && 575239462Sdim !AcpiGbl_DeviceNotify.Handler)) 576239462Sdim { 577193323Sed Status = AE_NOT_EXIST; 578193323Sed goto UnlockAndExit; 579193323Sed } 580193323Sed 581193323Sed if (HandlerType & ACPI_SYSTEM_NOTIFY) 582193323Sed { 583193323Sed AcpiGbl_SystemNotify.Node = NULL; 584193323Sed AcpiGbl_SystemNotify.Handler = NULL; 585193323Sed AcpiGbl_SystemNotify.Context = NULL; 586193323Sed } 587193323Sed 588193323Sed if (HandlerType & ACPI_DEVICE_NOTIFY) 589193323Sed { 590193323Sed AcpiGbl_DeviceNotify.Node = NULL; 591193323Sed AcpiGbl_DeviceNotify.Handler = NULL; 592193323Sed AcpiGbl_DeviceNotify.Context = NULL; 593193323Sed } 594193323Sed } 595193323Sed 596239462Sdim /* All Other Objects */ 597239462Sdim 598239462Sdim else 599239462Sdim { 600239462Sdim /* Notifies allowed on this object? */ 601239462Sdim 602239462Sdim if (!AcpiEvIsNotifyObject (Node)) 603239462Sdim { 604239462Sdim Status = AE_TYPE; 605239462Sdim goto UnlockAndExit; 606239462Sdim } 607239462Sdim 608239462Sdim /* Check for an existing internal object */ 609239462Sdim 610239462Sdim ObjDesc = AcpiNsGetAttachedObject (Node); 611239462Sdim if (!ObjDesc) 612218893Sdim { 613218893Sdim Status = AE_NOT_EXIST; 614193323Sed goto UnlockAndExit; 615193323Sed } 616198090Srdivacky 617193323Sed /* Object exists - make sure there's an existing handler */ 618193323Sed 619193323Sed if (HandlerType & ACPI_SYSTEM_NOTIFY) 620193323Sed { 621198090Srdivacky NotifyObj = ObjDesc->CommonNotify.SystemNotify; 622193323Sed if (!NotifyObj) 623193323Sed { 624193323Sed Status = AE_NOT_EXIST; 625223017Sdim goto UnlockAndExit; 626223017Sdim } 627223017Sdim 628223017Sdim if (NotifyObj->Notify.Handler != Handler) 629226633Sdim { 630193323Sed Status = AE_BAD_PARAMETER; 631223017Sdim goto UnlockAndExit; 632223017Sdim } 633193323Sed 634193323Sed /* Remove the handler */ 635193323Sed 636193323Sed ObjDesc->CommonNotify.SystemNotify = NULL; 637193323Sed AcpiUtRemoveReference (NotifyObj); 638193323Sed } 639193323Sed 640218893Sdim if (HandlerType & ACPI_DEVICE_NOTIFY) 641218893Sdim { 642193323Sed NotifyObj = ObjDesc->CommonNotify.DeviceNotify; 643193323Sed if (!NotifyObj) 644193323Sed { 645223017Sdim Status = AE_NOT_EXIST; 646193323Sed goto UnlockAndExit; 647193323Sed } 648193323Sed 649218893Sdim if (NotifyObj->Notify.Handler != Handler) 650218893Sdim { 651193323Sed Status = AE_BAD_PARAMETER; 652193323Sed goto UnlockAndExit; 653193323Sed } 654193323Sed 655198090Srdivacky /* Remove the handler */ 656198090Srdivacky 657193323Sed ObjDesc->CommonNotify.DeviceNotify = NULL; 658193323Sed AcpiUtRemoveReference (NotifyObj); 659193323Sed } 660193323Sed } 661193323Sed 662193323Sed 663193323SedUnlockAndExit: 664218893Sdim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 665218893Sdim return_ACPI_STATUS (Status); 666193323Sed} 667193323Sed 668193323SedACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) 669193323Sed 670198090Srdivacky 671193323Sed/******************************************************************************* 672193323Sed * 673193323Sed * FUNCTION: AcpiInstallGpeHandler 674193323Sed * 675193323Sed * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 676193323Sed * defined GPEs) 677193323Sed * GpeNumber - The GPE number within the GPE block 678193323Sed * Type - Whether this GPE should be treated as an 679193323Sed * edge- or level-triggered interrupt. 680193323Sed * Address - Address of the handler 681193323Sed * Context - Value passed to the handler on each GPE 682193323Sed * 683193323Sed * RETURN: Status 684193323Sed * 685193323Sed * DESCRIPTION: Install a handler for a General Purpose Event. 686193323Sed * 687193323Sed ******************************************************************************/ 688193323Sed 689193323SedACPI_STATUS 690193323SedAcpiInstallGpeHandler ( 691193323Sed ACPI_HANDLE GpeDevice, 692198090Srdivacky UINT32 GpeNumber, 693193323Sed UINT32 Type, 694193323Sed ACPI_EVENT_HANDLER Address, 695193323Sed void *Context) 696193323Sed{ 697193323Sed ACPI_GPE_EVENT_INFO *GpeEventInfo; 698193323Sed ACPI_HANDLER_INFO *Handler; 699193323Sed ACPI_STATUS Status; 700193323Sed ACPI_CPU_FLAGS Flags; 701193323Sed 702193323Sed 703193323Sed ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); 704193323Sed 705193323Sed 706193323Sed /* Parameter validation */ 707193323Sed 708198090Srdivacky if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK)) 709193323Sed { 710193323Sed return_ACPI_STATUS (AE_BAD_PARAMETER); 711193323Sed } 712218893Sdim 713218893Sdim Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 714218893Sdim if (ACPI_FAILURE (Status)) 715193323Sed { 716193323Sed return_ACPI_STATUS (Status); 717193323Sed } 718193323Sed 719193323Sed /* Ensure that we have a valid GPE number */ 720193323Sed 721193323Sed GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 722193323Sed if (!GpeEventInfo) 723193323Sed { 724193323Sed Status = AE_BAD_PARAMETER; 725202375Srdivacky goto UnlockAndExit; 726202375Srdivacky } 727202375Srdivacky 728202375Srdivacky /* Make sure that there isn't a handler there already */ 729202375Srdivacky 730202375Srdivacky if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) 731202375Srdivacky { 732202375Srdivacky Status = AE_ALREADY_EXISTS; 733202375Srdivacky goto UnlockAndExit; 734202375Srdivacky } 735202375Srdivacky 736202375Srdivacky /* Allocate and init handler object */ 737202375Srdivacky 738202375Srdivacky Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_HANDLER_INFO)); 739202375Srdivacky if (!Handler) 740193323Sed { 741193323Sed Status = AE_NO_MEMORY; 742193323Sed goto UnlockAndExit; 743193323Sed } 744193323Sed 745193323Sed Handler->Address = Address; 746193323Sed Handler->Context = Context; 747193323Sed Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; 748193323Sed 749193323Sed /* Disable the GPE before installing the handler */ 750193323Sed 751193323Sed Status = AcpiEvDisableGpe (GpeEventInfo); 752193323Sed if (ACPI_FAILURE (Status)) 753193323Sed { 754193323Sed goto UnlockAndExit; 755193323Sed } 756193323Sed 757193323Sed /* Install the handler */ 758193323Sed 759193323Sed Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 760193323Sed GpeEventInfo->Dispatch.Handler = Handler; 761198090Srdivacky 762198090Srdivacky /* Setup up dispatch flags to indicate handler (vs. method) */ 763193323Sed 764218893Sdim GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ 765218893Sdim GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER); 766193323Sed 767193323Sed AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 768193323Sed 769193323Sed 770226633SdimUnlockAndExit: 771193323Sed (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 772243830Sdim return_ACPI_STATUS (Status); 773218893Sdim} 774203954Srdivacky 775193323SedACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) 776193323Sed 777218893Sdim 778234353Sdim/******************************************************************************* 779193323Sed * 780193323Sed * FUNCTION: AcpiRemoveGpeHandler 781193323Sed * 782193323Sed * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 783193323Sed * defined GPEs) 784193323Sed * GpeNumber - The event to remove a handler 785193323Sed * Address - Address of the handler 786218893Sdim * 787234353Sdim * RETURN: Status 788193323Sed * 789193323Sed * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent. 790193323Sed * 791193323Sed ******************************************************************************/ 792198090Srdivacky 793193323SedACPI_STATUS 794193323SedAcpiRemoveGpeHandler ( 795193323Sed ACPI_HANDLE GpeDevice, 796193323Sed UINT32 GpeNumber, 797193323Sed ACPI_EVENT_HANDLER Address) 798193323Sed{ 799193323Sed ACPI_GPE_EVENT_INFO *GpeEventInfo; 800193323Sed ACPI_HANDLER_INFO *Handler; 801193323Sed ACPI_STATUS Status; 802198090Srdivacky ACPI_CPU_FLAGS Flags; 803193323Sed 804193323Sed 805193323Sed ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); 806193323Sed 807193323Sed 808193323Sed /* Parameter validation */ 809193323Sed 810198090Srdivacky if (!Address) 811198090Srdivacky { 812193323Sed return_ACPI_STATUS (AE_BAD_PARAMETER); 813203954Srdivacky } 814234353Sdim 815193323Sed Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 816198090Srdivacky if (ACPI_FAILURE (Status)) 817193323Sed { 818193323Sed return_ACPI_STATUS (Status); 819210299Sed } 820218893Sdim 821234353Sdim /* Ensure that we have a valid GPE number */ 822193323Sed 823193323Sed GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 824193323Sed if (!GpeEventInfo) 825193323Sed { 826210299Sed Status = AE_BAD_PARAMETER; 827218893Sdim goto UnlockAndExit; 828234353Sdim } 829193323Sed 830193323Sed /* Make sure that a handler is indeed installed */ 831193323Sed 832193323Sed if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) 833193323Sed { 834193323Sed Status = AE_NOT_EXIST; 835193323Sed goto UnlockAndExit; 836193323Sed } 837193323Sed 838193323Sed /* Make sure that the installed handler is the same */ 839193323Sed 840198090Srdivacky if (GpeEventInfo->Dispatch.Handler->Address != Address) 841226633Sdim { 842226633Sdim Status = AE_BAD_PARAMETER; 843226633Sdim goto UnlockAndExit; 844226633Sdim } 845198090Srdivacky 846198090Srdivacky /* Disable the GPE before removing the handler */ 847198090Srdivacky 848198090Srdivacky Status = AcpiEvDisableGpe (GpeEventInfo); 849198090Srdivacky if (ACPI_FAILURE (Status)) 850198090Srdivacky { 851198090Srdivacky goto UnlockAndExit; 852198090Srdivacky } 853198090Srdivacky 854198090Srdivacky /* Remove the handler */ 855198090Srdivacky 856198090Srdivacky Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 857198090Srdivacky Handler = GpeEventInfo->Dispatch.Handler; 858198090Srdivacky 859198090Srdivacky /* Restore Method node (if any), set dispatch flags */ 860198090Srdivacky 861198090Srdivacky GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; 862198090Srdivacky GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ 863198090Srdivacky if (Handler->MethodNode) 864198090Srdivacky { 865198090Srdivacky GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD; 866198090Srdivacky } 867198090Srdivacky AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 868193323Sed 869193323Sed /* Now we can free the handler object */ 870193323Sed 871198090Srdivacky ACPI_FREE (Handler); 872193323Sed 873193323Sed 874193323SedUnlockAndExit: 875234353Sdim (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 876234353Sdim return_ACPI_STATUS (Status); 877198090Srdivacky} 878234353Sdim 879234353SdimACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler) 880234353Sdim 881198090Srdivacky 882193323Sed/******************************************************************************* 883193323Sed * 884193323Sed * FUNCTION: AcpiAcquireGlobalLock 885193323Sed * 886193323Sed * PARAMETERS: Timeout - How long the caller is willing to wait 887193323Sed * Handle - Where the handle to the lock is returned 888193323Sed * (if acquired) 889221345Sdim * 890221345Sdim * RETURN: Status 891221345Sdim * 892221345Sdim * DESCRIPTION: Acquire the ACPI Global Lock 893221345Sdim * 894221345Sdim * Note: Allows callers with the same thread ID to acquire the global lock 895221345Sdim * multiple times. In other words, externally, the behavior of the global lock 896221345Sdim * is identical to an AML mutex. On the first acquire, a new handle is 897221345Sdim * returned. On any subsequent calls to acquire by the same thread, the same 898221345Sdim * handle is returned. 899221345Sdim * 900221345Sdim ******************************************************************************/ 901221345Sdim 902221345SdimACPI_STATUS 903221345SdimAcpiAcquireGlobalLock ( 904221345Sdim UINT16 Timeout, 905221345Sdim UINT32 *Handle) 906221345Sdim{ 907221345Sdim ACPI_STATUS Status; 908193323Sed 909193323Sed 910193323Sed if (!Handle) 911193323Sed { 912193323Sed return (AE_BAD_PARAMETER); 913193323Sed } 914193323Sed 915193323Sed /* Must lock interpreter to prevent race conditions */ 916193323Sed 917198090Srdivacky AcpiExEnterInterpreter (); 918193323Sed 919193323Sed Status = AcpiExAcquireMutexObject (Timeout, 920193323Sed AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); 921193323Sed 922193323Sed if (ACPI_SUCCESS (Status)) 923193323Sed { 924193323Sed /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */ 925193323Sed 926193323Sed *Handle = AcpiGbl_GlobalLockHandle; 927193323Sed } 928193323Sed 929193323Sed AcpiExExitInterpreter (); 930193323Sed return (Status); 931193323Sed} 932193323Sed 933193323SedACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock) 934193323Sed 935193323Sed 936193323Sed/******************************************************************************* 937193323Sed * 938193323Sed * FUNCTION: AcpiReleaseGlobalLock 939193323Sed * 940193323Sed * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock 941193323Sed * 942193323Sed * RETURN: Status 943193323Sed * 944193323Sed * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. 945193323Sed * 946193323Sed ******************************************************************************/ 947193323Sed 948193323SedACPI_STATUS 949193323SedAcpiReleaseGlobalLock ( 950193323Sed UINT32 Handle) 951193323Sed{ 952193323Sed ACPI_STATUS Status; 953193323Sed 954193323Sed 955193323Sed if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) 956193323Sed { 957193323Sed return (AE_NOT_ACQUIRED); 958193323Sed } 959193323Sed 960193323Sed Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); 961193323Sed return (Status); 962193323Sed} 963193323Sed 964193323SedACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) 965193323Sed 966193323Sed