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 978