1 /******************************************************************************
   2  *
   3  * Module Name: evxface - External interfaces for ACPI events
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #define __EVXFACE_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "acnamesp.h"
  50 #include "acevents.h"
  51 #include "acinterp.h"
  52 
  53 #define _COMPONENT          ACPI_EVENTS
  54         ACPI_MODULE_NAME    ("evxface")
  55 
  56 
  57 /*******************************************************************************
  58  *
  59  * FUNCTION:    AcpiInstallExceptionHandler
  60  *
  61  * PARAMETERS:  Handler         - Pointer to the handler function for the
  62  *                                event
  63  *
  64  * RETURN:      Status
  65  *
  66  * DESCRIPTION: Saves the pointer to the handler function
  67  *
  68  ******************************************************************************/
  69 
  70 ACPI_STATUS
  71 AcpiInstallExceptionHandler (
  72     ACPI_EXCEPTION_HANDLER  Handler)
  73 {
  74     ACPI_STATUS             Status;
  75 
  76 
  77     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
  78 
  79 
  80     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
  81     if (ACPI_FAILURE (Status))
  82     {
  83         return_ACPI_STATUS (Status);
  84     }
  85 
  86     /* Don't allow two handlers. */
  87 
  88     if (AcpiGbl_ExceptionHandler)
  89     {
  90         Status = AE_ALREADY_EXISTS;
  91         goto Cleanup;
  92     }
  93 
  94     /* Install the handler */
  95 
  96     AcpiGbl_ExceptionHandler = Handler;
  97 
  98 Cleanup:
  99     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 100     return_ACPI_STATUS (Status);
 101 }
 102 
 103 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
 104 
 105 
 106 /*******************************************************************************
 107  *
 108  * FUNCTION:    AcpiInstallGlobalEventHandler
 109  *
 110  * PARAMETERS:  Handler         - Pointer to the global event handler function
 111  *              Context         - Value passed to the handler on each event
 112  *
 113  * RETURN:      Status
 114  *
 115  * DESCRIPTION: Saves the pointer to the handler function. The global handler
 116  *              is invoked upon each incoming GPE and Fixed Event. It is
 117  *              invoked at interrupt level at the time of the event dispatch.
 118  *              Can be used to update event counters, etc.
 119  *
 120  ******************************************************************************/
 121 
 122 ACPI_STATUS
 123 AcpiInstallGlobalEventHandler (
 124     ACPI_GBL_EVENT_HANDLER  Handler,
 125     void                    *Context)
 126 {
 127     ACPI_STATUS             Status;
 128 
 129 
 130     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
 131 
 132 
 133     /* Parameter validation */
 134 
 135     if (!Handler)
 136     {
 137         return_ACPI_STATUS (AE_BAD_PARAMETER);
 138     }
 139 
 140     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 141     if (ACPI_FAILURE (Status))
 142     {
 143         return_ACPI_STATUS (Status);
 144     }
 145 
 146     /* Don't allow two handlers. */
 147 
 148     if (AcpiGbl_GlobalEventHandler)
 149     {
 150         Status = AE_ALREADY_EXISTS;
 151         goto Cleanup;
 152     }
 153 
 154     AcpiGbl_GlobalEventHandler = Handler;
 155     AcpiGbl_GlobalEventHandlerContext = Context;
 156 
 157 
 158 Cleanup:
 159     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 160     return_ACPI_STATUS (Status);
 161 }
 162 
 163 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
 164 
 165 
 166 /*******************************************************************************
 167  *
 168  * FUNCTION:    AcpiInstallFixedEventHandler
 169  *
 170  * PARAMETERS:  Event           - Event type to enable.
 171  *              Handler         - Pointer to the handler function for the
 172  *                                event
 173  *              Context         - Value passed to the handler on each GPE
 174  *
 175  * RETURN:      Status
 176  *
 177  * DESCRIPTION: Saves the pointer to the handler function and then enables the
 178  *              event.
 179  *
 180  ******************************************************************************/
 181 
 182 ACPI_STATUS
 183 AcpiInstallFixedEventHandler (
 184     UINT32                  Event,
 185     ACPI_EVENT_HANDLER      Handler,
 186     void                    *Context)
 187 {
 188     ACPI_STATUS             Status;
 189 
 190 
 191     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
 192 
 193 
 194     /* Parameter validation */
 195 
 196     if (Event > ACPI_EVENT_MAX)
 197     {
 198         return_ACPI_STATUS (AE_BAD_PARAMETER);
 199     }
 200 
 201     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 202     if (ACPI_FAILURE (Status))
 203     {
 204         return_ACPI_STATUS (Status);
 205     }
 206 
 207     /* Don't allow two handlers. */
 208 
 209     if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
 210     {
 211         Status = AE_ALREADY_EXISTS;
 212         goto Cleanup;
 213     }
 214 
 215     /* Install the handler before enabling the event */
 216 
 217     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
 218     AcpiGbl_FixedEventHandlers[Event].Context = Context;
 219 
 220     Status = AcpiEnableEvent (Event, 0);
 221     if (ACPI_FAILURE (Status))
 222     {
 223         ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
 224 
 225         /* Remove the handler */
 226 
 227         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
 228         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
 229     }
 230     else
 231     {
 232         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 233             "Enabled fixed event %X, Handler=%p\n", Event, Handler));
 234     }
 235 
 236 
 237 Cleanup:
 238     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 239     return_ACPI_STATUS (Status);
 240 }
 241 
 242 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
 243 
 244 
 245 /*******************************************************************************
 246  *
 247  * FUNCTION:    AcpiRemoveFixedEventHandler
 248  *
 249  * PARAMETERS:  Event           - Event type to disable.
 250  *              Handler         - Address of the handler
 251  *
 252  * RETURN:      Status
 253  *
 254  * DESCRIPTION: Disables the event and unregisters the event handler.
 255  *
 256  ******************************************************************************/
 257 
 258 ACPI_STATUS
 259 AcpiRemoveFixedEventHandler (
 260     UINT32                  Event,
 261     ACPI_EVENT_HANDLER      Handler)
 262 {
 263     ACPI_STATUS             Status = AE_OK;
 264 
 265 
 266     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
 267 
 268 
 269     /* Parameter validation */
 270 
 271     if (Event > ACPI_EVENT_MAX)
 272     {
 273         return_ACPI_STATUS (AE_BAD_PARAMETER);
 274     }
 275 
 276     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 277     if (ACPI_FAILURE (Status))
 278     {
 279         return_ACPI_STATUS (Status);
 280     }
 281 
 282     /* Disable the event before removing the handler */
 283 
 284     Status = AcpiDisableEvent (Event, 0);
 285 
 286     /* Always Remove the handler */
 287 
 288     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
 289     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
 290 
 291     if (ACPI_FAILURE (Status))
 292     {
 293         ACPI_WARNING ((AE_INFO,
 294             "Could not write to fixed event enable register 0x%X", Event));
 295     }
 296     else
 297     {
 298         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
 299     }
 300 
 301     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 302     return_ACPI_STATUS (Status);
 303 }
 304 
 305 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
 306 
 307 
 308 /*******************************************************************************
 309  *
 310  * FUNCTION:    AcpiInstallNotifyHandler
 311  *
 312  * PARAMETERS:  Device          - The device for which notifies will be handled
 313  *              HandlerType     - The type of handler:
 314  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
 315  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
 316  *                                  ACPI_ALL_NOTIFY:  both system and device
 317  *              Handler         - Address of the handler
 318  *              Context         - Value passed to the handler on each GPE
 319  *
 320  * RETURN:      Status
 321  *
 322  * DESCRIPTION: Install a handler for notifies on an ACPI device
 323  *
 324  ******************************************************************************/
 325 
 326 ACPI_STATUS
 327 AcpiInstallNotifyHandler (
 328     ACPI_HANDLE             Device,
 329     UINT32                  HandlerType,
 330     ACPI_NOTIFY_HANDLER     Handler,
 331     void                    *Context)
 332 {
 333     ACPI_OPERAND_OBJECT     *ObjDesc;
 334     ACPI_OPERAND_OBJECT     *NotifyObj;
 335     ACPI_NAMESPACE_NODE     *Node;
 336     ACPI_STATUS             Status;
 337 
 338 
 339     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
 340 
 341 
 342     /* Parameter validation */
 343 
 344     if ((!Device)  ||
 345         (!Handler) ||
 346         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
 347     {
 348         return_ACPI_STATUS (AE_BAD_PARAMETER);
 349     }
 350 
 351     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 352     if (ACPI_FAILURE (Status))
 353     {
 354         return_ACPI_STATUS (Status);
 355     }
 356 
 357     /* Convert and validate the device handle */
 358 
 359     Node = AcpiNsValidateHandle (Device);
 360     if (!Node)
 361     {
 362         Status = AE_BAD_PARAMETER;
 363         goto UnlockAndExit;
 364     }
 365 
 366     /*
 367      * Root Object:
 368      * Registering a notify handler on the root object indicates that the
 369      * caller wishes to receive notifications for all objects. Note that
 370      * only one <external> global handler can be regsitered (per notify type).
 371      */
 372     if (Device == ACPI_ROOT_OBJECT)
 373     {
 374         /* Make sure the handler is not already installed */
 375 
 376         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
 377                 AcpiGbl_SystemNotify.Handler)       ||
 378             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
 379                 AcpiGbl_DeviceNotify.Handler))
 380         {
 381             Status = AE_ALREADY_EXISTS;
 382             goto UnlockAndExit;
 383         }
 384 
 385         if (HandlerType & ACPI_SYSTEM_NOTIFY)
 386         {
 387             AcpiGbl_SystemNotify.Node    = Node;
 388             AcpiGbl_SystemNotify.Handler = Handler;
 389             AcpiGbl_SystemNotify.Context = Context;
 390         }
 391 
 392         if (HandlerType & ACPI_DEVICE_NOTIFY)
 393         {
 394             AcpiGbl_DeviceNotify.Node    = Node;
 395             AcpiGbl_DeviceNotify.Handler = Handler;
 396             AcpiGbl_DeviceNotify.Context = Context;
 397         }
 398 
 399         /* Global notify handler installed */
 400     }
 401 
 402     /*
 403      * All Other Objects:
 404      * Caller will only receive notifications specific to the target object.
 405      * Note that only certain object types can receive notifications.
 406      */
 407     else
 408     {
 409         /* Notifies allowed on this object? */
 410 
 411         if (!AcpiEvIsNotifyObject (Node))
 412         {
 413             Status = AE_TYPE;
 414             goto UnlockAndExit;
 415         }
 416 
 417         /* Check for an existing internal object */
 418 
 419         ObjDesc = AcpiNsGetAttachedObject (Node);
 420         if (ObjDesc)
 421         {
 422             /* Object exists - make sure there's no handler */
 423 
 424             if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
 425                     ObjDesc->CommonNotify.SystemNotify)   ||
 426                 ((HandlerType & ACPI_DEVICE_NOTIFY) &&
 427                     ObjDesc->CommonNotify.DeviceNotify))
 428             {
 429                 Status = AE_ALREADY_EXISTS;
 430                 goto UnlockAndExit;
 431             }
 432         }
 433         else
 434         {
 435             /* Create a new object */
 436 
 437             ObjDesc = AcpiUtCreateInternalObject (Node->Type);
 438             if (!ObjDesc)
 439             {
 440                 Status = AE_NO_MEMORY;
 441                 goto UnlockAndExit;
 442             }
 443 
 444             /* Attach new object to the Node */
 445 
 446             Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
 447 
 448             /* Remove local reference to the object */
 449 
 450             AcpiUtRemoveReference (ObjDesc);
 451             if (ACPI_FAILURE (Status))
 452             {
 453                 goto UnlockAndExit;
 454             }
 455         }
 456 
 457         /* Install the handler */
 458 
 459         NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
 460         if (!NotifyObj)
 461         {
 462             Status = AE_NO_MEMORY;
 463             goto UnlockAndExit;
 464         }
 465 
 466         NotifyObj->Notify.Node    = Node;
 467         NotifyObj->Notify.Handler = Handler;
 468         NotifyObj->Notify.Context = Context;
 469 
 470         if (HandlerType & ACPI_SYSTEM_NOTIFY)
 471         {
 472             ObjDesc->CommonNotify.SystemNotify = NotifyObj;
 473         }
 474 
 475         if (HandlerType & ACPI_DEVICE_NOTIFY)
 476         {
 477             ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
 478         }
 479 
 480         if (HandlerType == ACPI_ALL_NOTIFY)
 481         {
 482             /* Extra ref if installed in both */
 483 
 484             AcpiUtAddReference (NotifyObj);
 485         }
 486     }
 487 
 488 
 489 UnlockAndExit:
 490     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 491     return_ACPI_STATUS (Status);
 492 }
 493 
 494 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
 495 
 496 
 497 /*******************************************************************************
 498  *
 499  * FUNCTION:    AcpiRemoveNotifyHandler
 500  *
 501  * PARAMETERS:  Device          - The device for which notifies will be handled
 502  *              HandlerType     - The type of handler:
 503  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
 504  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
 505  *                                  ACPI_ALL_NOTIFY:  both system and device
 506  *              Handler         - Address of the handler
 507  *
 508  * RETURN:      Status
 509  *
 510  * DESCRIPTION: Remove a handler for notifies on an ACPI device
 511  *
 512  ******************************************************************************/
 513 
 514 ACPI_STATUS
 515 AcpiRemoveNotifyHandler (
 516     ACPI_HANDLE             Device,
 517     UINT32                  HandlerType,
 518     ACPI_NOTIFY_HANDLER     Handler)
 519 {
 520     ACPI_OPERAND_OBJECT     *NotifyObj;
 521     ACPI_OPERAND_OBJECT     *ObjDesc;
 522     ACPI_NAMESPACE_NODE     *Node;
 523     ACPI_STATUS             Status;
 524 
 525 
 526     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
 527 
 528 
 529     /* Parameter validation */
 530 
 531     if ((!Device)  ||
 532         (!Handler) ||
 533         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
 534     {
 535         return_ACPI_STATUS (AE_BAD_PARAMETER);
 536     }
 537 
 538     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 539     if (ACPI_FAILURE (Status))
 540     {
 541         return_ACPI_STATUS (Status);
 542     }
 543 
 544     /* Convert and validate the device handle */
 545 
 546     Node = AcpiNsValidateHandle (Device);
 547     if (!Node)
 548     {
 549         Status = AE_BAD_PARAMETER;
 550         goto UnlockAndExit;
 551     }
 552 
 553     /* Root Object */
 554 
 555     if (Device == ACPI_ROOT_OBJECT)
 556     {
 557         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 558             "Removing notify handler for namespace root object\n"));
 559 
 560         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
 561               !AcpiGbl_SystemNotify.Handler)        ||
 562             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
 563               !AcpiGbl_DeviceNotify.Handler))
 564         {
 565             Status = AE_NOT_EXIST;
 566             goto UnlockAndExit;
 567         }
 568 
 569         if (HandlerType & ACPI_SYSTEM_NOTIFY)
 570         {
 571             AcpiGbl_SystemNotify.Node    = NULL;
 572             AcpiGbl_SystemNotify.Handler = NULL;
 573             AcpiGbl_SystemNotify.Context = NULL;
 574         }
 575 
 576         if (HandlerType & ACPI_DEVICE_NOTIFY)
 577         {
 578             AcpiGbl_DeviceNotify.Node    = NULL;
 579             AcpiGbl_DeviceNotify.Handler = NULL;
 580             AcpiGbl_DeviceNotify.Context = NULL;
 581         }
 582     }
 583 
 584     /* All Other Objects */
 585 
 586     else
 587     {
 588         /* Notifies allowed on this object? */
 589 
 590         if (!AcpiEvIsNotifyObject (Node))
 591         {
 592             Status = AE_TYPE;
 593             goto UnlockAndExit;
 594         }
 595 
 596         /* Check for an existing internal object */
 597 
 598         ObjDesc = AcpiNsGetAttachedObject (Node);
 599         if (!ObjDesc)
 600         {
 601             Status = AE_NOT_EXIST;
 602             goto UnlockAndExit;
 603         }
 604 
 605         /* Object exists - make sure there's an existing handler */
 606 
 607         if (HandlerType & ACPI_SYSTEM_NOTIFY)
 608         {
 609             NotifyObj = ObjDesc->CommonNotify.SystemNotify;
 610             if (!NotifyObj)
 611             {
 612                 Status = AE_NOT_EXIST;
 613                 goto UnlockAndExit;
 614             }
 615 
 616             if (NotifyObj->Notify.Handler != Handler)
 617             {
 618                 Status = AE_BAD_PARAMETER;
 619                 goto UnlockAndExit;
 620             }
 621 
 622             /* Remove the handler */
 623 
 624             ObjDesc->CommonNotify.SystemNotify = NULL;
 625             AcpiUtRemoveReference (NotifyObj);
 626         }
 627 
 628         if (HandlerType & ACPI_DEVICE_NOTIFY)
 629         {
 630             NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
 631             if (!NotifyObj)
 632             {
 633                 Status = AE_NOT_EXIST;
 634                 goto UnlockAndExit;
 635             }
 636 
 637             if (NotifyObj->Notify.Handler != Handler)
 638             {
 639                 Status = AE_BAD_PARAMETER;
 640                 goto UnlockAndExit;
 641             }
 642 
 643             /* Remove the handler */
 644 
 645             ObjDesc->CommonNotify.DeviceNotify = NULL;
 646             AcpiUtRemoveReference (NotifyObj);
 647         }
 648     }
 649 
 650 
 651 UnlockAndExit:
 652     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 653     return_ACPI_STATUS (Status);
 654 }
 655 
 656 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
 657 
 658 
 659 /*******************************************************************************
 660  *
 661  * FUNCTION:    AcpiInstallGpeHandler
 662  *
 663  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
 664  *                                defined GPEs)
 665  *              GpeNumber       - The GPE number within the GPE block
 666  *              Type            - Whether this GPE should be treated as an
 667  *                                edge- or level-triggered interrupt.
 668  *              Address         - Address of the handler
 669  *              Context         - Value passed to the handler on each GPE
 670  *
 671  * RETURN:      Status
 672  *
 673  * DESCRIPTION: Install a handler for a General Purpose Event.
 674  *
 675  ******************************************************************************/
 676 
 677 ACPI_STATUS
 678 AcpiInstallGpeHandler (
 679     ACPI_HANDLE             GpeDevice,
 680     UINT32                  GpeNumber,
 681     UINT32                  Type,
 682     ACPI_GPE_HANDLER        Address,
 683     void                    *Context)
 684 {
 685     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
 686     ACPI_GPE_HANDLER_INFO   *Handler;
 687     ACPI_STATUS             Status;
 688     ACPI_CPU_FLAGS          Flags;
 689 
 690 
 691     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
 692 
 693 
 694     /* Parameter validation */
 695 
 696     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
 697     {
 698         return_ACPI_STATUS (AE_BAD_PARAMETER);
 699     }
 700 
 701     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 702     if (ACPI_FAILURE (Status))
 703     {
 704         return_ACPI_STATUS (Status);
 705     }
 706 
 707     /* Allocate and init handler object (before lock) */
 708 
 709     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
 710     if (!Handler)
 711     {
 712         Status = AE_NO_MEMORY;
 713         goto UnlockAndExit;
 714     }
 715 
 716     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
 717 
 718     /* Ensure that we have a valid GPE number */
 719 
 720     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
 721     if (!GpeEventInfo)
 722     {
 723         Status = AE_BAD_PARAMETER;
 724         goto FreeAndExit;
 725     }
 726 
 727     /* Make sure that there isn't a handler there already */
 728 
 729     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
 730             ACPI_GPE_DISPATCH_HANDLER)
 731     {
 732         Status = AE_ALREADY_EXISTS;
 733         goto FreeAndExit;
 734     }
 735 
 736     Handler->Address = Address;
 737     Handler->Context = Context;
 738     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
 739     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
 740         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
 741 
 742     /*
 743      * If the GPE is associated with a method, it may have been enabled
 744      * automatically during initialization, in which case it has to be
 745      * disabled now to avoid spurious execution of the handler.
 746      */
 747     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
 748          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
 749         GpeEventInfo->RuntimeCount)
 750     {
 751         Handler->OriginallyEnabled = TRUE;
 752         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
 753 
 754         /* Sanity check of original type against new type */
 755 
 756         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
 757         {
 758             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
 759         }
 760     }
 761 
 762     /* Install the handler */
 763 
 764     GpeEventInfo->Dispatch.Handler = Handler;
 765 
 766     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
 767 
 768     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
 769     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
 770 
 771     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 772 
 773 
 774 UnlockAndExit:
 775     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 776     return_ACPI_STATUS (Status);
 777 
 778 FreeAndExit:
 779     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 780     ACPI_FREE (Handler);
 781     goto UnlockAndExit;
 782 }
 783 
 784 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
 785 
 786 
 787 /*******************************************************************************
 788  *
 789  * FUNCTION:    AcpiRemoveGpeHandler
 790  *
 791  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
 792  *                                defined GPEs)
 793  *              GpeNumber       - The event to remove a handler
 794  *              Address         - Address of the handler
 795  *
 796  * RETURN:      Status
 797  *
 798  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
 799  *
 800  ******************************************************************************/
 801 
 802 ACPI_STATUS
 803 AcpiRemoveGpeHandler (
 804     ACPI_HANDLE             GpeDevice,
 805     UINT32                  GpeNumber,
 806     ACPI_GPE_HANDLER        Address)
 807 {
 808     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
 809     ACPI_GPE_HANDLER_INFO   *Handler;
 810     ACPI_STATUS             Status;
 811     ACPI_CPU_FLAGS          Flags;
 812 
 813 
 814     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
 815 
 816 
 817     /* Parameter validation */
 818 
 819     if (!Address)
 820     {
 821         return_ACPI_STATUS (AE_BAD_PARAMETER);
 822     }
 823 
 824     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 825     if (ACPI_FAILURE (Status))
 826     {
 827         return_ACPI_STATUS (Status);
 828     }
 829 
 830     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
 831 
 832     /* Ensure that we have a valid GPE number */
 833 
 834     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
 835     if (!GpeEventInfo)
 836     {
 837         Status = AE_BAD_PARAMETER;
 838         goto UnlockAndExit;
 839     }
 840 
 841     /* Make sure that a handler is indeed installed */
 842 
 843     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
 844             ACPI_GPE_DISPATCH_HANDLER)
 845     {
 846         Status = AE_NOT_EXIST;
 847         goto UnlockAndExit;
 848     }
 849 
 850     /* Make sure that the installed handler is the same */
 851 
 852     if (GpeEventInfo->Dispatch.Handler->Address != Address)
 853     {
 854         Status = AE_BAD_PARAMETER;
 855         goto UnlockAndExit;
 856     }
 857 
 858     /* Remove the handler */
 859 
 860     Handler = GpeEventInfo->Dispatch.Handler;
 861 
 862     /* Restore Method node (if any), set dispatch flags */
 863 
 864     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
 865     GpeEventInfo->Flags &=
 866         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
 867     GpeEventInfo->Flags |= Handler->OriginalFlags;
 868 
 869     /*
 870      * If the GPE was previously associated with a method and it was
 871      * enabled, it should be enabled at this point to restore the
 872      * post-initialization configuration.
 873      */
 874     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
 875         Handler->OriginallyEnabled)
 876     {
 877         (void) AcpiEvAddGpeReference (GpeEventInfo);
 878     }
 879 
 880     /* Now we can free the handler object */
 881 
 882     ACPI_FREE (Handler);
 883 
 884 
 885 UnlockAndExit:
 886     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 887     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 888     return_ACPI_STATUS (Status);
 889 }
 890 
 891 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
 892 
 893 
 894 /*******************************************************************************
 895  *
 896  * FUNCTION:    AcpiAcquireGlobalLock
 897  *
 898  * PARAMETERS:  Timeout         - How long the caller is willing to wait
 899  *              Handle          - Where the handle to the lock is returned
 900  *                                (if acquired)
 901  *
 902  * RETURN:      Status
 903  *
 904  * DESCRIPTION: Acquire the ACPI Global Lock
 905  *
 906  * Note: Allows callers with the same thread ID to acquire the global lock
 907  * multiple times. In other words, externally, the behavior of the global lock
 908  * is identical to an AML mutex. On the first acquire, a new handle is
 909  * returned. On any subsequent calls to acquire by the same thread, the same
 910  * handle is returned.
 911  *
 912  ******************************************************************************/
 913 
 914 ACPI_STATUS
 915 AcpiAcquireGlobalLock (
 916     UINT16                  Timeout,
 917     UINT32                  *Handle)
 918 {
 919     ACPI_STATUS             Status;
 920 
 921 
 922     if (!Handle)
 923     {
 924         return (AE_BAD_PARAMETER);
 925     }
 926 
 927     /* Must lock interpreter to prevent race conditions */
 928 
 929     AcpiExEnterInterpreter ();
 930 
 931     Status = AcpiExAcquireMutexObject (Timeout,
 932                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
 933 
 934     if (ACPI_SUCCESS (Status))
 935     {
 936         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
 937 
 938         *Handle = AcpiGbl_GlobalLockHandle;
 939     }
 940 
 941     AcpiExExitInterpreter ();
 942     return (Status);
 943 }
 944 
 945 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
 946 
 947 
 948 /*******************************************************************************
 949  *
 950  * FUNCTION:    AcpiReleaseGlobalLock
 951  *
 952  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
 953  *
 954  * RETURN:      Status
 955  *
 956  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
 957  *
 958  ******************************************************************************/
 959 
 960 ACPI_STATUS
 961 AcpiReleaseGlobalLock (
 962     UINT32                  Handle)
 963 {
 964     ACPI_STATUS             Status;
 965 
 966 
 967     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
 968     {
 969         return (AE_NOT_ACQUIRED);
 970     }
 971 
 972     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
 973     return (Status);
 974 }
 975 
 976 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
 977