1 /****************************************************************************** 2 * 3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2014, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 *****************************************************************************/ 115 116 117 #define __EVXFGPE_C__ 118 #define EXPORT_ACPI_INTERFACES 119 120 #include "acpi.h" 121 #include "accommon.h" 122 #include "acevents.h" 123 #include "acnamesp.h" 124 125 #define _COMPONENT ACPI_EVENTS 126 ACPI_MODULE_NAME ("evxfgpe") 127 128 129 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */ 130 /******************************************************************************* 131 * 132 * FUNCTION: AcpiUpdateAllGpes 133 * 134 * PARAMETERS: None 135 * 136 * RETURN: Status 137 * 138 * DESCRIPTION: Complete GPE initialization and enable all GPEs that have 139 * associated _Lxx or _Exx methods and are not pointed to by any 140 * device _PRW methods (this indicates that these GPEs are 141 * generally intended for system or device wakeup. Such GPEs 142 * have to be enabled directly when the devices whose _PRW 143 * methods point to them are set up for wakeup signaling.) 144 * 145 * NOTE: Should be called after any GPEs are added to the system. Primarily, 146 * after the system _PRW methods have been run, but also after a GPE Block 147 * Device has been added or if any new GPE methods have been added via a 148 * dynamic table load. 149 * 150 ******************************************************************************/ 151 152 ACPI_STATUS 153 AcpiUpdateAllGpes ( 154 void) 155 { 156 ACPI_STATUS Status; 157 158 159 ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes); 160 161 162 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 163 if (ACPI_FAILURE (Status)) 164 { 165 return_ACPI_STATUS (Status); 166 } 167 168 if (AcpiGbl_AllGpesInitialized) 169 { 170 goto UnlockAndExit; 171 } 172 173 Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL); 174 if (ACPI_SUCCESS (Status)) 175 { 176 AcpiGbl_AllGpesInitialized = TRUE; 177 } 178 179 UnlockAndExit: 180 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 181 return_ACPI_STATUS (Status); 182 } 183 184 ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes) 185 186 187 /******************************************************************************* 188 * 189 * FUNCTION: AcpiEnableGpe 190 * 191 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 192 * GpeNumber - GPE level within the GPE block 193 * 194 * RETURN: Status 195 * 196 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is 197 * hardware-enabled. 198 * 199 ******************************************************************************/ 200 201 ACPI_STATUS 202 AcpiEnableGpe ( 203 ACPI_HANDLE GpeDevice, 204 UINT32 GpeNumber) 205 { 206 ACPI_STATUS Status = AE_BAD_PARAMETER; 207 ACPI_GPE_EVENT_INFO *GpeEventInfo; 208 ACPI_CPU_FLAGS Flags; 209 210 211 ACPI_FUNCTION_TRACE (AcpiEnableGpe); 212 213 214 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 215 216 /* 217 * Ensure that we have a valid GPE number and that there is some way 218 * of handling the GPE (handler or a GPE method). In other words, we 219 * won't allow a valid GPE to be enabled if there is no way to handle it. 220 */ 221 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 222 if (GpeEventInfo) 223 { 224 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != 225 ACPI_GPE_DISPATCH_NONE) 226 { 227 Status = AcpiEvAddGpeReference (GpeEventInfo); 228 } 229 else 230 { 231 Status = AE_NO_HANDLER; 232 } 233 } 234 235 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 236 return_ACPI_STATUS (Status); 237 } 238 239 ACPI_EXPORT_SYMBOL (AcpiEnableGpe) 240 241 242 /******************************************************************************* 243 * 244 * FUNCTION: AcpiDisableGpe 245 * 246 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 247 * GpeNumber - GPE level within the GPE block 248 * 249 * RETURN: Status 250 * 251 * DESCRIPTION: Remove a reference to a GPE. When the last reference is 252 * removed, only then is the GPE disabled (for runtime GPEs), or 253 * the GPE mask bit disabled (for wake GPEs) 254 * 255 ******************************************************************************/ 256 257 ACPI_STATUS 258 AcpiDisableGpe ( 259 ACPI_HANDLE GpeDevice, 260 UINT32 GpeNumber) 261 { 262 ACPI_STATUS Status = AE_BAD_PARAMETER; 263 ACPI_GPE_EVENT_INFO *GpeEventInfo; 264 ACPI_CPU_FLAGS Flags; 265 266 267 ACPI_FUNCTION_TRACE (AcpiDisableGpe); 268 269 270 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 271 272 /* Ensure that we have a valid GPE number */ 273 274 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 275 if (GpeEventInfo) 276 { 277 Status = AcpiEvRemoveGpeReference (GpeEventInfo); 278 } 279 280 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 281 return_ACPI_STATUS (Status); 282 } 283 284 ACPI_EXPORT_SYMBOL (AcpiDisableGpe) 285 286 287 /******************************************************************************* 288 * 289 * FUNCTION: AcpiSetGpe 290 * 291 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 292 * GpeNumber - GPE level within the GPE block 293 * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE 294 * 295 * RETURN: Status 296 * 297 * DESCRIPTION: Enable or disable an individual GPE. This function bypasses 298 * the reference count mechanism used in the AcpiEnableGpe and 299 * AcpiDisableGpe interfaces -- and should be used with care. 300 * 301 * Note: Typically used to disable a runtime GPE for short period of time, 302 * then re-enable it, without disturbing the existing reference counts. This 303 * is useful, for example, in the Embedded Controller (EC) driver. 304 * 305 ******************************************************************************/ 306 307 ACPI_STATUS 308 AcpiSetGpe ( 309 ACPI_HANDLE GpeDevice, 310 UINT32 GpeNumber, 311 UINT8 Action) 312 { 313 ACPI_GPE_EVENT_INFO *GpeEventInfo; 314 ACPI_STATUS Status; 315 ACPI_CPU_FLAGS Flags; 316 317 318 ACPI_FUNCTION_TRACE (AcpiSetGpe); 319 320 321 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 322 323 /* Ensure that we have a valid GPE number */ 324 325 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 326 if (!GpeEventInfo) 327 { 328 Status = AE_BAD_PARAMETER; 329 goto UnlockAndExit; 330 } 331 332 /* Perform the action */ 333 334 switch (Action) 335 { 336 case ACPI_GPE_ENABLE: 337 338 Status = AcpiEvEnableGpe (GpeEventInfo); 339 break; 340 341 case ACPI_GPE_DISABLE: 342 343 Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); 344 break; 345 346 default: 347 348 Status = AE_BAD_PARAMETER; 349 break; 350 } 351 352 UnlockAndExit: 353 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 354 return_ACPI_STATUS (Status); 355 } 356 357 ACPI_EXPORT_SYMBOL (AcpiSetGpe) 358 359 360 /******************************************************************************* 361 * 362 * FUNCTION: AcpiMarkGpeForWake 363 * 364 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 365 * GpeNumber - GPE level within the GPE block 366 * 367 * RETURN: Status 368 * 369 * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply 370 * sets the ACPI_GPE_CAN_WAKE flag. 371 * 372 * Some potential callers of AcpiSetupGpeForWake may know in advance that 373 * there won't be any notify handlers installed for device wake notifications 374 * from the given GPE (one example is a button GPE in Linux). For these cases, 375 * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake. 376 * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to 377 * setup implicit wake notification for it (since there's no handler method). 378 * 379 ******************************************************************************/ 380 381 ACPI_STATUS 382 AcpiMarkGpeForWake ( 383 ACPI_HANDLE GpeDevice, 384 UINT32 GpeNumber) 385 { 386 ACPI_GPE_EVENT_INFO *GpeEventInfo; 387 ACPI_STATUS Status = AE_BAD_PARAMETER; 388 ACPI_CPU_FLAGS Flags; 389 390 391 ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake); 392 393 394 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 395 396 /* Ensure that we have a valid GPE number */ 397 398 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 399 if (GpeEventInfo) 400 { 401 /* Mark the GPE as a possible wake event */ 402 403 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 404 Status = AE_OK; 405 } 406 407 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 408 return_ACPI_STATUS (Status); 409 } 410 411 ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake) 412 413 414 /******************************************************************************* 415 * 416 * FUNCTION: AcpiSetupGpeForWake 417 * 418 * PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW) 419 * GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 420 * GpeNumber - GPE level within the GPE block 421 * 422 * RETURN: Status 423 * 424 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This 425 * interface is intended to be used as the host executes the 426 * _PRW methods (Power Resources for Wake) in the system tables. 427 * Each _PRW appears under a Device Object (The WakeDevice), and 428 * contains the info for the wake GPE associated with the 429 * WakeDevice. 430 * 431 ******************************************************************************/ 432 433 ACPI_STATUS 434 AcpiSetupGpeForWake ( 435 ACPI_HANDLE WakeDevice, 436 ACPI_HANDLE GpeDevice, 437 UINT32 GpeNumber) 438 { 439 ACPI_STATUS Status; 440 ACPI_GPE_EVENT_INFO *GpeEventInfo; 441 ACPI_NAMESPACE_NODE *DeviceNode; 442 ACPI_GPE_NOTIFY_INFO *Notify; 443 ACPI_GPE_NOTIFY_INFO *NewNotify; 444 ACPI_CPU_FLAGS Flags; 445 446 447 ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake); 448 449 450 /* Parameter Validation */ 451 452 if (!WakeDevice) 453 { 454 /* 455 * By forcing WakeDevice to be valid, we automatically enable the 456 * implicit notify feature on all hosts. 457 */ 458 return_ACPI_STATUS (AE_BAD_PARAMETER); 459 } 460 461 /* Handle root object case */ 462 463 if (WakeDevice == ACPI_ROOT_OBJECT) 464 { 465 DeviceNode = AcpiGbl_RootNode; 466 } 467 else 468 { 469 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); 470 } 471 472 /* Validate WakeDevice is of type Device */ 473 474 if (DeviceNode->Type != ACPI_TYPE_DEVICE) 475 { 476 return_ACPI_STATUS (AE_BAD_PARAMETER); 477 } 478 479 /* 480 * Allocate a new notify object up front, in case it is needed. 481 * Memory allocation while holding a spinlock is a big no-no 482 * on some hosts. 483 */ 484 NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); 485 if (!NewNotify) 486 { 487 return_ACPI_STATUS (AE_NO_MEMORY); 488 } 489 490 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 491 492 /* Ensure that we have a valid GPE number */ 493 494 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 495 if (!GpeEventInfo) 496 { 497 Status = AE_BAD_PARAMETER; 498 goto UnlockAndExit; 499 } 500 501 /* 502 * If there is no method or handler for this GPE, then the 503 * WakeDevice will be notified whenever this GPE fires. This is 504 * known as an "implicit notify". Note: The GPE is assumed to be 505 * level-triggered (for windows compatibility). 506 */ 507 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 508 ACPI_GPE_DISPATCH_NONE) 509 { 510 /* 511 * This is the first device for implicit notify on this GPE. 512 * Just set the flags here, and enter the NOTIFY block below. 513 */ 514 GpeEventInfo->Flags = 515 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 516 } 517 518 /* 519 * If we already have an implicit notify on this GPE, add 520 * this device to the notify list. 521 */ 522 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 523 ACPI_GPE_DISPATCH_NOTIFY) 524 { 525 /* Ensure that the device is not already in the list */ 526 527 Notify = GpeEventInfo->Dispatch.NotifyList; 528 while (Notify) 529 { 530 if (Notify->DeviceNode == DeviceNode) 531 { 532 Status = AE_ALREADY_EXISTS; 533 goto UnlockAndExit; 534 } 535 Notify = Notify->Next; 536 } 537 538 /* Add this device to the notify list for this GPE */ 539 540 NewNotify->DeviceNode = DeviceNode; 541 NewNotify->Next = GpeEventInfo->Dispatch.NotifyList; 542 GpeEventInfo->Dispatch.NotifyList = NewNotify; 543 NewNotify = NULL; 544 } 545 546 /* Mark the GPE as a possible wake event */ 547 548 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 549 Status = AE_OK; 550 551 552 UnlockAndExit: 553 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 554 555 /* Delete the notify object if it was not used above */ 556 557 if (NewNotify) 558 { 559 ACPI_FREE (NewNotify); 560 } 561 return_ACPI_STATUS (Status); 562 } 563 564 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) 565 566 567 /******************************************************************************* 568 * 569 * FUNCTION: AcpiSetGpeWakeMask 570 * 571 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 572 * GpeNumber - GPE level within the GPE block 573 * Action - Enable or Disable 574 * 575 * RETURN: Status 576 * 577 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 578 * already be marked as a WAKE GPE. 579 * 580 ******************************************************************************/ 581 582 ACPI_STATUS 583 AcpiSetGpeWakeMask ( 584 ACPI_HANDLE GpeDevice, 585 UINT32 GpeNumber, 586 UINT8 Action) 587 { 588 ACPI_STATUS Status = AE_OK; 589 ACPI_GPE_EVENT_INFO *GpeEventInfo; 590 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 591 ACPI_CPU_FLAGS Flags; 592 UINT32 RegisterBit; 593 594 595 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); 596 597 598 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 599 600 /* 601 * Ensure that we have a valid GPE number and that this GPE is in 602 * fact a wake GPE 603 */ 604 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 605 if (!GpeEventInfo) 606 { 607 Status = AE_BAD_PARAMETER; 608 goto UnlockAndExit; 609 } 610 611 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 612 { 613 Status = AE_TYPE; 614 goto UnlockAndExit; 615 } 616 617 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 618 if (!GpeRegisterInfo) 619 { 620 Status = AE_NOT_EXIST; 621 goto UnlockAndExit; 622 } 623 624 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); 625 626 /* Perform the action */ 627 628 switch (Action) 629 { 630 case ACPI_GPE_ENABLE: 631 632 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 633 break; 634 635 case ACPI_GPE_DISABLE: 636 637 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 638 break; 639 640 default: 641 642 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); 643 Status = AE_BAD_PARAMETER; 644 break; 645 } 646 647 UnlockAndExit: 648 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 649 return_ACPI_STATUS (Status); 650 } 651 652 ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) 653 654 655 /******************************************************************************* 656 * 657 * FUNCTION: AcpiClearGpe 658 * 659 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 660 * GpeNumber - GPE level within the GPE block 661 * 662 * RETURN: Status 663 * 664 * DESCRIPTION: Clear an ACPI event (general purpose) 665 * 666 ******************************************************************************/ 667 668 ACPI_STATUS 669 AcpiClearGpe ( 670 ACPI_HANDLE GpeDevice, 671 UINT32 GpeNumber) 672 { 673 ACPI_STATUS Status = AE_OK; 674 ACPI_GPE_EVENT_INFO *GpeEventInfo; 675 ACPI_CPU_FLAGS Flags; 676 677 678 ACPI_FUNCTION_TRACE (AcpiClearGpe); 679 680 681 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 682 683 /* Ensure that we have a valid GPE number */ 684 685 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 686 if (!GpeEventInfo) 687 { 688 Status = AE_BAD_PARAMETER; 689 goto UnlockAndExit; 690 } 691 692 Status = AcpiHwClearGpe (GpeEventInfo); 693 694 UnlockAndExit: 695 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 696 return_ACPI_STATUS (Status); 697 } 698 699 ACPI_EXPORT_SYMBOL (AcpiClearGpe) 700 701 702 /******************************************************************************* 703 * 704 * FUNCTION: AcpiGetGpeStatus 705 * 706 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 707 * GpeNumber - GPE level within the GPE block 708 * EventStatus - Where the current status of the event 709 * will be returned 710 * 711 * RETURN: Status 712 * 713 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 714 * 715 ******************************************************************************/ 716 717 ACPI_STATUS 718 AcpiGetGpeStatus ( 719 ACPI_HANDLE GpeDevice, 720 UINT32 GpeNumber, 721 ACPI_EVENT_STATUS *EventStatus) 722 { 723 ACPI_STATUS Status = AE_OK; 724 ACPI_GPE_EVENT_INFO *GpeEventInfo; 725 ACPI_CPU_FLAGS Flags; 726 727 728 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); 729 730 731 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 732 733 /* Ensure that we have a valid GPE number */ 734 735 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 736 if (!GpeEventInfo) 737 { 738 Status = AE_BAD_PARAMETER; 739 goto UnlockAndExit; 740 } 741 742 /* Obtain status on the requested GPE number */ 743 744 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); 745 746 UnlockAndExit: 747 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 748 return_ACPI_STATUS (Status); 749 } 750 751 ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) 752 753 754 /******************************************************************************* 755 * 756 * FUNCTION: AcpiFinishGpe 757 * 758 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 759 * (NULL for FADT defined GPEs) 760 * GpeNumber - GPE level within the GPE block 761 * 762 * RETURN: Status 763 * 764 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE 765 * processing. Intended for use by asynchronous host-installed 766 * GPE handlers. The GPE is only reenabled if the EnableForRun bit 767 * is set in the GPE info. 768 * 769 ******************************************************************************/ 770 771 ACPI_STATUS 772 AcpiFinishGpe ( 773 ACPI_HANDLE GpeDevice, 774 UINT32 GpeNumber) 775 { 776 ACPI_GPE_EVENT_INFO *GpeEventInfo; 777 ACPI_STATUS Status; 778 ACPI_CPU_FLAGS Flags; 779 780 781 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 782 783 784 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 785 786 /* Ensure that we have a valid GPE number */ 787 788 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 789 if (!GpeEventInfo) 790 { 791 Status = AE_BAD_PARAMETER; 792 goto UnlockAndExit; 793 } 794 795 Status = AcpiEvFinishGpe (GpeEventInfo); 796 797 UnlockAndExit: 798 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 799 return_ACPI_STATUS (Status); 800 } 801 802 ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 803 804 805 /****************************************************************************** 806 * 807 * FUNCTION: AcpiDisableAllGpes 808 * 809 * PARAMETERS: None 810 * 811 * RETURN: Status 812 * 813 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 814 * 815 ******************************************************************************/ 816 817 ACPI_STATUS 818 AcpiDisableAllGpes ( 819 void) 820 { 821 ACPI_STATUS Status; 822 823 824 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 825 826 827 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 828 if (ACPI_FAILURE (Status)) 829 { 830 return_ACPI_STATUS (Status); 831 } 832 833 Status = AcpiHwDisableAllGpes (); 834 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 835 836 return_ACPI_STATUS (Status); 837 } 838 839 ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 840 841 842 /****************************************************************************** 843 * 844 * FUNCTION: AcpiEnableAllRuntimeGpes 845 * 846 * PARAMETERS: None 847 * 848 * RETURN: Status 849 * 850 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 851 * 852 ******************************************************************************/ 853 854 ACPI_STATUS 855 AcpiEnableAllRuntimeGpes ( 856 void) 857 { 858 ACPI_STATUS Status; 859 860 861 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 862 863 864 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 865 if (ACPI_FAILURE (Status)) 866 { 867 return_ACPI_STATUS (Status); 868 } 869 870 Status = AcpiHwEnableAllRuntimeGpes (); 871 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 872 873 return_ACPI_STATUS (Status); 874 } 875 876 ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 877 878 879 /******************************************************************************* 880 * 881 * FUNCTION: AcpiInstallGpeBlock 882 * 883 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 884 * GpeBlockAddress - Address and SpaceID 885 * RegisterCount - Number of GPE register pairs in the block 886 * InterruptNumber - H/W interrupt for the block 887 * 888 * RETURN: Status 889 * 890 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 891 * enabled here. 892 * 893 ******************************************************************************/ 894 895 ACPI_STATUS 896 AcpiInstallGpeBlock ( 897 ACPI_HANDLE GpeDevice, 898 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 899 UINT32 RegisterCount, 900 UINT32 InterruptNumber) 901 { 902 ACPI_STATUS Status; 903 ACPI_OPERAND_OBJECT *ObjDesc; 904 ACPI_NAMESPACE_NODE *Node; 905 ACPI_GPE_BLOCK_INFO *GpeBlock; 906 907 908 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 909 910 911 if ((!GpeDevice) || 912 (!GpeBlockAddress) || 913 (!RegisterCount)) 914 { 915 return_ACPI_STATUS (AE_BAD_PARAMETER); 916 } 917 918 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 919 if (ACPI_FAILURE (Status)) 920 { 921 return_ACPI_STATUS (Status); 922 } 923 924 Node = AcpiNsValidateHandle (GpeDevice); 925 if (!Node) 926 { 927 Status = AE_BAD_PARAMETER; 928 goto UnlockAndExit; 929 } 930 931 /* Validate the parent device */ 932 933 if (Node->Type != ACPI_TYPE_DEVICE) 934 { 935 Status = AE_TYPE; 936 goto UnlockAndExit; 937 } 938 939 if (Node->Object) 940 { 941 Status = AE_ALREADY_EXISTS; 942 goto UnlockAndExit; 943 } 944 945 /* 946 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 947 * is always zero 948 */ 949 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, 950 GpeBlockAddress->SpaceId, RegisterCount, 951 0, InterruptNumber, &GpeBlock); 952 if (ACPI_FAILURE (Status)) 953 { 954 goto UnlockAndExit; 955 } 956 957 /* Install block in the DeviceObject attached to the node */ 958 959 ObjDesc = AcpiNsGetAttachedObject (Node); 960 if (!ObjDesc) 961 { 962 /* 963 * No object, create a new one (Device nodes do not always have 964 * an attached object) 965 */ 966 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 967 if (!ObjDesc) 968 { 969 Status = AE_NO_MEMORY; 970 goto UnlockAndExit; 971 } 972 973 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 974 975 /* Remove local reference to the object */ 976 977 AcpiUtRemoveReference (ObjDesc); 978 if (ACPI_FAILURE (Status)) 979 { 980 goto UnlockAndExit; 981 } 982 } 983 984 /* Now install the GPE block in the DeviceObject */ 985 986 ObjDesc->Device.GpeBlock = GpeBlock; 987 988 989 UnlockAndExit: 990 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 991 return_ACPI_STATUS (Status); 992 } 993 994 ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 995 996 997 /******************************************************************************* 998 * 999 * FUNCTION: AcpiRemoveGpeBlock 1000 * 1001 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 1002 * 1003 * RETURN: Status 1004 * 1005 * DESCRIPTION: Remove a previously installed block of GPE registers 1006 * 1007 ******************************************************************************/ 1008 1009 ACPI_STATUS 1010 AcpiRemoveGpeBlock ( 1011 ACPI_HANDLE GpeDevice) 1012 { 1013 ACPI_OPERAND_OBJECT *ObjDesc; 1014 ACPI_STATUS Status; 1015 ACPI_NAMESPACE_NODE *Node; 1016 1017 1018 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 1019 1020 1021 if (!GpeDevice) 1022 { 1023 return_ACPI_STATUS (AE_BAD_PARAMETER); 1024 } 1025 1026 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 1027 if (ACPI_FAILURE (Status)) 1028 { 1029 return_ACPI_STATUS (Status); 1030 } 1031 1032 Node = AcpiNsValidateHandle (GpeDevice); 1033 if (!Node) 1034 { 1035 Status = AE_BAD_PARAMETER; 1036 goto UnlockAndExit; 1037 } 1038 1039 /* Validate the parent device */ 1040 1041 if (Node->Type != ACPI_TYPE_DEVICE) 1042 { 1043 Status = AE_TYPE; 1044 goto UnlockAndExit; 1045 } 1046 1047 /* Get the DeviceObject attached to the node */ 1048 1049 ObjDesc = AcpiNsGetAttachedObject (Node); 1050 if (!ObjDesc || 1051 !ObjDesc->Device.GpeBlock) 1052 { 1053 return_ACPI_STATUS (AE_NULL_OBJECT); 1054 } 1055 1056 /* Delete the GPE block (but not the DeviceObject) */ 1057 1058 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 1059 if (ACPI_SUCCESS (Status)) 1060 { 1061 ObjDesc->Device.GpeBlock = NULL; 1062 } 1063 1064 UnlockAndExit: 1065 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1066 return_ACPI_STATUS (Status); 1067 } 1068 1069 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 1070 1071 1072 /******************************************************************************* 1073 * 1074 * FUNCTION: AcpiGetGpeDevice 1075 * 1076 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 1077 * GpeDevice - Where the parent GPE Device is returned 1078 * 1079 * RETURN: Status 1080 * 1081 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 1082 * gpe device indicates that the gpe number is contained in one of 1083 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 1084 * 1085 ******************************************************************************/ 1086 1087 ACPI_STATUS 1088 AcpiGetGpeDevice ( 1089 UINT32 Index, 1090 ACPI_HANDLE *GpeDevice) 1091 { 1092 ACPI_GPE_DEVICE_INFO Info; 1093 ACPI_STATUS Status; 1094 1095 1096 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 1097 1098 1099 if (!GpeDevice) 1100 { 1101 return_ACPI_STATUS (AE_BAD_PARAMETER); 1102 } 1103 1104 if (Index >= AcpiCurrentGpeCount) 1105 { 1106 return_ACPI_STATUS (AE_NOT_EXIST); 1107 } 1108 1109 /* Setup and walk the GPE list */ 1110 1111 Info.Index = Index; 1112 Info.Status = AE_NOT_EXIST; 1113 Info.GpeDevice = NULL; 1114 Info.NextBlockBaseIndex = 0; 1115 1116 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 1117 if (ACPI_FAILURE (Status)) 1118 { 1119 return_ACPI_STATUS (Status); 1120 } 1121 1122 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 1123 return_ACPI_STATUS (Info.Status); 1124 } 1125 1126 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 1127 1128 #endif /* !ACPI_REDUCED_HARDWARE */ 1129