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 = AE_OK; 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 /* Root Object. Global handlers are removed here */ 285 286 if (Device == ACPI_ROOT_OBJECT) 287 { 288 for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 289 { 290 if (HandlerType & (i+1)) 291 { 292 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 293 if (ACPI_FAILURE (Status)) 294 { 295 return_ACPI_STATUS (Status); 296 } 297 298 if (!AcpiGbl_GlobalNotify[i].Handler || 299 (AcpiGbl_GlobalNotify[i].Handler != Handler)) 300 { 301 Status = AE_NOT_EXIST; 302 goto UnlockAndExit; 303 } 304 305 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 306 "Removing global notify handler\n")); 307 308 AcpiGbl_GlobalNotify[i].Handler = NULL; 309 AcpiGbl_GlobalNotify[i].Context = NULL; 310 311 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 312 313 /* Make sure all deferred notify tasks are completed */ 314 315 AcpiOsWaitEventsComplete (); 316 } 317 } 318 319 return_ACPI_STATUS (AE_OK); 320 } 321 322 /* All other objects: Are Notifies allowed on this object? */ 323 324 if (!AcpiEvIsNotifyObject (Node)) 325 { 326 return_ACPI_STATUS (AE_TYPE); 327 } 328 329 /* Must have an existing internal object */ 330 331 ObjDesc = AcpiNsGetAttachedObject (Node); 332 if (!ObjDesc) 333 { 334 return_ACPI_STATUS (AE_NOT_EXIST); 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 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 344 if (ACPI_FAILURE (Status)) 345 { 346 return_ACPI_STATUS (Status); 347 } 348 349 HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; 350 PreviousHandlerObj = NULL; 351 352 /* Attempt to find the handler in the handler list */ 353 354 while (HandlerObj && 355 (HandlerObj->Notify.Handler != Handler)) 356 { 357 PreviousHandlerObj = HandlerObj; 358 HandlerObj = HandlerObj->Notify.Next[i]; 359 } 360 361 if (!HandlerObj) 362 { 363 Status = AE_NOT_EXIST; 364 goto UnlockAndExit; 365 } 366 367 /* Remove the handler object from the list */ 368 369 if (PreviousHandlerObj) /* Handler is not at the list head */ 370 { 371 PreviousHandlerObj->Notify.Next[i] = 372 HandlerObj->Notify.Next[i]; 373 } 374 else /* Handler is at the list head */ 375 { 376 ObjDesc->CommonNotify.NotifyList[i] = 377 HandlerObj->Notify.Next[i]; 378 } 379 380 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 381 382 /* Make sure all deferred notify tasks are completed */ 383 384 AcpiOsWaitEventsComplete (); 385 AcpiUtRemoveReference (HandlerObj); 386 } 387 } 388 389 return_ACPI_STATUS (Status); 390 391 392 UnlockAndExit: 393 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 394 return_ACPI_STATUS (Status); 395 } 396 397 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) 398 399 400 /******************************************************************************* 401 * 402 * FUNCTION: AcpiInstallExceptionHandler 403 * 404 * PARAMETERS: Handler - Pointer to the handler function for the 405 * event 406 * 407 * RETURN: Status 408 * 409 * DESCRIPTION: Saves the pointer to the handler function 410 * 411 ******************************************************************************/ 412 413 ACPI_STATUS 414 AcpiInstallExceptionHandler ( 415 ACPI_EXCEPTION_HANDLER Handler) 416 { 417 ACPI_STATUS Status; 418 419 420 ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); 421 422 423 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 424 if (ACPI_FAILURE (Status)) 425 { 426 return_ACPI_STATUS (Status); 427 } 428 429 /* Don't allow two handlers. */ 430 431 if (AcpiGbl_ExceptionHandler) 432 { 433 Status = AE_ALREADY_EXISTS; 434 goto Cleanup; 435 } 436 437 /* Install the handler */ 438 439 AcpiGbl_ExceptionHandler = Handler; 440 441 Cleanup: 442 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 443 return_ACPI_STATUS (Status); 444 } 445 446 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) 447 448 449 #if (!ACPI_REDUCED_HARDWARE) 450 /******************************************************************************* 451 * 452 * FUNCTION: AcpiInstallSciHandler 453 * 454 * PARAMETERS: Address - Address of the handler 455 * Context - Value passed to the handler on each SCI 456 * 457 * RETURN: Status 458 * 459 * DESCRIPTION: Install a handler for a System Control Interrupt. 460 * 461 ******************************************************************************/ 462 463 ACPI_STATUS 464 AcpiInstallSciHandler ( 465 ACPI_SCI_HANDLER Address, 466 void *Context) 467 { 468 ACPI_SCI_HANDLER_INFO *NewSciHandler; 469 ACPI_SCI_HANDLER_INFO *SciHandler; 470 ACPI_CPU_FLAGS Flags; 471 ACPI_STATUS Status; 472 473 474 ACPI_FUNCTION_TRACE (AcpiInstallSciHandler); 475 476 477 if (!Address) 478 { 479 return_ACPI_STATUS (AE_BAD_PARAMETER); 480 } 481 482 /* Allocate and init a handler object */ 483 484 NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO)); 485 if (!NewSciHandler) 486 { 487 return_ACPI_STATUS (AE_NO_MEMORY); 488 } 489 490 NewSciHandler->Address = Address; 491 NewSciHandler->Context = Context; 492 493 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 494 if (ACPI_FAILURE (Status)) 495 { 496 goto Exit; 497 } 498 499 /* Lock list during installation */ 500 501 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 502 SciHandler = AcpiGbl_SciHandlerList; 503 504 /* Ensure handler does not already exist */ 505 506 while (SciHandler) 507 { 508 if (Address == SciHandler->Address) 509 { 510 Status = AE_ALREADY_EXISTS; 511 goto UnlockAndExit; 512 } 513 514 SciHandler = SciHandler->Next; 515 } 516 517 /* Install the new handler into the global list (at head) */ 518 519 NewSciHandler->Next = AcpiGbl_SciHandlerList; 520 AcpiGbl_SciHandlerList = NewSciHandler; 521 522 523 UnlockAndExit: 524 525 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 526 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 527 528 Exit: 529 if (ACPI_FAILURE (Status)) 530 { 531 ACPI_FREE (NewSciHandler); 532 } 533 return_ACPI_STATUS (Status); 534 } 535 536 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler) 537 538 539 /******************************************************************************* 540 * 541 * FUNCTION: AcpiRemoveSciHandler 542 * 543 * PARAMETERS: Address - Address of the handler 544 * 545 * RETURN: Status 546 * 547 * DESCRIPTION: Remove a handler for a System Control Interrupt. 548 * 549 ******************************************************************************/ 550 551 ACPI_STATUS 552 AcpiRemoveSciHandler ( 553 ACPI_SCI_HANDLER Address) 554 { 555 ACPI_SCI_HANDLER_INFO *PrevSciHandler; 556 ACPI_SCI_HANDLER_INFO *NextSciHandler; 557 ACPI_CPU_FLAGS Flags; 558 ACPI_STATUS Status; 559 560 561 ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler); 562 563 564 if (!Address) 565 { 566 return_ACPI_STATUS (AE_BAD_PARAMETER); 567 } 568 569 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 570 if (ACPI_FAILURE (Status)) 571 { 572 return_ACPI_STATUS (Status); 573 } 574 575 /* Remove the SCI handler with lock */ 576 577 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 578 579 PrevSciHandler = NULL; 580 NextSciHandler = AcpiGbl_SciHandlerList; 581 while (NextSciHandler) 582 { 583 if (NextSciHandler->Address == Address) 584 { 585 /* Unlink and free the SCI handler info block */ 586 587 if (PrevSciHandler) 588 { 589 PrevSciHandler->Next = NextSciHandler->Next; 590 } 591 else 592 { 593 AcpiGbl_SciHandlerList = NextSciHandler->Next; 594 } 595 596 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 597 ACPI_FREE (NextSciHandler); 598 goto UnlockAndExit; 599 } 600 601 PrevSciHandler = NextSciHandler; 602 NextSciHandler = NextSciHandler->Next; 603 } 604 605 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 606 Status = AE_NOT_EXIST; 607 608 609 UnlockAndExit: 610 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 611 return_ACPI_STATUS (Status); 612 } 613 614 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler) 615 616 617 /******************************************************************************* 618 * 619 * FUNCTION: AcpiInstallGlobalEventHandler 620 * 621 * PARAMETERS: Handler - Pointer to the global event handler function 622 * Context - Value passed to the handler on each event 623 * 624 * RETURN: Status 625 * 626 * DESCRIPTION: Saves the pointer to the handler function. The global handler 627 * is invoked upon each incoming GPE and Fixed Event. It is 628 * invoked at interrupt level at the time of the event dispatch. 629 * Can be used to update event counters, etc. 630 * 631 ******************************************************************************/ 632 633 ACPI_STATUS 634 AcpiInstallGlobalEventHandler ( 635 ACPI_GBL_EVENT_HANDLER Handler, 636 void *Context) 637 { 638 ACPI_STATUS Status; 639 640 641 ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); 642 643 644 /* Parameter validation */ 645 646 if (!Handler) 647 { 648 return_ACPI_STATUS (AE_BAD_PARAMETER); 649 } 650 651 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 652 if (ACPI_FAILURE (Status)) 653 { 654 return_ACPI_STATUS (Status); 655 } 656 657 /* Don't allow two handlers. */ 658 659 if (AcpiGbl_GlobalEventHandler) 660 { 661 Status = AE_ALREADY_EXISTS; 662 goto Cleanup; 663 } 664 665 AcpiGbl_GlobalEventHandler = Handler; 666 AcpiGbl_GlobalEventHandlerContext = Context; 667 668 669 Cleanup: 670 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 671 return_ACPI_STATUS (Status); 672 } 673 674 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) 675 676 677 /******************************************************************************* 678 * 679 * FUNCTION: AcpiInstallFixedEventHandler 680 * 681 * PARAMETERS: Event - Event type to enable. 682 * Handler - Pointer to the handler function for the 683 * event 684 * Context - Value passed to the handler on each GPE 685 * 686 * RETURN: Status 687 * 688 * DESCRIPTION: Saves the pointer to the handler function and then enables the 689 * event. 690 * 691 ******************************************************************************/ 692 693 ACPI_STATUS 694 AcpiInstallFixedEventHandler ( 695 UINT32 Event, 696 ACPI_EVENT_HANDLER Handler, 697 void *Context) 698 { 699 ACPI_STATUS Status; 700 701 702 ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); 703 704 705 /* Parameter validation */ 706 707 if (Event > ACPI_EVENT_MAX) 708 { 709 return_ACPI_STATUS (AE_BAD_PARAMETER); 710 } 711 712 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 713 if (ACPI_FAILURE (Status)) 714 { 715 return_ACPI_STATUS (Status); 716 } 717 718 /* Do not allow multiple handlers */ 719 720 if (AcpiGbl_FixedEventHandlers[Event].Handler) 721 { 722 Status = AE_ALREADY_EXISTS; 723 goto Cleanup; 724 } 725 726 /* Install the handler before enabling the event */ 727 728 AcpiGbl_FixedEventHandlers[Event].Handler = Handler; 729 AcpiGbl_FixedEventHandlers[Event].Context = Context; 730 731 Status = AcpiEnableEvent (Event, 0); 732 if (ACPI_FAILURE (Status)) 733 { 734 ACPI_WARNING ((AE_INFO, 735 "Could not enable fixed event - %s (%u)", 736 AcpiUtGetEventName (Event), Event)); 737 738 /* Remove the handler */ 739 740 AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 741 AcpiGbl_FixedEventHandlers[Event].Context = NULL; 742 } 743 else 744 { 745 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 746 "Enabled fixed event %s (%X), Handler=%p\n", 747 AcpiUtGetEventName (Event), Event, Handler)); 748 } 749 750 751 Cleanup: 752 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 753 return_ACPI_STATUS (Status); 754 } 755 756 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) 757 758 759 /******************************************************************************* 760 * 761 * FUNCTION: AcpiRemoveFixedEventHandler 762 * 763 * PARAMETERS: Event - Event type to disable. 764 * Handler - Address of the handler 765 * 766 * RETURN: Status 767 * 768 * DESCRIPTION: Disables the event and unregisters the event handler. 769 * 770 ******************************************************************************/ 771 772 ACPI_STATUS 773 AcpiRemoveFixedEventHandler ( 774 UINT32 Event, 775 ACPI_EVENT_HANDLER Handler) 776 { 777 ACPI_STATUS Status = AE_OK; 778 779 780 ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); 781 782 783 /* Parameter validation */ 784 785 if (Event > ACPI_EVENT_MAX) 786 { 787 return_ACPI_STATUS (AE_BAD_PARAMETER); 788 } 789 790 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 791 if (ACPI_FAILURE (Status)) 792 { 793 return_ACPI_STATUS (Status); 794 } 795 796 /* Disable the event before removing the handler */ 797 798 Status = AcpiDisableEvent (Event, 0); 799 800 /* Always Remove the handler */ 801 802 AcpiGbl_FixedEventHandlers[Event].Handler = NULL; 803 AcpiGbl_FixedEventHandlers[Event].Context = NULL; 804 805 if (ACPI_FAILURE (Status)) 806 { 807 ACPI_WARNING ((AE_INFO, 808 "Could not disable fixed event - %s (%u)", 809 AcpiUtGetEventName (Event), Event)); 810 } 811 else 812 { 813 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 814 "Disabled fixed event - %s (%X)\n", 815 AcpiUtGetEventName (Event), Event)); 816 } 817 818 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 819 return_ACPI_STATUS (Status); 820 } 821 822 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) 823 824 825 /******************************************************************************* 826 * 827 * FUNCTION: AcpiInstallGpeHandler 828 * 829 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 830 * defined GPEs) 831 * GpeNumber - The GPE number within the GPE block 832 * Type - Whether this GPE should be treated as an 833 * edge- or level-triggered interrupt. 834 * Address - Address of the handler 835 * Context - Value passed to the handler on each GPE 836 * 837 * RETURN: Status 838 * 839 * DESCRIPTION: Install a handler for a General Purpose Event. 840 * 841 ******************************************************************************/ 842 843 ACPI_STATUS 844 AcpiInstallGpeHandler ( 845 ACPI_HANDLE GpeDevice, 846 UINT32 GpeNumber, 847 UINT32 Type, 848 ACPI_GPE_HANDLER Address, 849 void *Context) 850 { 851 ACPI_GPE_EVENT_INFO *GpeEventInfo; 852 ACPI_GPE_HANDLER_INFO *Handler; 853 ACPI_STATUS Status; 854 ACPI_CPU_FLAGS Flags; 855 856 857 ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); 858 859 860 /* Parameter validation */ 861 862 if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) 863 { 864 return_ACPI_STATUS (AE_BAD_PARAMETER); 865 } 866 867 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 868 if (ACPI_FAILURE (Status)) 869 { 870 return_ACPI_STATUS (Status); 871 } 872 873 /* Allocate and init handler object (before lock) */ 874 875 Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO)); 876 if (!Handler) 877 { 878 Status = AE_NO_MEMORY; 879 goto UnlockAndExit; 880 } 881 882 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 883 884 /* Ensure that we have a valid GPE number */ 885 886 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 887 if (!GpeEventInfo) 888 { 889 Status = AE_BAD_PARAMETER; 890 goto FreeAndExit; 891 } 892 893 /* Make sure that there isn't a handler there already */ 894 895 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 896 ACPI_GPE_DISPATCH_HANDLER) 897 { 898 Status = AE_ALREADY_EXISTS; 899 goto FreeAndExit; 900 } 901 902 Handler->Address = Address; 903 Handler->Context = Context; 904 Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; 905 Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags & 906 (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK)); 907 908 /* 909 * If the GPE is associated with a method, it may have been enabled 910 * automatically during initialization, in which case it has to be 911 * disabled now to avoid spurious execution of the handler. 912 */ 913 if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) || 914 (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) && 915 GpeEventInfo->RuntimeCount) 916 { 917 Handler->OriginallyEnabled = TRUE; 918 (void) AcpiEvRemoveGpeReference (GpeEventInfo); 919 920 /* Sanity check of original type against new type */ 921 922 if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) 923 { 924 ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)")); 925 } 926 } 927 928 /* Install the handler */ 929 930 GpeEventInfo->Dispatch.Handler = Handler; 931 932 /* Setup up dispatch flags to indicate handler (vs. method/notify) */ 933 934 GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 935 GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER); 936 937 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 938 939 940 UnlockAndExit: 941 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 942 return_ACPI_STATUS (Status); 943 944 FreeAndExit: 945 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 946 ACPI_FREE (Handler); 947 goto UnlockAndExit; 948 } 949 950 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) 951 952 953 /******************************************************************************* 954 * 955 * FUNCTION: AcpiRemoveGpeHandler 956 * 957 * PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT 958 * defined GPEs) 959 * GpeNumber - The event to remove a handler 960 * Address - Address of the handler 961 * 962 * RETURN: Status 963 * 964 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent. 965 * 966 ******************************************************************************/ 967 968 ACPI_STATUS 969 AcpiRemoveGpeHandler ( 970 ACPI_HANDLE GpeDevice, 971 UINT32 GpeNumber, 972 ACPI_GPE_HANDLER Address) 973 { 974 ACPI_GPE_EVENT_INFO *GpeEventInfo; 975 ACPI_GPE_HANDLER_INFO *Handler; 976 ACPI_STATUS Status; 977 ACPI_CPU_FLAGS Flags; 978 979 980 ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); 981 982 983 /* Parameter validation */ 984 985 if (!Address) 986 { 987 return_ACPI_STATUS (AE_BAD_PARAMETER); 988 } 989 990 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 991 if (ACPI_FAILURE (Status)) 992 { 993 return_ACPI_STATUS (Status); 994 } 995 996 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 997 998 /* Ensure that we have a valid GPE number */ 999 1000 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 1001 if (!GpeEventInfo) 1002 { 1003 Status = AE_BAD_PARAMETER; 1004 goto UnlockAndExit; 1005 } 1006 1007 /* Make sure that a handler is indeed installed */ 1008 1009 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != 1010 ACPI_GPE_DISPATCH_HANDLER) 1011 { 1012 Status = AE_NOT_EXIST; 1013 goto UnlockAndExit; 1014 } 1015 1016 /* Make sure that the installed handler is the same */ 1017 1018 if (GpeEventInfo->Dispatch.Handler->Address != Address) 1019 { 1020 Status = AE_BAD_PARAMETER; 1021 goto UnlockAndExit; 1022 } 1023 1024 /* Remove the handler */ 1025 1026 Handler = GpeEventInfo->Dispatch.Handler; 1027 1028 /* Restore Method node (if any), set dispatch flags */ 1029 1030 GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; 1031 GpeEventInfo->Flags &= 1032 ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); 1033 GpeEventInfo->Flags |= Handler->OriginalFlags; 1034 1035 /* 1036 * If the GPE was previously associated with a method and it was 1037 * enabled, it should be enabled at this point to restore the 1038 * post-initialization configuration. 1039 */ 1040 if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) && 1041 Handler->OriginallyEnabled) 1042 { 1043 (void) AcpiEvAddGpeReference (GpeEventInfo); 1044 } 1045 1046 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 1047 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 1048 1049 /* Make sure all deferred GPE tasks are completed */ 1050 1051 AcpiOsWaitEventsComplete (); 1052 1053 /* Now we can free the handler object */ 1054 1055 ACPI_FREE (Handler); 1056 return_ACPI_STATUS (Status); 1057 1058 UnlockAndExit: 1059 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 1060 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 1061 return_ACPI_STATUS (Status); 1062 } 1063 1064 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler) 1065 1066 1067 /******************************************************************************* 1068 * 1069 * FUNCTION: AcpiAcquireGlobalLock 1070 * 1071 * PARAMETERS: Timeout - How long the caller is willing to wait 1072 * Handle - Where the handle to the lock is returned 1073 * (if acquired) 1074 * 1075 * RETURN: Status 1076 * 1077 * DESCRIPTION: Acquire the ACPI Global Lock 1078 * 1079 * Note: Allows callers with the same thread ID to acquire the global lock 1080 * multiple times. In other words, externally, the behavior of the global lock 1081 * is identical to an AML mutex. On the first acquire, a new handle is 1082 * returned. On any subsequent calls to acquire by the same thread, the same 1083 * handle is returned. 1084 * 1085 ******************************************************************************/ 1086 1087 ACPI_STATUS 1088 AcpiAcquireGlobalLock ( 1089 UINT16 Timeout, 1090 UINT32 *Handle) 1091 { 1092 ACPI_STATUS Status; 1093 1094 1095 if (!Handle) 1096 { 1097 return (AE_BAD_PARAMETER); 1098 } 1099 1100 /* Must lock interpreter to prevent race conditions */ 1101 1102 AcpiExEnterInterpreter (); 1103 1104 Status = AcpiExAcquireMutexObject (Timeout, 1105 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); 1106 1107 if (ACPI_SUCCESS (Status)) 1108 { 1109 /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */ 1110 1111 *Handle = AcpiGbl_GlobalLockHandle; 1112 } 1113 1114 AcpiExExitInterpreter (); 1115 return (Status); 1116 } 1117 1118 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock) 1119 1120 1121 /******************************************************************************* 1122 * 1123 * FUNCTION: AcpiReleaseGlobalLock 1124 * 1125 * PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock 1126 * 1127 * RETURN: Status 1128 * 1129 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. 1130 * 1131 ******************************************************************************/ 1132 1133 ACPI_STATUS 1134 AcpiReleaseGlobalLock ( 1135 UINT32 Handle) 1136 { 1137 ACPI_STATUS Status; 1138 1139 1140 if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) 1141 { 1142 return (AE_NOT_ACQUIRED); 1143 } 1144 1145 Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); 1146 return (Status); 1147 } 1148 1149 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) 1150 1151 #endif /* !ACPI_REDUCED_HARDWARE */ 1152