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