1 /****************************************************************************** 2 * 3 * Module Name: evxface - External interfaces for ACPI events 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 */