1 /******************************************************************************
   2  *
   3  * Module Name: evxface - External interfaces for ACPI events
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 #define EXPORT_ACPI_INTERFACES
  47 
  48 #include "acpi.h"
  49 #include "accommon.h"
  50 #include "acnamesp.h"
  51 #include "acevents.h"
  52 #include "acinterp.h"
  53 
  54 #define _COMPONENT          ACPI_EVENTS
  55         ACPI_MODULE_NAME    ("evxface")
  56 
  57 
  58 /*******************************************************************************
  59  *
  60  * FUNCTION:    AcpiInstallNotifyHandler
  61  *
  62  * PARAMETERS:  Device          - The device for which notifies will be handled
  63  *              HandlerType     - The type of handler:
  64  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
  65  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
  66  *                                  ACPI_ALL_NOTIFY:    Both System and Device
  67  *              Handler         - Address of the handler
  68  *              Context         - Value passed to the handler on each GPE
  69  *
  70  * RETURN:      Status
  71  *
  72  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
  73  *              ThermalZone, or Processor object.
  74  *
  75  * NOTES:       The Root namespace object may have only one handler for each
  76  *              type of notify (System/Device). Device/Thermal/Processor objects
  77  *              may have one device notify handler, and multiple system notify
  78  *              handlers.
  79  *
  80  ******************************************************************************/
  81 
  82 ACPI_STATUS
  83 AcpiInstallNotifyHandler (
  84     ACPI_HANDLE             Device,
  85     UINT32                  HandlerType,
  86     ACPI_NOTIFY_HANDLER     Handler,
  87     void                    *Context)
  88 {
  89     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
  90     ACPI_OPERAND_OBJECT     *ObjDesc;
  91     ACPI_OPERAND_OBJECT     *HandlerObj;
  92     ACPI_STATUS             Status;
  93     UINT32                  i;
  94 
  95 
  96     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
  97 
  98 
  99     /* Parameter validation */
 100 
 101     if ((!Device) || (!Handler) || (!HandlerType) ||
 102         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
 103     {
 104         return_ACPI_STATUS (AE_BAD_PARAMETER);
 105     }
 106 
 107     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 108     if (ACPI_FAILURE (Status))
 109     {
 110         return_ACPI_STATUS (Status);
 111     }
 112 
 113     /*
 114      * Root Object:
 115      * Registering a notify handler on the root object indicates that the
 116      * caller wishes to receive notifications for all objects. Note that
 117      * only one global handler can be registered per notify type.
 118      * Ensure that a handler is not already installed.
 119      */
 120     if (Device == ACPI_ROOT_OBJECT)
 121     {
 122         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
 123         {
 124             if (HandlerType & (i+1))
 125             {
 126                 if (AcpiGbl_GlobalNotify[i].Handler)
 127                 {
 128                     Status = AE_ALREADY_EXISTS;
 129                     goto UnlockAndExit;
 130                 }
 131 
 132                 AcpiGbl_GlobalNotify[i].Handler = Handler;
 133                 AcpiGbl_GlobalNotify[i].Context = Context;
 134             }
 135         }
 136 
 137         goto UnlockAndExit; /* Global notify handler installed, all done */
 138     }
 139 
 140     /*
 141      * All Other Objects:
 142      * Caller will only receive notifications specific to the target
 143      * object. Note that only certain object types are allowed to
 144      * receive notifications.
 145      */
 146 
 147     /* Are Notifies allowed on this object? */
 148 
 149     if (!AcpiEvIsNotifyObject (Node))
 150     {
 151         Status = AE_TYPE;
 152         goto UnlockAndExit;
 153     }
 154 
 155     /* Check for an existing internal object, might not exist */
 156 
 157     ObjDesc = AcpiNsGetAttachedObject (Node);
 158     if (!ObjDesc)
 159     {
 160         /* Create a new object */
 161 
 162         ObjDesc = AcpiUtCreateInternalObject (Node->Type);
 163         if (!ObjDesc)
 164         {
 165             Status = AE_NO_MEMORY;
 166             goto UnlockAndExit;
 167         }
 168 
 169         /* Attach new object to the Node, remove local reference */
 170 
 171         Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
 172         AcpiUtRemoveReference (ObjDesc);
 173         if (ACPI_FAILURE (Status))
 174         {
 175             goto UnlockAndExit;
 176         }
 177     }
 178 
 179     /* Ensure that the handler is not already installed in the lists */
 180 
 181     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
 182     {
 183         if (HandlerType & (i+1))
 184         {
 185             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
 186             while (HandlerObj)
 187             {
 188                 if (HandlerObj->Notify.Handler == Handler)
 189                 {
 190                     Status = AE_ALREADY_EXISTS;
 191                     goto UnlockAndExit;
 192                 }
 193 
 194                 HandlerObj = HandlerObj->Notify.Next[i];
 195             }
 196         }
 197     }
 198 
 199     /* Create and populate a new notify handler object */
 200 
 201     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
 202     if (!HandlerObj)
 203     {
 204         Status = AE_NO_MEMORY;
 205         goto UnlockAndExit;
 206     }
 207 
 208     HandlerObj->Notify.Node = Node;
 209     HandlerObj->Notify.HandlerType = HandlerType;
 210     HandlerObj->Notify.Handler = Handler;
 211     HandlerObj->Notify.Context = Context;
 212 
 213     /* Install the handler at the list head(s) */
 214 
 215     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
 216     {
 217         if (HandlerType & (i+1))
 218         {
 219             HandlerObj->Notify.Next[i] =
 220                 ObjDesc->CommonNotify.NotifyList[i];
 221 
 222             ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
 223         }
 224     }
 225 
 226     /* Add an extra reference if handler was installed in both lists */
 227 
 228     if (HandlerType == ACPI_ALL_NOTIFY)
 229     {
 230         AcpiUtAddReference (HandlerObj);
 231     }
 232 
 233 
 234 UnlockAndExit:
 235     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 236     return_ACPI_STATUS (Status);
 237 }
 238 
 239 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
 240 
 241 
 242 /*******************************************************************************
 243  *
 244  * FUNCTION:    AcpiRemoveNotifyHandler
 245  *
 246  * PARAMETERS:  Device          - The device for which the handler is installed
 247  *              HandlerType     - The type of handler:
 248  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
 249  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
 250  *                                  ACPI_ALL_NOTIFY:    Both System and Device
 251  *              Handler         - Address of the handler
 252  *
 253  * RETURN:      Status
 254  *
 255  * DESCRIPTION: Remove a handler for notifies on an ACPI device
 256  *
 257  ******************************************************************************/
 258 
 259 ACPI_STATUS
 260 AcpiRemoveNotifyHandler (
 261     ACPI_HANDLE             Device,
 262     UINT32                  HandlerType,
 263     ACPI_NOTIFY_HANDLER     Handler)
 264 {
 265     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
 266     ACPI_OPERAND_OBJECT     *ObjDesc;
 267     ACPI_OPERAND_OBJECT     *HandlerObj;
 268     ACPI_OPERAND_OBJECT     *PreviousHandlerObj;
 269     ACPI_STATUS             Status;
 270     UINT32                  i;
 271 
 272 
 273     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
 274 
 275 
 276     /* Parameter validation */
 277 
 278     if ((!Device) || (!Handler) || (!HandlerType) ||
 279         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
 280     {
 281         return_ACPI_STATUS (AE_BAD_PARAMETER);
 282     }
 283 
 284     /* Make sure all deferred notify tasks are completed */
 285 
 286     AcpiOsWaitEventsComplete ();
 287 
 288     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 289     if (ACPI_FAILURE (Status))
 290     {
 291         return_ACPI_STATUS (Status);
 292     }
 293 
 294     /* Root Object. Global handlers are removed here */
 295 
 296     if (Device == ACPI_ROOT_OBJECT)
 297     {
 298         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
 299         {
 300             if (HandlerType & (i+1))
 301             {
 302                 if (!AcpiGbl_GlobalNotify[i].Handler ||
 303                     (AcpiGbl_GlobalNotify[i].Handler != Handler))
 304                 {
 305                     Status = AE_NOT_EXIST;
 306                     goto UnlockAndExit;
 307                 }
 308 
 309                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 310                     "Removing global notify handler\n"));
 311 
 312                 AcpiGbl_GlobalNotify[i].Handler = NULL;
 313                 AcpiGbl_GlobalNotify[i].Context = NULL;
 314             }
 315         }
 316 
 317         goto UnlockAndExit;
 318     }
 319 
 320     /* All other objects: Are Notifies allowed on this object? */
 321 
 322     if (!AcpiEvIsNotifyObject (Node))
 323     {
 324         Status = AE_TYPE;
 325         goto UnlockAndExit;
 326     }
 327 
 328     /* Must have an existing internal object */
 329 
 330     ObjDesc = AcpiNsGetAttachedObject (Node);
 331     if (!ObjDesc)
 332     {
 333         Status = AE_NOT_EXIST;
 334         goto UnlockAndExit;
 335     }
 336 
 337     /* Internal object exists. Find the handler and remove it */
 338 
 339     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
 340     {
 341         if (HandlerType & (i+1))
 342         {
 343             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
 344             PreviousHandlerObj = NULL;
 345 
 346             /* Attempt to find the handler in the handler list */
 347 
 348             while (HandlerObj &&
 349                   (HandlerObj->Notify.Handler != Handler))
 350             {
 351                 PreviousHandlerObj = HandlerObj;
 352                 HandlerObj = HandlerObj->Notify.Next[i];
 353             }
 354 
 355             if (!HandlerObj)
 356             {
 357                 Status = AE_NOT_EXIST;
 358                 goto UnlockAndExit;
 359             }
 360 
 361             /* Remove the handler object from the list */
 362 
 363             if (PreviousHandlerObj) /* Handler is not at the list head */
 364             {
 365                 PreviousHandlerObj->Notify.Next[i] =
 366                     HandlerObj->Notify.Next[i];
 367             }
 368             else /* Handler is at the list head */
 369             {
 370                 ObjDesc->CommonNotify.NotifyList[i] =
 371                     HandlerObj->Notify.Next[i];
 372             }
 373 
 374             AcpiUtRemoveReference (HandlerObj);
 375         }
 376     }
 377 
 378 
 379 UnlockAndExit:
 380     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 381     return_ACPI_STATUS (Status);
 382 }
 383 
 384 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
 385 
 386 
 387 /*******************************************************************************
 388  *
 389  * FUNCTION:    AcpiInstallExceptionHandler
 390  *
 391  * PARAMETERS:  Handler         - Pointer to the handler function for the
 392  *                                event
 393  *
 394  * RETURN:      Status
 395  *
 396  * DESCRIPTION: Saves the pointer to the handler function
 397  *
 398  ******************************************************************************/
 399 
 400 ACPI_STATUS
 401 AcpiInstallExceptionHandler (
 402     ACPI_EXCEPTION_HANDLER  Handler)
 403 {
 404     ACPI_STATUS             Status;
 405 
 406 
 407     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
 408 
 409 
 410     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 411     if (ACPI_FAILURE (Status))
 412     {
 413         return_ACPI_STATUS (Status);
 414     }
 415 
 416     /* Don't allow two handlers. */
 417 
 418     if (AcpiGbl_ExceptionHandler)
 419     {
 420         Status = AE_ALREADY_EXISTS;
 421         goto Cleanup;
 422     }
 423 
 424     /* Install the handler */
 425 
 426     AcpiGbl_ExceptionHandler = Handler;
 427 
 428 Cleanup:
 429     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 430     return_ACPI_STATUS (Status);
 431 }
 432 
 433 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
 434 
 435 
 436 #if (!ACPI_REDUCED_HARDWARE)
 437 /*******************************************************************************
 438  *
 439  * FUNCTION:    AcpiInstallSciHandler
 440  *
 441  * PARAMETERS:  Address             - Address of the handler
 442  *              Context             - Value passed to the handler on each SCI
 443  *
 444  * RETURN:      Status
 445  *
 446  * DESCRIPTION: Install a handler for a System Control Interrupt.
 447  *
 448  ******************************************************************************/
 449 
 450 ACPI_STATUS
 451 AcpiInstallSciHandler (
 452     ACPI_SCI_HANDLER        Address,
 453     void                    *Context)
 454 {
 455     ACPI_SCI_HANDLER_INFO   *NewSciHandler;
 456     ACPI_SCI_HANDLER_INFO   *SciHandler;
 457     ACPI_CPU_FLAGS          Flags;
 458     ACPI_STATUS             Status;
 459 
 460 
 461     ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
 462 
 463 
 464     if (!Address)
 465     {
 466         return_ACPI_STATUS (AE_BAD_PARAMETER);
 467     }
 468 
 469     /* Allocate and init a handler object */
 470 
 471     NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
 472     if (!NewSciHandler)
 473     {
 474         return_ACPI_STATUS (AE_NO_MEMORY);
 475     }
 476 
 477     NewSciHandler->Address = Address;
 478     NewSciHandler->Context = Context;
 479 
 480     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 481     if (ACPI_FAILURE (Status))
 482     {
 483         goto Exit;
 484     }
 485 
 486     /* Lock list during installation */
 487 
 488     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
 489     SciHandler = AcpiGbl_SciHandlerList;
 490 
 491     /* Ensure handler does not already exist */
 492 
 493     while (SciHandler)
 494     {
 495         if (Address == SciHandler->Address)
 496         {
 497             Status = AE_ALREADY_EXISTS;
 498             goto UnlockAndExit;
 499         }
 500 
 501         SciHandler = SciHandler->Next;
 502     }
 503 
 504     /* Install the new handler into the global list (at head) */
 505 
 506     NewSciHandler->Next = AcpiGbl_SciHandlerList;
 507     AcpiGbl_SciHandlerList = NewSciHandler;
 508 
 509 
 510 UnlockAndExit:
 511 
 512     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 513     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 514 
 515 Exit:
 516     if (ACPI_FAILURE (Status))
 517     {
 518         ACPI_FREE (NewSciHandler);
 519     }
 520     return_ACPI_STATUS (Status);
 521 }
 522 
 523 
 524 /*******************************************************************************
 525  *
 526  * FUNCTION:    AcpiRemoveSciHandler
 527  *
 528  * PARAMETERS:  Address             - Address of the handler
 529  *
 530  * RETURN:      Status
 531  *
 532  * DESCRIPTION: Remove a handler for a System Control Interrupt.
 533  *
 534  ******************************************************************************/
 535 
 536 ACPI_STATUS
 537 AcpiRemoveSciHandler (
 538     ACPI_SCI_HANDLER        Address)
 539 {
 540     ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
 541     ACPI_SCI_HANDLER_INFO   *NextSciHandler;
 542     ACPI_CPU_FLAGS          Flags;
 543     ACPI_STATUS             Status;
 544 
 545 
 546     ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
 547 
 548 
 549     if (!Address)
 550     {
 551         return_ACPI_STATUS (AE_BAD_PARAMETER);
 552     }
 553 
 554     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 555     if (ACPI_FAILURE (Status))
 556     {
 557         return_ACPI_STATUS (Status);
 558     }
 559 
 560     /* Remove the SCI handler with lock */
 561 
 562     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
 563 
 564     PrevSciHandler = NULL;
 565     NextSciHandler = AcpiGbl_SciHandlerList;
 566     while (NextSciHandler)
 567     {
 568         if (NextSciHandler->Address == Address)
 569         {
 570             /* Unlink and free the SCI handler info block */
 571 
 572             if (PrevSciHandler)
 573             {
 574                 PrevSciHandler->Next = NextSciHandler->Next;
 575             }
 576             else
 577             {
 578                 AcpiGbl_SciHandlerList = NextSciHandler->Next;
 579             }
 580 
 581             AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 582             ACPI_FREE (NextSciHandler);
 583             goto UnlockAndExit;
 584         }
 585 
 586         PrevSciHandler = NextSciHandler;
 587         NextSciHandler = NextSciHandler->Next;
 588     }
 589 
 590     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 591     Status = AE_NOT_EXIST;
 592 
 593 
 594 UnlockAndExit:
 595     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 596     return_ACPI_STATUS (Status);
 597 }
 598 
 599 
 600 /*******************************************************************************
 601  *
 602  * FUNCTION:    AcpiInstallGlobalEventHandler
 603  *
 604  * PARAMETERS:  Handler         - Pointer to the global event handler function
 605  *              Context         - Value passed to the handler on each event
 606  *
 607  * RETURN:      Status
 608  *
 609  * DESCRIPTION: Saves the pointer to the handler function. The global handler
 610  *              is invoked upon each incoming GPE and Fixed Event. It is
 611  *              invoked at interrupt level at the time of the event dispatch.
 612  *              Can be used to update event counters, etc.
 613  *
 614  ******************************************************************************/
 615 
 616 ACPI_STATUS
 617 AcpiInstallGlobalEventHandler (
 618     ACPI_GBL_EVENT_HANDLER  Handler,
 619     void                    *Context)
 620 {
 621     ACPI_STATUS             Status;
 622 
 623 
 624     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
 625 
 626 
 627     /* Parameter validation */
 628 
 629     if (!Handler)
 630     {
 631         return_ACPI_STATUS (AE_BAD_PARAMETER);
 632     }
 633 
 634     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 635     if (ACPI_FAILURE (Status))
 636     {
 637         return_ACPI_STATUS (Status);
 638     }
 639 
 640     /* Don't allow two handlers. */
 641 
 642     if (AcpiGbl_GlobalEventHandler)
 643     {
 644         Status = AE_ALREADY_EXISTS;
 645         goto Cleanup;
 646     }
 647 
 648     AcpiGbl_GlobalEventHandler = Handler;
 649     AcpiGbl_GlobalEventHandlerContext = Context;
 650 
 651 
 652 Cleanup:
 653     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 654     return_ACPI_STATUS (Status);
 655 }
 656 
 657 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
 658 
 659 
 660 /*******************************************************************************
 661  *
 662  * FUNCTION:    AcpiInstallFixedEventHandler
 663  *
 664  * PARAMETERS:  Event           - Event type to enable.
 665  *              Handler         - Pointer to the handler function for the
 666  *                                event
 667  *              Context         - Value passed to the handler on each GPE
 668  *
 669  * RETURN:      Status
 670  *
 671  * DESCRIPTION: Saves the pointer to the handler function and then enables the
 672  *              event.
 673  *
 674  ******************************************************************************/
 675 
 676 ACPI_STATUS
 677 AcpiInstallFixedEventHandler (
 678     UINT32                  Event,
 679     ACPI_EVENT_HANDLER      Handler,
 680     void                    *Context)
 681 {
 682     ACPI_STATUS             Status;
 683 
 684 
 685     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
 686 
 687 
 688     /* Parameter validation */
 689 
 690     if (Event > ACPI_EVENT_MAX)
 691     {
 692         return_ACPI_STATUS (AE_BAD_PARAMETER);
 693     }
 694 
 695     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 696     if (ACPI_FAILURE (Status))
 697     {
 698         return_ACPI_STATUS (Status);
 699     }
 700 
 701     /* Do not allow multiple handlers */
 702 
 703     if (AcpiGbl_FixedEventHandlers[Event].Handler)
 704     {
 705         Status = AE_ALREADY_EXISTS;
 706         goto Cleanup;
 707     }
 708 
 709     /* Install the handler before enabling the event */
 710 
 711     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
 712     AcpiGbl_FixedEventHandlers[Event].Context = Context;
 713 
 714     Status = AcpiEnableEvent (Event, 0);
 715     if (ACPI_FAILURE (Status))
 716     {
 717         ACPI_WARNING ((AE_INFO,
 718             "Could not enable fixed event - %s (%u)",
 719             AcpiUtGetEventName (Event), Event));
 720 
 721         /* Remove the handler */
 722 
 723         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
 724         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
 725     }
 726     else
 727     {
 728         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 729             "Enabled fixed event %s (%X), Handler=%p\n",
 730             AcpiUtGetEventName (Event), Event, Handler));
 731     }
 732 
 733 
 734 Cleanup:
 735     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 736     return_ACPI_STATUS (Status);
 737 }
 738 
 739 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
 740 
 741 
 742 /*******************************************************************************
 743  *
 744  * FUNCTION:    AcpiRemoveFixedEventHandler
 745  *
 746  * PARAMETERS:  Event           - Event type to disable.
 747  *              Handler         - Address of the handler
 748  *
 749  * RETURN:      Status
 750  *
 751  * DESCRIPTION: Disables the event and unregisters the event handler.
 752  *
 753  ******************************************************************************/
 754 
 755 ACPI_STATUS
 756 AcpiRemoveFixedEventHandler (
 757     UINT32                  Event,
 758     ACPI_EVENT_HANDLER      Handler)
 759 {
 760     ACPI_STATUS             Status = AE_OK;
 761 
 762 
 763     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
 764 
 765 
 766     /* Parameter validation */
 767 
 768     if (Event > ACPI_EVENT_MAX)
 769     {
 770         return_ACPI_STATUS (AE_BAD_PARAMETER);
 771     }
 772 
 773     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 774     if (ACPI_FAILURE (Status))
 775     {
 776         return_ACPI_STATUS (Status);
 777     }
 778 
 779     /* Disable the event before removing the handler */
 780 
 781     Status = AcpiDisableEvent (Event, 0);
 782 
 783     /* Always Remove the handler */
 784 
 785     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
 786     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
 787 
 788     if (ACPI_FAILURE (Status))
 789     {
 790         ACPI_WARNING ((AE_INFO,
 791             "Could not disable fixed event - %s (%u)",
 792             AcpiUtGetEventName (Event), Event));
 793     }
 794     else
 795     {
 796         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
 797             "Disabled fixed event - %s (%X)\n",
 798             AcpiUtGetEventName (Event), Event));
 799     }
 800 
 801     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 802     return_ACPI_STATUS (Status);
 803 }
 804 
 805 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
 806 
 807 
 808 /*******************************************************************************
 809  *
 810  * FUNCTION:    AcpiInstallGpeHandler
 811  *
 812  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
 813  *                                defined GPEs)
 814  *              GpeNumber       - The GPE number within the GPE block
 815  *              Type            - Whether this GPE should be treated as an
 816  *                                edge- or level-triggered interrupt.
 817  *              Address         - Address of the handler
 818  *              Context         - Value passed to the handler on each GPE
 819  *
 820  * RETURN:      Status
 821  *
 822  * DESCRIPTION: Install a handler for a General Purpose Event.
 823  *
 824  ******************************************************************************/
 825 
 826 ACPI_STATUS
 827 AcpiInstallGpeHandler (
 828     ACPI_HANDLE             GpeDevice,
 829     UINT32                  GpeNumber,
 830     UINT32                  Type,
 831     ACPI_GPE_HANDLER        Address,
 832     void                    *Context)
 833 {
 834     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
 835     ACPI_GPE_HANDLER_INFO   *Handler;
 836     ACPI_STATUS             Status;
 837     ACPI_CPU_FLAGS          Flags;
 838 
 839 
 840     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
 841 
 842 
 843     /* Parameter validation */
 844 
 845     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
 846     {
 847         return_ACPI_STATUS (AE_BAD_PARAMETER);
 848     }
 849 
 850     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 851     if (ACPI_FAILURE (Status))
 852     {
 853         return_ACPI_STATUS (Status);
 854     }
 855 
 856     /* Allocate and init handler object (before lock) */
 857 
 858     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
 859     if (!Handler)
 860     {
 861         Status = AE_NO_MEMORY;
 862         goto UnlockAndExit;
 863     }
 864 
 865     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
 866 
 867     /* Ensure that we have a valid GPE number */
 868 
 869     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
 870     if (!GpeEventInfo)
 871     {
 872         Status = AE_BAD_PARAMETER;
 873         goto FreeAndExit;
 874     }
 875 
 876     /* Make sure that there isn't a handler there already */
 877 
 878     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
 879             ACPI_GPE_DISPATCH_HANDLER)
 880     {
 881         Status = AE_ALREADY_EXISTS;
 882         goto FreeAndExit;
 883     }
 884 
 885     Handler->Address = Address;
 886     Handler->Context = Context;
 887     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
 888     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
 889         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
 890 
 891     /*
 892      * If the GPE is associated with a method, it may have been enabled
 893      * automatically during initialization, in which case it has to be
 894      * disabled now to avoid spurious execution of the handler.
 895      */
 896     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
 897          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
 898         GpeEventInfo->RuntimeCount)
 899     {
 900         Handler->OriginallyEnabled = TRUE;
 901         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
 902 
 903         /* Sanity check of original type against new type */
 904 
 905         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
 906         {
 907             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
 908         }
 909     }
 910 
 911     /* Install the handler */
 912 
 913     GpeEventInfo->Dispatch.Handler = Handler;
 914 
 915     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
 916 
 917     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
 918     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
 919 
 920     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 921 
 922 
 923 UnlockAndExit:
 924     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 925     return_ACPI_STATUS (Status);
 926 
 927 FreeAndExit:
 928     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
 929     ACPI_FREE (Handler);
 930     goto UnlockAndExit;
 931 }
 932 
 933 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
 934 
 935 
 936 /*******************************************************************************
 937  *
 938  * FUNCTION:    AcpiRemoveGpeHandler
 939  *
 940  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
 941  *                                defined GPEs)
 942  *              GpeNumber       - The event to remove a handler
 943  *              Address         - Address of the handler
 944  *
 945  * RETURN:      Status
 946  *
 947  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
 948  *
 949  ******************************************************************************/
 950 
 951 ACPI_STATUS
 952 AcpiRemoveGpeHandler (
 953     ACPI_HANDLE             GpeDevice,
 954     UINT32                  GpeNumber,
 955     ACPI_GPE_HANDLER        Address)
 956 {
 957     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
 958     ACPI_GPE_HANDLER_INFO   *Handler;
 959     ACPI_STATUS             Status;
 960     ACPI_CPU_FLAGS          Flags;
 961 
 962 
 963     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
 964 
 965 
 966     /* Parameter validation */
 967 
 968     if (!Address)
 969     {
 970         return_ACPI_STATUS (AE_BAD_PARAMETER);
 971     }
 972 
 973     /* Make sure all deferred GPE tasks are completed */
 974 
 975     AcpiOsWaitEventsComplete ();
 976 
 977     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 978     if (ACPI_FAILURE (Status))
 979     {
 980         return_ACPI_STATUS (Status);
 981     }
 982 
 983     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
 984 
 985     /* Ensure that we have a valid GPE number */
 986 
 987     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
 988     if (!GpeEventInfo)
 989     {
 990         Status = AE_BAD_PARAMETER;
 991         goto UnlockAndExit;
 992     }
 993 
 994     /* Make sure that a handler is indeed installed */
 995 
 996     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
 997             ACPI_GPE_DISPATCH_HANDLER)
 998     {
 999         Status = AE_NOT_EXIST;
1000         goto UnlockAndExit;
1001     }
1002 
1003     /* Make sure that the installed handler is the same */
1004 
1005     if (GpeEventInfo->Dispatch.Handler->Address != Address)
1006     {
1007         Status = AE_BAD_PARAMETER;
1008         goto UnlockAndExit;
1009     }
1010 
1011     /* Remove the handler */
1012 
1013     Handler = GpeEventInfo->Dispatch.Handler;
1014 
1015     /* Restore Method node (if any), set dispatch flags */
1016 
1017     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
1018     GpeEventInfo->Flags &=
1019         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
1020     GpeEventInfo->Flags |= Handler->OriginalFlags;
1021 
1022     /*
1023      * If the GPE was previously associated with a method and it was
1024      * enabled, it should be enabled at this point to restore the
1025      * post-initialization configuration.
1026      */
1027     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
1028         Handler->OriginallyEnabled)
1029     {
1030         (void) AcpiEvAddGpeReference (GpeEventInfo);
1031     }
1032 
1033     /* Now we can free the handler object */
1034 
1035     ACPI_FREE (Handler);
1036 
1037 
1038 UnlockAndExit:
1039     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1040     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
1041     return_ACPI_STATUS (Status);
1042 }
1043 
1044 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
1045 
1046 
1047 /*******************************************************************************
1048  *
1049  * FUNCTION:    AcpiAcquireGlobalLock
1050  *
1051  * PARAMETERS:  Timeout         - How long the caller is willing to wait
1052  *              Handle          - Where the handle to the lock is returned
1053  *                                (if acquired)
1054  *
1055  * RETURN:      Status
1056  *
1057  * DESCRIPTION: Acquire the ACPI Global Lock
1058  *
1059  * Note: Allows callers with the same thread ID to acquire the global lock
1060  * multiple times. In other words, externally, the behavior of the global lock
1061  * is identical to an AML mutex. On the first acquire, a new handle is
1062  * returned. On any subsequent calls to acquire by the same thread, the same
1063  * handle is returned.
1064  *
1065  ******************************************************************************/
1066 
1067 ACPI_STATUS
1068 AcpiAcquireGlobalLock (
1069     UINT16                  Timeout,
1070     UINT32                  *Handle)
1071 {
1072     ACPI_STATUS             Status;
1073 
1074 
1075     if (!Handle)
1076     {
1077         return (AE_BAD_PARAMETER);
1078     }
1079 
1080     /* Must lock interpreter to prevent race conditions */
1081 
1082     AcpiExEnterInterpreter ();
1083 
1084     Status = AcpiExAcquireMutexObject (Timeout,
1085                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1086 
1087     if (ACPI_SUCCESS (Status))
1088     {
1089         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1090 
1091         *Handle = AcpiGbl_GlobalLockHandle;
1092     }
1093 
1094     AcpiExExitInterpreter ();
1095     return (Status);
1096 }
1097 
1098 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1099 
1100 
1101 /*******************************************************************************
1102  *
1103  * FUNCTION:    AcpiReleaseGlobalLock
1104  *
1105  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1106  *
1107  * RETURN:      Status
1108  *
1109  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1110  *
1111  ******************************************************************************/
1112 
1113 ACPI_STATUS
1114 AcpiReleaseGlobalLock (
1115     UINT32                  Handle)
1116 {
1117     ACPI_STATUS             Status;
1118 
1119 
1120     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1121     {
1122         return (AE_NOT_ACQUIRED);
1123     }
1124 
1125     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1126     return (Status);
1127 }
1128 
1129 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1130 
1131 #endif /* !ACPI_REDUCED_HARDWARE */