evxfgpe.c revision 217365
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 <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/******************************************************************************* 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 78ACPI_STATUS 79AcpiUpdateAllGpes ( 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 105UnlockAndExit: 106 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 107 return_ACPI_STATUS (Status); 108} 109 110ACPI_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 127ACPI_STATUS 128AcpiEnableGpe ( 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 154ACPI_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 172ACPI_STATUS 173AcpiDisableGpe ( 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 199ACPI_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 222ACPI_STATUS 223AcpiSetGpe ( 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 264UnlockAndExit: 265 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 266 return_ACPI_STATUS (Status); 267} 268 269ACPI_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 291ACPI_STATUS 292AcpiSetupGpeForWake ( 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 /* Validate WakeDevice is of type Device */ 318 319 DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); 320 if (DeviceNode->Type != ACPI_TYPE_DEVICE) 321 { 322 return_ACPI_STATUS (AE_BAD_PARAMETER); 323 } 324 325 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 326 327 /* Ensure that we have a valid GPE number */ 328 329 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 330 if (GpeEventInfo) 331 { 332 /* 333 * If there is no method or handler for this GPE, then the 334 * WakeDevice will be notified whenever this GPE fires (aka 335 * "implicit notify") Note: The GPE is assumed to be 336 * level-triggered (for windows compatibility). 337 */ 338 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 339 ACPI_GPE_DISPATCH_NONE) 340 { 341 GpeEventInfo->Flags = 342 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); 343 GpeEventInfo->Dispatch.DeviceNode = DeviceNode; 344 } 345 346 GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; 347 Status = AE_OK; 348 } 349 350 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 351 return_ACPI_STATUS (Status); 352} 353 354ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) 355 356 357/******************************************************************************* 358 * 359 * FUNCTION: AcpiSetGpeWakeMask 360 * 361 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 362 * GpeNumber - GPE level within the GPE block 363 * Action - Enable or Disable 364 * 365 * RETURN: Status 366 * 367 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must 368 * already be marked as a WAKE GPE. 369 * 370 ******************************************************************************/ 371 372ACPI_STATUS 373AcpiSetGpeWakeMask ( 374 ACPI_HANDLE GpeDevice, 375 UINT32 GpeNumber, 376 UINT8 Action) 377{ 378 ACPI_STATUS Status = AE_OK; 379 ACPI_GPE_EVENT_INFO *GpeEventInfo; 380 ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 381 ACPI_CPU_FLAGS Flags; 382 UINT32 RegisterBit; 383 384 385 ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); 386 387 388 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 389 390 /* 391 * Ensure that we have a valid GPE number and that this GPE is in 392 * fact a wake GPE 393 */ 394 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 395 if (!GpeEventInfo) 396 { 397 Status = AE_BAD_PARAMETER; 398 goto UnlockAndExit; 399 } 400 401 if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) 402 { 403 Status = AE_TYPE; 404 goto UnlockAndExit; 405 } 406 407 GpeRegisterInfo = GpeEventInfo->RegisterInfo; 408 if (!GpeRegisterInfo) 409 { 410 Status = AE_NOT_EXIST; 411 goto UnlockAndExit; 412 } 413 414 RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); 415 416 /* Perform the action */ 417 418 switch (Action) 419 { 420 case ACPI_GPE_ENABLE: 421 ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 422 break; 423 424 case ACPI_GPE_DISABLE: 425 ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); 426 break; 427 428 default: 429 ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); 430 Status = AE_BAD_PARAMETER; 431 break; 432 } 433 434UnlockAndExit: 435 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 436 return_ACPI_STATUS (Status); 437} 438 439ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) 440 441 442/******************************************************************************* 443 * 444 * FUNCTION: AcpiClearGpe 445 * 446 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 447 * GpeNumber - GPE level within the GPE block 448 * 449 * RETURN: Status 450 * 451 * DESCRIPTION: Clear an ACPI event (general purpose) 452 * 453 ******************************************************************************/ 454 455ACPI_STATUS 456AcpiClearGpe ( 457 ACPI_HANDLE GpeDevice, 458 UINT32 GpeNumber) 459{ 460 ACPI_STATUS Status = AE_OK; 461 ACPI_GPE_EVENT_INFO *GpeEventInfo; 462 ACPI_CPU_FLAGS Flags; 463 464 465 ACPI_FUNCTION_TRACE (AcpiClearGpe); 466 467 468 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 469 470 /* Ensure that we have a valid GPE number */ 471 472 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 473 if (!GpeEventInfo) 474 { 475 Status = AE_BAD_PARAMETER; 476 goto UnlockAndExit; 477 } 478 479 Status = AcpiHwClearGpe (GpeEventInfo); 480 481UnlockAndExit: 482 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 483 return_ACPI_STATUS (Status); 484} 485 486ACPI_EXPORT_SYMBOL (AcpiClearGpe) 487 488 489/******************************************************************************* 490 * 491 * FUNCTION: AcpiGetGpeStatus 492 * 493 * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 494 * GpeNumber - GPE level within the GPE block 495 * EventStatus - Where the current status of the event 496 * will be returned 497 * 498 * RETURN: Status 499 * 500 * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) 501 * 502 ******************************************************************************/ 503 504ACPI_STATUS 505AcpiGetGpeStatus ( 506 ACPI_HANDLE GpeDevice, 507 UINT32 GpeNumber, 508 ACPI_EVENT_STATUS *EventStatus) 509{ 510 ACPI_STATUS Status = AE_OK; 511 ACPI_GPE_EVENT_INFO *GpeEventInfo; 512 ACPI_CPU_FLAGS Flags; 513 514 515 ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); 516 517 518 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 519 520 /* Ensure that we have a valid GPE number */ 521 522 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 523 if (!GpeEventInfo) 524 { 525 Status = AE_BAD_PARAMETER; 526 goto UnlockAndExit; 527 } 528 529 /* Obtain status on the requested GPE number */ 530 531 Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); 532 533UnlockAndExit: 534 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 535 return_ACPI_STATUS (Status); 536} 537 538ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) 539 540 541/******************************************************************************* 542 * 543 * FUNCTION: AcpiFinishGpe 544 * 545 * PARAMETERS: GpeDevice - Namespace node for the GPE Block 546 * (NULL for FADT defined GPEs) 547 * GpeNumber - GPE level within the GPE block 548 * 549 * RETURN: Status 550 * 551 * DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE 552 * processing. Intended for use by asynchronous host-installed 553 * GPE handlers. The GPE is only reenabled if the EnableForRun bit 554 * is set in the GPE info. 555 * 556 ******************************************************************************/ 557 558ACPI_STATUS 559AcpiFinishGpe ( 560 ACPI_HANDLE GpeDevice, 561 UINT32 GpeNumber) 562{ 563 ACPI_GPE_EVENT_INFO *GpeEventInfo; 564 ACPI_STATUS Status; 565 ACPI_CPU_FLAGS Flags; 566 567 568 ACPI_FUNCTION_TRACE (AcpiFinishGpe); 569 570 571 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 572 573 /* Ensure that we have a valid GPE number */ 574 575 GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); 576 if (!GpeEventInfo) 577 { 578 Status = AE_BAD_PARAMETER; 579 goto UnlockAndExit; 580 } 581 582 Status = AcpiEvFinishGpe (GpeEventInfo); 583 584UnlockAndExit: 585 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 586 return_ACPI_STATUS (Status); 587} 588 589ACPI_EXPORT_SYMBOL (AcpiFinishGpe) 590 591 592/****************************************************************************** 593 * 594 * FUNCTION: AcpiDisableAllGpes 595 * 596 * PARAMETERS: None 597 * 598 * RETURN: Status 599 * 600 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks 601 * 602 ******************************************************************************/ 603 604ACPI_STATUS 605AcpiDisableAllGpes ( 606 void) 607{ 608 ACPI_STATUS Status; 609 610 611 ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); 612 613 614 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 615 if (ACPI_FAILURE (Status)) 616 { 617 return_ACPI_STATUS (Status); 618 } 619 620 Status = AcpiHwDisableAllGpes (); 621 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 622 623 return_ACPI_STATUS (Status); 624} 625 626ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) 627 628 629/****************************************************************************** 630 * 631 * FUNCTION: AcpiEnableAllRuntimeGpes 632 * 633 * PARAMETERS: None 634 * 635 * RETURN: Status 636 * 637 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks 638 * 639 ******************************************************************************/ 640 641ACPI_STATUS 642AcpiEnableAllRuntimeGpes ( 643 void) 644{ 645 ACPI_STATUS Status; 646 647 648 ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); 649 650 651 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 652 if (ACPI_FAILURE (Status)) 653 { 654 return_ACPI_STATUS (Status); 655 } 656 657 Status = AcpiHwEnableAllRuntimeGpes (); 658 (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 659 660 return_ACPI_STATUS (Status); 661} 662 663ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) 664 665 666/******************************************************************************* 667 * 668 * FUNCTION: AcpiInstallGpeBlock 669 * 670 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 671 * GpeBlockAddress - Address and SpaceID 672 * RegisterCount - Number of GPE register pairs in the block 673 * InterruptNumber - H/W interrupt for the block 674 * 675 * RETURN: Status 676 * 677 * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not 678 * enabled here. 679 * 680 ******************************************************************************/ 681 682ACPI_STATUS 683AcpiInstallGpeBlock ( 684 ACPI_HANDLE GpeDevice, 685 ACPI_GENERIC_ADDRESS *GpeBlockAddress, 686 UINT32 RegisterCount, 687 UINT32 InterruptNumber) 688{ 689 ACPI_STATUS Status; 690 ACPI_OPERAND_OBJECT *ObjDesc; 691 ACPI_NAMESPACE_NODE *Node; 692 ACPI_GPE_BLOCK_INFO *GpeBlock; 693 694 695 ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); 696 697 698 if ((!GpeDevice) || 699 (!GpeBlockAddress) || 700 (!RegisterCount)) 701 { 702 return_ACPI_STATUS (AE_BAD_PARAMETER); 703 } 704 705 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 706 if (ACPI_FAILURE (Status)) 707 { 708 return (Status); 709 } 710 711 Node = AcpiNsValidateHandle (GpeDevice); 712 if (!Node) 713 { 714 Status = AE_BAD_PARAMETER; 715 goto UnlockAndExit; 716 } 717 718 /* 719 * For user-installed GPE Block Devices, the GpeBlockBaseNumber 720 * is always zero 721 */ 722 Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount, 723 0, InterruptNumber, &GpeBlock); 724 if (ACPI_FAILURE (Status)) 725 { 726 goto UnlockAndExit; 727 } 728 729 /* Install block in the DeviceObject attached to the node */ 730 731 ObjDesc = AcpiNsGetAttachedObject (Node); 732 if (!ObjDesc) 733 { 734 /* 735 * No object, create a new one (Device nodes do not always have 736 * an attached object) 737 */ 738 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); 739 if (!ObjDesc) 740 { 741 Status = AE_NO_MEMORY; 742 goto UnlockAndExit; 743 } 744 745 Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); 746 747 /* Remove local reference to the object */ 748 749 AcpiUtRemoveReference (ObjDesc); 750 if (ACPI_FAILURE (Status)) 751 { 752 goto UnlockAndExit; 753 } 754 } 755 756 /* Now install the GPE block in the DeviceObject */ 757 758 ObjDesc->Device.GpeBlock = GpeBlock; 759 760 761UnlockAndExit: 762 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 763 return_ACPI_STATUS (Status); 764} 765 766ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) 767 768 769/******************************************************************************* 770 * 771 * FUNCTION: AcpiRemoveGpeBlock 772 * 773 * PARAMETERS: GpeDevice - Handle to the parent GPE Block Device 774 * 775 * RETURN: Status 776 * 777 * DESCRIPTION: Remove a previously installed block of GPE registers 778 * 779 ******************************************************************************/ 780 781ACPI_STATUS 782AcpiRemoveGpeBlock ( 783 ACPI_HANDLE GpeDevice) 784{ 785 ACPI_OPERAND_OBJECT *ObjDesc; 786 ACPI_STATUS Status; 787 ACPI_NAMESPACE_NODE *Node; 788 789 790 ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); 791 792 793 if (!GpeDevice) 794 { 795 return_ACPI_STATUS (AE_BAD_PARAMETER); 796 } 797 798 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 799 if (ACPI_FAILURE (Status)) 800 { 801 return (Status); 802 } 803 804 Node = AcpiNsValidateHandle (GpeDevice); 805 if (!Node) 806 { 807 Status = AE_BAD_PARAMETER; 808 goto UnlockAndExit; 809 } 810 811 /* Get the DeviceObject attached to the node */ 812 813 ObjDesc = AcpiNsGetAttachedObject (Node); 814 if (!ObjDesc || 815 !ObjDesc->Device.GpeBlock) 816 { 817 return_ACPI_STATUS (AE_NULL_OBJECT); 818 } 819 820 /* Delete the GPE block (but not the DeviceObject) */ 821 822 Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); 823 if (ACPI_SUCCESS (Status)) 824 { 825 ObjDesc->Device.GpeBlock = NULL; 826 } 827 828UnlockAndExit: 829 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 830 return_ACPI_STATUS (Status); 831} 832 833ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) 834 835 836/******************************************************************************* 837 * 838 * FUNCTION: AcpiGetGpeDevice 839 * 840 * PARAMETERS: Index - System GPE index (0-CurrentGpeCount) 841 * GpeDevice - Where the parent GPE Device is returned 842 * 843 * RETURN: Status 844 * 845 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL 846 * gpe device indicates that the gpe number is contained in one of 847 * the FADT-defined gpe blocks. Otherwise, the GPE block device. 848 * 849 ******************************************************************************/ 850 851ACPI_STATUS 852AcpiGetGpeDevice ( 853 UINT32 Index, 854 ACPI_HANDLE *GpeDevice) 855{ 856 ACPI_GPE_DEVICE_INFO Info; 857 ACPI_STATUS Status; 858 859 860 ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); 861 862 863 if (!GpeDevice) 864 { 865 return_ACPI_STATUS (AE_BAD_PARAMETER); 866 } 867 868 if (Index >= AcpiCurrentGpeCount) 869 { 870 return_ACPI_STATUS (AE_NOT_EXIST); 871 } 872 873 /* Setup and walk the GPE list */ 874 875 Info.Index = Index; 876 Info.Status = AE_NOT_EXIST; 877 Info.GpeDevice = NULL; 878 Info.NextBlockBaseIndex = 0; 879 880 Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); 881 if (ACPI_FAILURE (Status)) 882 { 883 return_ACPI_STATUS (Status); 884 } 885 886 *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); 887 return_ACPI_STATUS (Info.Status); 888} 889 890ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) 891