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