1 /****************************************************************************** 2 * 3 * Module Name: evregion - Operation Region support 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 __EVREGION_C__ 46 47 #include "acpi.h" 48 #include "accommon.h" 49 #include "acevents.h" 50 #include "acnamesp.h" 51 #include "acinterp.h" 52 53 #define _COMPONENT ACPI_EVENTS 54 ACPI_MODULE_NAME ("evregion") 55 56 57 extern UINT8 AcpiGbl_DefaultAddressSpaces[]; 58 59 /* Local prototypes */ 60 61 static void 62 AcpiEvOrphanEcRegMethod ( 63 ACPI_NAMESPACE_NODE *EcDeviceNode); 64 65 static ACPI_STATUS 66 AcpiEvRegRun ( 67 ACPI_HANDLE ObjHandle, 68 UINT32 Level, 69 void *Context, 70 void **ReturnValue); 71 72 73 /******************************************************************************* 74 * 75 * FUNCTION: AcpiEvInitializeOpRegions 76 * 77 * PARAMETERS: None 78 * 79 * RETURN: Status 80 * 81 * DESCRIPTION: Execute _REG methods for all Operation Regions that have 82 * an installed default region handler. 83 * 84 ******************************************************************************/ 85 86 ACPI_STATUS 87 AcpiEvInitializeOpRegions ( 88 void) 89 { 90 ACPI_STATUS Status; 91 UINT32 i; 92 93 94 ACPI_FUNCTION_TRACE (EvInitializeOpRegions); 95 96 97 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 98 if (ACPI_FAILURE (Status)) 99 { 100 return_ACPI_STATUS (Status); 101 } 102 103 /* Run the _REG methods for OpRegions in each default address space */ 104 105 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 106 { 107 /* 108 * Make sure the installed handler is the DEFAULT handler. If not the 109 * default, the _REG methods will have already been run (when the 110 * handler was installed) 111 */ 112 if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode, 113 AcpiGbl_DefaultAddressSpaces[i])) 114 { 115 Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode, 116 AcpiGbl_DefaultAddressSpaces[i]); 117 } 118 } 119 120 AcpiGbl_RegMethodsExecuted = TRUE; 121 122 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 123 return_ACPI_STATUS (Status); 124 } 125 126 127 /******************************************************************************* 128 * 129 * FUNCTION: AcpiEvAddressSpaceDispatch 130 * 131 * PARAMETERS: RegionObj - Internal region object 132 * FieldObj - Corresponding field. Can be NULL. 133 * Function - Read or Write operation 134 * RegionOffset - Where in the region to read or write 135 * BitWidth - Field width in bits (8, 16, 32, or 64) 136 * Value - Pointer to in or out value, must be 137 * a full 64-bit integer 138 * 139 * RETURN: Status 140 * 141 * DESCRIPTION: Dispatch an address space or operation region access to 142 * a previously installed handler. 143 * 144 ******************************************************************************/ 145 146 ACPI_STATUS 147 AcpiEvAddressSpaceDispatch ( 148 ACPI_OPERAND_OBJECT *RegionObj, 149 ACPI_OPERAND_OBJECT *FieldObj, 150 UINT32 Function, 151 UINT32 RegionOffset, 152 UINT32 BitWidth, 153 UINT64 *Value) 154 { 155 ACPI_STATUS Status; 156 ACPI_ADR_SPACE_HANDLER Handler; 157 ACPI_ADR_SPACE_SETUP RegionSetup; 158 ACPI_OPERAND_OBJECT *HandlerDesc; 159 ACPI_OPERAND_OBJECT *RegionObj2; 160 void *RegionContext = NULL; 161 ACPI_CONNECTION_INFO *Context; 162 163 164 ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); 165 166 167 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 168 if (!RegionObj2) 169 { 170 return_ACPI_STATUS (AE_NOT_EXIST); 171 } 172 173 /* Ensure that there is a handler associated with this region */ 174 175 HandlerDesc = RegionObj->Region.Handler; 176 if (!HandlerDesc) 177 { 178 ACPI_ERROR ((AE_INFO, 179 "No handler for Region [%4.4s] (%p) [%s]", 180 AcpiUtGetNodeName (RegionObj->Region.Node), 181 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 182 183 return_ACPI_STATUS (AE_NOT_EXIST); 184 } 185 186 Context = HandlerDesc->AddressSpace.Context; 187 188 /* 189 * It may be the case that the region has never been initialized. 190 * Some types of regions require special init code 191 */ 192 if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 193 { 194 /* This region has not been initialized yet, do it */ 195 196 RegionSetup = HandlerDesc->AddressSpace.Setup; 197 if (!RegionSetup) 198 { 199 /* No initialization routine, exit with error */ 200 201 ACPI_ERROR ((AE_INFO, 202 "No init routine for region(%p) [%s]", 203 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 204 return_ACPI_STATUS (AE_NOT_EXIST); 205 } 206 207 /* 208 * We must exit the interpreter because the region setup will 209 * potentially execute control methods (for example, the _REG method 210 * for this region) 211 */ 212 AcpiExExitInterpreter (); 213 214 Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, 215 Context, &RegionContext); 216 217 /* Re-enter the interpreter */ 218 219 AcpiExEnterInterpreter (); 220 221 /* Check for failure of the Region Setup */ 222 223 if (ACPI_FAILURE (Status)) 224 { 225 ACPI_EXCEPTION ((AE_INFO, Status, 226 "During region initialization: [%s]", 227 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 228 return_ACPI_STATUS (Status); 229 } 230 231 /* Region initialization may have been completed by RegionSetup */ 232 233 if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 234 { 235 RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; 236 237 /* 238 * Save the returned context for use in all accesses to 239 * the handler for this particular region 240 */ 241 if (!(RegionObj2->Extra.RegionContext)) 242 { 243 RegionObj2->Extra.RegionContext = RegionContext; 244 } 245 } 246 } 247 248 /* We have everything we need, we can invoke the address space handler */ 249 250 Handler = HandlerDesc->AddressSpace.Handler; 251 252 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 253 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 254 &RegionObj->Region.Handler->AddressSpace, Handler, 255 ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset), 256 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 257 258 /* 259 * Special handling for GenericSerialBus and GeneralPurposeIo: 260 * There are three extra parameters that must be passed to the 261 * handler via the context: 262 * 1) Connection buffer, a resource template from Connection() op. 263 * 2) Length of the above buffer. 264 * 3) Actual access length from the AccessAs() op. 265 */ 266 if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) || 267 (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) && 268 Context && 269 FieldObj) 270 { 271 /* Get the Connection (ResourceTemplate) buffer */ 272 273 Context->Connection = FieldObj->Field.ResourceBuffer; 274 Context->Length = FieldObj->Field.ResourceLength; 275 Context->AccessLength = FieldObj->Field.AccessLength; 276 } 277 278 if (!(HandlerDesc->AddressSpace.HandlerFlags & 279 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 280 { 281 /* 282 * For handlers other than the default (supplied) handlers, we must 283 * exit the interpreter because the handler *might* block -- we don't 284 * know what it will do, so we can't hold the lock on the intepreter. 285 */ 286 AcpiExExitInterpreter(); 287 } 288 289 /* Call the handler */ 290 291 Status = Handler (Function, 292 (RegionObj->Region.Address + RegionOffset), BitWidth, Value, 293 Context, RegionObj2->Extra.RegionContext); 294 295 if (ACPI_FAILURE (Status)) 296 { 297 ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", 298 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 299 } 300 301 if (!(HandlerDesc->AddressSpace.HandlerFlags & 302 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 303 { 304 /* 305 * We just returned from a non-default handler, we must re-enter the 306 * interpreter 307 */ 308 AcpiExEnterInterpreter (); 309 } 310 311 return_ACPI_STATUS (Status); 312 } 313 314 315 /******************************************************************************* 316 * 317 * FUNCTION: AcpiEvDetachRegion 318 * 319 * PARAMETERS: RegionObj - Region Object 320 * AcpiNsIsLocked - Namespace Region Already Locked? 321 * 322 * RETURN: None 323 * 324 * DESCRIPTION: Break the association between the handler and the region 325 * this is a two way association. 326 * 327 ******************************************************************************/ 328 329 void 330 AcpiEvDetachRegion( 331 ACPI_OPERAND_OBJECT *RegionObj, 332 BOOLEAN AcpiNsIsLocked) 333 { 334 ACPI_OPERAND_OBJECT *HandlerObj; 335 ACPI_OPERAND_OBJECT *ObjDesc; 336 ACPI_OPERAND_OBJECT *StartDesc; 337 ACPI_OPERAND_OBJECT **LastObjPtr; 338 ACPI_ADR_SPACE_SETUP RegionSetup; 339 void **RegionContext; 340 ACPI_OPERAND_OBJECT *RegionObj2; 341 ACPI_STATUS Status; 342 343 344 ACPI_FUNCTION_TRACE (EvDetachRegion); 345 346 347 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 348 if (!RegionObj2) 349 { 350 return_VOID; 351 } 352 RegionContext = &RegionObj2->Extra.RegionContext; 353 354 /* Get the address handler from the region object */ 355 356 HandlerObj = RegionObj->Region.Handler; 357 if (!HandlerObj) 358 { 359 /* This region has no handler, all done */ 360 361 return_VOID; 362 } 363 364 /* Find this region in the handler's list */ 365 366 ObjDesc = HandlerObj->AddressSpace.RegionList; 367 StartDesc = ObjDesc; 368 LastObjPtr = &HandlerObj->AddressSpace.RegionList; 369 370 while (ObjDesc) 371 { 372 /* Is this the correct Region? */ 373 374 if (ObjDesc == RegionObj) 375 { 376 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 377 "Removing Region %p from address handler %p\n", 378 RegionObj, HandlerObj)); 379 380 /* This is it, remove it from the handler's list */ 381 382 *LastObjPtr = ObjDesc->Region.Next; 383 ObjDesc->Region.Next = NULL; /* Must clear field */ 384 385 if (AcpiNsIsLocked) 386 { 387 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 388 if (ACPI_FAILURE (Status)) 389 { 390 return_VOID; 391 } 392 } 393 394 /* Now stop region accesses by executing the _REG method */ 395 396 Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); 397 if (ACPI_FAILURE (Status)) 398 { 399 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", 400 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 401 } 402 403 if (AcpiNsIsLocked) 404 { 405 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 406 if (ACPI_FAILURE (Status)) 407 { 408 return_VOID; 409 } 410 } 411 412 /* 413 * If the region has been activated, call the setup handler with 414 * the deactivate notification 415 */ 416 if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 417 { 418 RegionSetup = HandlerObj->AddressSpace.Setup; 419 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, 420 HandlerObj->AddressSpace.Context, RegionContext); 421 422 /* 423 * RegionContext should have been released by the deactivate 424 * operation. We don't need access to it anymore here. 425 */ 426 if (RegionContext) 427 { 428 *RegionContext = NULL; 429 } 430 431 /* Init routine may fail, Just ignore errors */ 432 433 if (ACPI_FAILURE (Status)) 434 { 435 ACPI_EXCEPTION ((AE_INFO, Status, 436 "from region handler - deactivate, [%s]", 437 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 438 } 439 440 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 441 } 442 443 /* 444 * Remove handler reference in the region 445 * 446 * NOTE: this doesn't mean that the region goes away, the region 447 * is just inaccessible as indicated to the _REG method 448 * 449 * If the region is on the handler's list, this must be the 450 * region's handler 451 */ 452 RegionObj->Region.Handler = NULL; 453 AcpiUtRemoveReference (HandlerObj); 454 455 return_VOID; 456 } 457 458 /* Walk the linked list of handlers */ 459 460 LastObjPtr = &ObjDesc->Region.Next; 461 ObjDesc = ObjDesc->Region.Next; 462 463 /* Prevent infinite loop if list is corrupted */ 464 465 if (ObjDesc == StartDesc) 466 { 467 ACPI_ERROR ((AE_INFO, 468 "Circular handler list in region object %p", 469 RegionObj)); 470 return_VOID; 471 } 472 } 473 474 /* If we get here, the region was not in the handler's region list */ 475 476 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 477 "Cannot remove region %p from address handler %p\n", 478 RegionObj, HandlerObj)); 479 480 return_VOID; 481 } 482 483 484 /******************************************************************************* 485 * 486 * FUNCTION: AcpiEvAttachRegion 487 * 488 * PARAMETERS: HandlerObj - Handler Object 489 * RegionObj - Region Object 490 * AcpiNsIsLocked - Namespace Region Already Locked? 491 * 492 * RETURN: None 493 * 494 * DESCRIPTION: Create the association between the handler and the region 495 * this is a two way association. 496 * 497 ******************************************************************************/ 498 499 ACPI_STATUS 500 AcpiEvAttachRegion ( 501 ACPI_OPERAND_OBJECT *HandlerObj, 502 ACPI_OPERAND_OBJECT *RegionObj, 503 BOOLEAN AcpiNsIsLocked) 504 { 505 506 ACPI_FUNCTION_TRACE (EvAttachRegion); 507 508 509 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 510 "Adding Region [%4.4s] %p to address handler %p [%s]\n", 511 AcpiUtGetNodeName (RegionObj->Region.Node), 512 RegionObj, HandlerObj, 513 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 514 515 /* Link this region to the front of the handler's list */ 516 517 RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; 518 HandlerObj->AddressSpace.RegionList = RegionObj; 519 520 /* Install the region's handler */ 521 522 if (RegionObj->Region.Handler) 523 { 524 return_ACPI_STATUS (AE_ALREADY_EXISTS); 525 } 526 527 RegionObj->Region.Handler = HandlerObj; 528 AcpiUtAddReference (HandlerObj); 529 530 return_ACPI_STATUS (AE_OK); 531 } 532 533 534 /******************************************************************************* 535 * 536 * FUNCTION: AcpiEvExecuteRegMethod 537 * 538 * PARAMETERS: RegionObj - Region object 539 * Function - Passed to _REG: On (1) or Off (0) 540 * 541 * RETURN: Status 542 * 543 * DESCRIPTION: Execute _REG method for a region 544 * 545 ******************************************************************************/ 546 547 ACPI_STATUS 548 AcpiEvExecuteRegMethod ( 549 ACPI_OPERAND_OBJECT *RegionObj, 550 UINT32 Function) 551 { 552 ACPI_EVALUATE_INFO *Info; 553 ACPI_OPERAND_OBJECT *Args[3]; 554 ACPI_OPERAND_OBJECT *RegionObj2; 555 ACPI_STATUS Status; 556 557 558 ACPI_FUNCTION_TRACE (EvExecuteRegMethod); 559 560 561 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 562 if (!RegionObj2) 563 { 564 return_ACPI_STATUS (AE_NOT_EXIST); 565 } 566 567 if (RegionObj2->Extra.Method_REG == NULL) 568 { 569 return_ACPI_STATUS (AE_OK); 570 } 571 572 /* Allocate and initialize the evaluation information block */ 573 574 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 575 if (!Info) 576 { 577 return_ACPI_STATUS (AE_NO_MEMORY); 578 } 579 580 Info->PrefixNode = RegionObj2->Extra.Method_REG; 581 Info->RelativePathname = NULL; 582 Info->Parameters = Args; 583 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 584 585 /* 586 * The _REG method has two arguments: 587 * 588 * Arg0 - Integer: 589 * Operation region space ID Same value as RegionObj->Region.SpaceId 590 * 591 * Arg1 - Integer: 592 * connection status 1 for connecting the handler, 0 for disconnecting 593 * the handler (Passed as a parameter) 594 */ 595 Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); 596 if (!Args[0]) 597 { 598 Status = AE_NO_MEMORY; 599 goto Cleanup1; 600 } 601 602 Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); 603 if (!Args[1]) 604 { 605 Status = AE_NO_MEMORY; 606 goto Cleanup2; 607 } 608 609 Args[2] = NULL; /* Terminate list */ 610 611 /* Execute the method, no return value */ 612 613 ACPI_DEBUG_EXEC ( 614 AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); 615 616 Status = AcpiNsEvaluate (Info); 617 AcpiUtRemoveReference (Args[1]); 618 619 Cleanup2: 620 AcpiUtRemoveReference (Args[0]); 621 622 Cleanup1: 623 ACPI_FREE (Info); 624 return_ACPI_STATUS (Status); 625 } 626 627 628 /******************************************************************************* 629 * 630 * FUNCTION: AcpiEvExecuteRegMethods 631 * 632 * PARAMETERS: Node - Namespace node for the device 633 * SpaceId - The address space ID 634 * 635 * RETURN: Status 636 * 637 * DESCRIPTION: Run all _REG methods for the input Space ID; 638 * Note: assumes namespace is locked, or system init time. 639 * 640 ******************************************************************************/ 641 642 ACPI_STATUS 643 AcpiEvExecuteRegMethods ( 644 ACPI_NAMESPACE_NODE *Node, 645 ACPI_ADR_SPACE_TYPE SpaceId) 646 { 647 ACPI_STATUS Status; 648 649 650 ACPI_FUNCTION_TRACE (EvExecuteRegMethods); 651 652 653 /* 654 * Run all _REG methods for all Operation Regions for this space ID. This 655 * is a separate walk in order to handle any interdependencies between 656 * regions and _REG methods. (i.e. handlers must be installed for all 657 * regions of this Space ID before we can run any _REG methods) 658 */ 659 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 660 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, 661 &SpaceId, NULL); 662 663 /* Special case for EC: handle "orphan" _REG methods with no region */ 664 665 if (SpaceId == ACPI_ADR_SPACE_EC) 666 { 667 AcpiEvOrphanEcRegMethod (Node); 668 } 669 670 return_ACPI_STATUS (Status); 671 } 672 673 674 /******************************************************************************* 675 * 676 * FUNCTION: AcpiEvRegRun 677 * 678 * PARAMETERS: WalkNamespace callback 679 * 680 * DESCRIPTION: Run _REG method for region objects of the requested spaceID 681 * 682 ******************************************************************************/ 683 684 static ACPI_STATUS 685 AcpiEvRegRun ( 686 ACPI_HANDLE ObjHandle, 687 UINT32 Level, 688 void *Context, 689 void **ReturnValue) 690 { 691 ACPI_OPERAND_OBJECT *ObjDesc; 692 ACPI_NAMESPACE_NODE *Node; 693 ACPI_ADR_SPACE_TYPE SpaceId; 694 ACPI_STATUS Status; 695 696 697 SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); 698 699 /* Convert and validate the device handle */ 700 701 Node = AcpiNsValidateHandle (ObjHandle); 702 if (!Node) 703 { 704 return (AE_BAD_PARAMETER); 705 } 706 707 /* 708 * We only care about regions.and objects that are allowed to have address 709 * space handlers 710 */ 711 if ((Node->Type != ACPI_TYPE_REGION) && 712 (Node != AcpiGbl_RootNode)) 713 { 714 return (AE_OK); 715 } 716 717 /* Check for an existing internal object */ 718 719 ObjDesc = AcpiNsGetAttachedObject (Node); 720 if (!ObjDesc) 721 { 722 /* No object, just exit */ 723 724 return (AE_OK); 725 } 726 727 /* Object is a Region */ 728 729 if (ObjDesc->Region.SpaceId != SpaceId) 730 { 731 /* This region is for a different address space, just ignore it */ 732 733 return (AE_OK); 734 } 735 736 Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT); 737 return (Status); 738 } 739 740 741 /******************************************************************************* 742 * 743 * FUNCTION: AcpiEvOrphanEcRegMethod 744 * 745 * PARAMETERS: EcDeviceNode - Namespace node for an EC device 746 * 747 * RETURN: None 748 * 749 * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC 750 * device. This is a _REG method that has no corresponding region 751 * within the EC device scope. The orphan _REG method appears to 752 * have been enabled by the description of the ECDT in the ACPI 753 * specification: "The availability of the region space can be 754 * detected by providing a _REG method object underneath the 755 * Embedded Controller device." 756 * 757 * To quickly access the EC device, we use the EcDeviceNode used 758 * during EC handler installation. Otherwise, we would need to 759 * perform a time consuming namespace walk, executing _HID 760 * methods to find the EC device. 761 * 762 * MUTEX: Assumes the namespace is locked 763 * 764 ******************************************************************************/ 765 766 static void 767 AcpiEvOrphanEcRegMethod ( 768 ACPI_NAMESPACE_NODE *EcDeviceNode) 769 { 770 ACPI_HANDLE RegMethod; 771 ACPI_NAMESPACE_NODE *NextNode; 772 ACPI_STATUS Status; 773 ACPI_OBJECT_LIST Args; 774 ACPI_OBJECT Objects[2]; 775 776 777 ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); 778 779 780 if (!EcDeviceNode) 781 { 782 return_VOID; 783 } 784 785 /* Namespace is currently locked, must release */ 786 787 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 788 789 /* Get a handle to a _REG method immediately under the EC device */ 790 791 Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod); 792 if (ACPI_FAILURE (Status)) 793 { 794 goto Exit; /* There is no _REG method present */ 795 } 796 797 /* 798 * Execute the _REG method only if there is no Operation Region in 799 * this scope with the Embedded Controller space ID. Otherwise, it 800 * will already have been executed. Note, this allows for Regions 801 * with other space IDs to be present; but the code below will then 802 * execute the _REG method with the EmbeddedControl SpaceID argument. 803 */ 804 NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); 805 while (NextNode) 806 { 807 if ((NextNode->Type == ACPI_TYPE_REGION) && 808 (NextNode->Object) && 809 (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) 810 { 811 goto Exit; /* Do not execute the _REG */ 812 } 813 814 NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); 815 } 816 817 /* Evaluate the _REG(EmbeddedControl,Connect) method */ 818 819 Args.Count = 2; 820 Args.Pointer = Objects; 821 Objects[0].Type = ACPI_TYPE_INTEGER; 822 Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; 823 Objects[1].Type = ACPI_TYPE_INTEGER; 824 Objects[1].Integer.Value = ACPI_REG_CONNECT; 825 826 Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); 827 828 Exit: 829 /* We ignore all errors from above, don't care */ 830 831 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 832 return_VOID; 833 } 834