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