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