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