1 /****************************************************************************** 2 * 3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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 __EVXFGPE_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "acevents.h" 50 #include "acnamesp.h" 51 52 #define _COMPONENT ACPI_EVENTS 53 ACPI_MODULE_NAME ("evxfgpe") 54 55 56 /******************************************************************************* 57 * 58 * FUNCTION: AcpiUpdateAllGpes 59 * 60 * PARAMETERS: None 61 * 62 * RETURN: Status 63 * 64 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have 65 * associated _Lxx or _Exx methods and are not pointed to by any 66 * device _PRW methods (this indicates that these GPEs are 67 * generally intended for system or device wakeup. Such GPEs 68 * have to be enabled directly when the devices whose _PRW 69 * methods point to them are set up for wakeup signaling.) 70 * 71 * NOTE: Should be called after any GPEs are added to the system. Primarily, 72 * after the system _PRW methods have been run, but also after a GPE Block 73 * Device has been added or if any new GPE methods have been added via a 74 * dynamic table load. 75 * 76 ******************************************************************************/ 77 78 ACPI_STATUS 79 AcpiUpdateAllGpes ( 80 void) 81 { 82 ACPI_STATUS Status; 83 84 85 ACPI_FUNCTION_TRACE (AcpiUpdateGpes); 86 87 88 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 89 if (ACPI_FAILURE (Status)) 90 { 91 return_ACPI_STATUS (Status); 92 } 93 94 if (AcpiGbl_AllGpesInitialized) 95 { 96 goto UnlockAndExit; 97 } 98 99 Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL); 100 if (ACPI_SUCCESS (Status)) 101 { 102 AcpiGbl_AllGpesInitialized = TRUE; 103 } 104 105 UnlockAndExit: 106 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 107 return_ACPI_STATUS (Status); 108 } 109 110 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes) 111 112 113 /******************************************************************************* 114 * 115 * FUNCTION: AcpiEnableGpe 116 * 117 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 118 * GpeNumber - GPE level within the GPE block 119 * 120 * RETURN: Status 121 * 122 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 123 * hardware-enabled. 124 * 125 ******************************************************************************/ 126 127 ACPI_STATUS 128 AcpiEnableGpe ( 129 ACPI_HANDLE GpeDevice, 130 UINT32 GpeNumber) 131 { 132 ACPI_STATUS Status = AE_BAD_PARAMETER; 133 ACPI_GPE_EVENT_INFO *GpeEventInfo; 134 ACPI_CPU_FLAGS Flags; 135 136 137 ACPI_FUNCTION_TRACE (AcpiEnableGpe); 138 139 140 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 141 142 /* Ensure that we have a valid GPE number */ 143 144 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 145 if (GpeEventInfo) 146 { 147 Status = AcpiEvAddGpeReference (GpeEventInfo); 148 } 149 150 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 151 return_ACPI_STATUS (Status); 152 } 153 154 ACPI_EXPORT_SYMBOL (AcpiEnableGpe) 155 156 157 /******************************************************************************* 158 * 159 * FUNCTION: AcpiDisableGpe 160 * 161 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 162 * GpeNumber - GPE level within the GPE block 163 * 164 * RETURN: Status 165 * 166 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 167 * removed, only then is the GPE disabled (for runtime GPEs), or 168 * the GPE mask bit disabled (for wake GPEs) 169 * 170 ******************************************************************************/ 171 172 ACPI_STATUS 173 AcpiDisableGpe ( 174 ACPI_HANDLE GpeDevice, 175 UINT32 GpeNumber) 176 { 177 ACPI_STATUS Status = AE_BAD_PARAMETER; 178 ACPI_GPE_EVENT_INFO *GpeEventInfo; 179 ACPI_CPU_FLAGS Flags; 180 181 182 ACPI_FUNCTION_TRACE (AcpiDisableGpe); 183 184 185 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 186 187 /* Ensure that we have a valid GPE number */ 188 189 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 190 if (GpeEventInfo) 191 { 192 Status = AcpiEvRemoveGpeReference (GpeEventInfo); 193 } 194 195 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 196 return_ACPI_STATUS (Status); 197 } 198 199 ACPI_EXPORT_SYMBOL (AcpiDisableGpe) 200 201 202 /******************************************************************************* 203 * 204 * FUNCTION: AcpiSetGpe 205 * 206 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 207 * GpeNumber - GPE level within the GPE block 208 * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE 209 * 210 * RETURN: Status 211 * 212 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses 213 * the reference count mechanism used in the AcpiEnableGpe and 214 * AcpiDisableGpe interfaces -- and should be used with care. 215 * 216 * Note: Typically used to disable a runtime GPE for short period of time, 217 * then re-enable it, without disturbing the existing reference counts. This 218 * is useful, for example, in the Embedded Controller (EC) driver. 219 * 220 ******************************************************************************/ 221 222 ACPI_STATUS 223 AcpiSetGpe ( 224 ACPI_HANDLE GpeDevice, 225 UINT32 GpeNumber, 226 UINT8 Action) 227 { 228 ACPI_GPE_EVENT_INFO *GpeEventInfo; 229 ACPI_STATUS Status; 230 ACPI_CPU_FLAGS Flags; 231 232 233 ACPI_FUNCTION_TRACE (AcpiSetGpe); 234 235 236 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 237 238 /* Ensure that we have a valid GPE number */ 239 240 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 241 if (!GpeEventInfo) 242 { 243 Status = AE_BAD_PARAMETER; 244 goto UnlockAndExit; 245 } 246 247 /* Perform the action */ 248 249 switch (Action) 250 { 251 case ACPI_GPE_ENABLE: 252 Status = AcpiEvEnableGpe (GpeEventInfo); 253 break; 254 255 case ACPI_GPE_DISABLE: 256 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 257 break; 258 259 default: 260 Status = AE_BAD_PARAMETER; 261 break; 262 } 263 264 UnlockAndExit: 265 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 266 return_ACPI_STATUS (Status); 267 } 268 269 ACPI_EXPORT_SYMBOL (AcpiSetGpe) 270 271 272 /******************************************************************************* 273 * 274 * FUNCTION: AcpiSetupGpeForWake 275 * 276 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW) 277 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 278 * GpeNumber - GPE level within the GPE block 279 * 280 * RETURN: Status 281 * 282 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This 283 * interface is intended to be used as the host executes the 284 * _PRW methods (Power Resources for Wake) in the system tables. 285 * Each _PRW appears under a Device Object (The WakeDevice), and 286 * contains the info for the wake GPE associated with the 287 * WakeDevice. 288 * 289 ******************************************************************************/ 290 291 ACPI_STATUS 292 AcpiSetupGpeForWake ( 293 ACPI_HANDLE WakeDevice, 294 ACPI_HANDLE GpeDevice, 295 UINT32 GpeNumber) 296 { 297 ACPI_STATUS Status = AE_BAD_PARAMETER; 298 ACPI_GPE_EVENT_INFO *GpeEventInfo; 299 ACPI_NAMESPACE_NODE *DeviceNode; 300 ACPI_CPU_FLAGS Flags; 301 302 303 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake); 304 305 306 /* Parameter Validation */ 307 308 if (!WakeDevice) 309 { 310 /* 311 * By forcing WakeDevice to be valid, we automatically enable the 312 * implicit notify feature on all hosts. 313 */ 314 return_ACPI_STATUS (AE_BAD_PARAMETER); 315 } 316 317 /* Handle root object case */ 318 319 if (WakeDevice == ACPI_ROOT_OBJECT) 320 { 321 DeviceNode = AcpiGbl_RootNode; 322 } 323 else 324 { 325 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); 326 } 327 328 /* Validate WakeDevice is of type Device */ 329 330 if (DeviceNode->Type != ACPI_TYPE_DEVICE) 331 { 332 return_ACPI_STATUS (AE_BAD_PARAMETER); 333 } 334 335 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 336 337 /* Ensure that we have a valid GPE number */ 338 339 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 340 if (GpeEventInfo) 341 { 342 /* 343 * If there is no method or handler for this GPE, then the 344 * WakeDevice will be notified whenever this GPE fires (aka 345 * "implicit notify") Note: The GPE is assumed to be 346 * level-triggered (for windows compatibility). 347 */ 348 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 349 ACPI_GPE_DISPATCH_NONE) 350 { 351 GpeEventInfo->Flags = 352 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 353 GpeEventInfo->Dispatch.DeviceNode = DeviceNode; 354 } 355 356 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 357 Status = AE_OK; 358 } 359 360 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 361 return_ACPI_STATUS (Status); 362 } 363 364 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) 365 366 367 /******************************************************************************* 368 * 369 * FUNCTION: AcpiSetGpeWakeMask 370 * 371 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 372 * GpeNumber - GPE level within the GPE block 373 * Action - Enable or Disable 374 * 375 * RETURN: Status 376 * 377 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 378 * already be marked as a WAKE GPE. 379 * 380 ******************************************************************************/ 381 382 ACPI_STATUS 383 AcpiSetGpeWakeMask ( 384 ACPI_HANDLE GpeDevice, 385 UINT32 GpeNumber, 386 UINT8 Action) 387 { 388 ACPI_STATUS Status = AE_OK; 389 ACPI_GPE_EVENT_INFO *GpeEventInfo; 390 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 391 ACPI_CPU_FLAGS Flags; 392 UINT32 RegisterBit; 393 394 395 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); 396 397 398 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 399 400 /* 401 * Ensure that we have a valid GPE number and that this GPE is in 402 * fact a wake GPE 403 */ 404 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 405 if (!GpeEventInfo) 406 { 407 Status = AE_BAD_PARAMETER; 408 goto UnlockAndExit; 409 } 410 411 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 412 { 413 Status = AE_TYPE; 414 goto UnlockAndExit; 415 } 416 417 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 418 if (!GpeRegisterInfo) 419 { 420 Status = AE_NOT_EXIST; 421 goto UnlockAndExit; 422 } 423 424 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 425 426 /* Perform the action */ 427 428 switch (Action) 429 { 430 case ACPI_GPE_ENABLE: 431 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 432 break; 433 434 case ACPI_GPE_DISABLE: 435 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 436 break; 437 438 default: 439 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); 440 Status = AE_BAD_PARAMETER; 441 break; 442 } 443 444 UnlockAndExit: 445 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 446 return_ACPI_STATUS (Status); 447 } 448 449 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) 450 451 452 /******************************************************************************* 453 * 454 * FUNCTION: AcpiClearGpe 455 * 456 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 457 * GpeNumber - GPE level within the GPE block 458 * 459 * RETURN: Status 460 * 461 * DESCRIPTION: Clear an ACPI event (general purpose) 462 * 463 ******************************************************************************/ 464 465 ACPI_STATUS 466 AcpiClearGpe ( 467 ACPI_HANDLE GpeDevice, 468 UINT32 GpeNumber) 469 { 470 ACPI_STATUS Status = AE_OK; 471 ACPI_GPE_EVENT_INFO *GpeEventInfo; 472 ACPI_CPU_FLAGS Flags; 473 474 475 ACPI_FUNCTION_TRACE (AcpiClearGpe); 476 477 478 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 479 480 /* Ensure that we have a valid GPE number */ 481 482 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 483 if (!GpeEventInfo) 484 { 485 Status = AE_BAD_PARAMETER; 486 goto UnlockAndExit; 487 } 488 489 Status = AcpiHwClearGpe (GpeEventInfo); 490 491 UnlockAndExit: 492 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 493 return_ACPI_STATUS (Status); 494 } 495 496 ACPI_EXPORT_SYMBOL (AcpiClearGpe) 497 498 499 /******************************************************************************* 500 * 501 * FUNCTION: AcpiGetGpeStatus 502 * 503 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 504 * GpeNumber - GPE level within the GPE block 505 * EventStatus - Where the current status of the event 506 * will be returned 507 * 508 * RETURN: Status 509 * 510 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 511 * 512 ******************************************************************************/ 513 514 ACPI_STATUS 515 AcpiGetGpeStatus ( 516 ACPI_HANDLE GpeDevice, 517 UINT32 GpeNumber, 518 ACPI_EVENT_STATUS *EventStatus) 519 { 520 ACPI_STATUS Status = AE_OK; 521 ACPI_GPE_EVENT_INFO *GpeEventInfo; 522 ACPI_CPU_FLAGS Flags; 523 524 525 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); 526 527 528 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 529 530 /* Ensure that we have a valid GPE number */ 531 532 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 533 if (!GpeEventInfo) 534 { 535 Status = AE_BAD_PARAMETER; 536 goto UnlockAndExit; 537 } 538 539 /* Obtain status on the requested GPE number */ 540 541 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); 542 543 UnlockAndExit: 544 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 545 return_ACPI_STATUS (Status); 546 } 547 548 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) 549 550 551 /******************************************************************************* 552 * 553 * FUNCTION: AcpiFinishGpe 554 * 555 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 556 * (NULL for FADT defined GPEs) 557 * GpeNumber - GPE level within the GPE block 558 * 559 * RETURN: Status 560 * 561 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE 562 * processing. Intended for use by asynchronous host-installed 563 * GPE handlers. The GPE is only reenabled if the EnableForRun bit 564 * is set in the GPE info. 565 * 566 ******************************************************************************/ 567 568 ACPI_STATUS 569 AcpiFinishGpe ( 570 ACPI_HANDLE GpeDevice, 571 UINT32 GpeNumber) 572 { 573 ACPI_GPE_EVENT_INFO *GpeEventInfo; 574 ACPI_STATUS Status; 575 ACPI_CPU_FLAGS Flags; 576 577 578 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 579 580 581 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 582 583 /* Ensure that we have a valid GPE number */ 584 585 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 586 if (!GpeEventInfo) 587 { 588 Status = AE_BAD_PARAMETER; 589 goto UnlockAndExit; 590 } 591 592 Status = AcpiEvFinishGpe (GpeEventInfo); 593 594 UnlockAndExit: 595 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 596 return_ACPI_STATUS (Status); 597 } 598 599 ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 600 601 602 /****************************************************************************** 603 * 604 * FUNCTION: AcpiDisableAllGpes 605 * 606 * PARAMETERS: None 607 * 608 * RETURN: Status 609 * 610 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 611 * 612 ******************************************************************************/ 613 614 ACPI_STATUS 615 AcpiDisableAllGpes ( 616 void) 617 { 618 ACPI_STATUS Status; 619 620 621 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 622 623 624 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 625 if (ACPI_FAILURE (Status)) 626 { 627 return_ACPI_STATUS (Status); 628 } 629 630 Status = AcpiHwDisableAllGpes (); 631 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 632 633 return_ACPI_STATUS (Status); 634 } 635 636 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 637 638 639 /****************************************************************************** 640 * 641 * FUNCTION: AcpiEnableAllRuntimeGpes 642 * 643 * PARAMETERS: None 644 * 645 * RETURN: Status 646 * 647 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 648 * 649 ******************************************************************************/ 650 651 ACPI_STATUS 652 AcpiEnableAllRuntimeGpes ( 653 void) 654 { 655 ACPI_STATUS Status; 656 657 658 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 659 660 661 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 662 if (ACPI_FAILURE (Status)) 663 { 664 return_ACPI_STATUS (Status); 665 } 666 667 Status = AcpiHwEnableAllRuntimeGpes (); 668 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 669 670 return_ACPI_STATUS (Status); 671 } 672 673 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 674 675 676 /******************************************************************************* 677 * 678 * FUNCTION: AcpiInstallGpeBlock 679 * 680 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 681 * GpeBlockAddress - Address and SpaceID 682 * RegisterCount - Number of GPE register pairs in the block 683 * InterruptNumber - H/W interrupt for the block 684 * 685 * RETURN: Status 686 * 687 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 688 * enabled here. 689 * 690 ******************************************************************************/ 691 692 ACPI_STATUS 693 AcpiInstallGpeBlock ( 694 ACPI_HANDLE GpeDevice, 695 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 696 UINT32 RegisterCount, 697 UINT32 InterruptNumber) 698 { 699 ACPI_STATUS Status; 700 ACPI_OPERAND_OBJECT *ObjDesc; 701 ACPI_NAMESPACE_NODE *Node; 702 ACPI_GPE_BLOCK_INFO *GpeBlock; 703 704 705 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 706 707 708 if ((!GpeDevice) || 709 (!GpeBlockAddress) || 710 (!RegisterCount)) 711 { 712 return_ACPI_STATUS (AE_BAD_PARAMETER); 713 } 714 715 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 716 if (ACPI_FAILURE (Status)) 717 { 718 return (Status); 719 } 720 721 Node = AcpiNsValidateHandle (GpeDevice); 722 if (!Node) 723 { 724 Status = AE_BAD_PARAMETER; 725 goto UnlockAndExit; 726 } 727 728 /* 729 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 730 * is always zero 731 */ 732 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount, 733 0, InterruptNumber, &GpeBlock); 734 if (ACPI_FAILURE (Status)) 735 { 736 goto UnlockAndExit; 737 } 738 739 /* Install block in the DeviceObject attached to the node */ 740 741 ObjDesc = AcpiNsGetAttachedObject (Node); 742 if (!ObjDesc) 743 { 744 /* 745 * No object, create a new one (Device nodes do not always have 746 * an attached object) 747 */ 748 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 749 if (!ObjDesc) 750 { 751 Status = AE_NO_MEMORY; 752 goto UnlockAndExit; 753 } 754 755 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 756 757 /* Remove local reference to the object */ 758 759 AcpiUtRemoveReference (ObjDesc); 760 if (ACPI_FAILURE (Status)) 761 { 762 goto UnlockAndExit; 763 } 764 } 765 766 /* Now install the GPE block in the DeviceObject */ 767 768 ObjDesc->Device.GpeBlock = GpeBlock; 769 770 771 UnlockAndExit: 772 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 773 return_ACPI_STATUS (Status); 774 } 775 776 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 777 778 779 /******************************************************************************* 780 * 781 * FUNCTION: AcpiRemoveGpeBlock 782 * 783 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 784 * 785 * RETURN: Status 786 * 787 * DESCRIPTION: Remove a previously installed block of GPE registers 788 * 789 ******************************************************************************/ 790 791 ACPI_STATUS 792 AcpiRemoveGpeBlock ( 793 ACPI_HANDLE GpeDevice) 794 { 795 ACPI_OPERAND_OBJECT *ObjDesc; 796 ACPI_STATUS Status; 797 ACPI_NAMESPACE_NODE *Node; 798 799 800 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 801 802 803 if (!GpeDevice) 804 { 805 return_ACPI_STATUS (AE_BAD_PARAMETER); 806 } 807 808 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 809 if (ACPI_FAILURE (Status)) 810 { 811 return (Status); 812 } 813 814 Node = AcpiNsValidateHandle (GpeDevice); 815 if (!Node) 816 { 817 Status = AE_BAD_PARAMETER; 818 goto UnlockAndExit; 819 } 820 821 /* Get the DeviceObject attached to the node */ 822 823 ObjDesc = AcpiNsGetAttachedObject (Node); 824 if (!ObjDesc || 825 !ObjDesc->Device.GpeBlock) 826 { 827 return_ACPI_STATUS (AE_NULL_OBJECT); 828 } 829 830 /* Delete the GPE block (but not the DeviceObject) */ 831 832 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 833 if (ACPI_SUCCESS (Status)) 834 { 835 ObjDesc->Device.GpeBlock = NULL; 836 } 837 838 UnlockAndExit: 839 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 840 return_ACPI_STATUS (Status); 841 } 842 843 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 844 845 846 /******************************************************************************* 847 * 848 * FUNCTION: AcpiGetGpeDevice 849 * 850 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 851 * GpeDevice - Where the parent GPE Device is returned 852 * 853 * RETURN: Status 854 * 855 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 856 * gpe device indicates that the gpe number is contained in one of 857 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 858 * 859 ******************************************************************************/ 860 861 ACPI_STATUS 862 AcpiGetGpeDevice ( 863 UINT32 Index, 864 ACPI_HANDLE *GpeDevice) 865 { 866 ACPI_GPE_DEVICE_INFO Info; 867 ACPI_STATUS Status; 868 869 870 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 871 872 873 if (!GpeDevice) 874 { 875 return_ACPI_STATUS (AE_BAD_PARAMETER); 876 } 877 878 if (Index >= AcpiCurrentGpeCount) 879 { 880 return_ACPI_STATUS (AE_NOT_EXIST); 881 } 882 883 /* Setup and walk the GPE list */ 884 885 Info.Index = Index; 886 Info.Status = AE_NOT_EXIST; 887 Info.GpeDevice = NULL; 888 Info.NextBlockBaseIndex = 0; 889 890 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 891 if (ACPI_FAILURE (Status)) 892 { 893 return_ACPI_STATUS (Status); 894 } 895 896 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 897 return_ACPI_STATUS (Info.Status); 898 } 899 900 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 901