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