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