1 /****************************************************************************** 2 * 3 * Module Name: evregion - Operation Region support 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, 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 **LastObjPtr; 337 ACPI_ADR_SPACE_SETUP RegionSetup; 338 void **RegionContext; 339 ACPI_OPERAND_OBJECT *RegionObj2; 340 ACPI_STATUS Status; 341 342 343 ACPI_FUNCTION_TRACE (EvDetachRegion); 344 345 346 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 347 if (!RegionObj2) 348 { 349 return_VOID; 350 } 351 RegionContext = &RegionObj2->Extra.RegionContext; 352 353 /* Get the address handler from the region object */ 354 355 HandlerObj = RegionObj->Region.Handler; 356 if (!HandlerObj) 357 { 358 /* This region has no handler, all done */ 359 360 return_VOID; 361 } 362 363 /* Find this region in the handler's list */ 364 365 ObjDesc = HandlerObj->AddressSpace.RegionList; 366 LastObjPtr = &HandlerObj->AddressSpace.RegionList; 367 368 while (ObjDesc) 369 { 370 /* Is this the correct Region? */ 371 372 if (ObjDesc == RegionObj) 373 { 374 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 375 "Removing Region %p from address handler %p\n", 376 RegionObj, HandlerObj)); 377 378 /* This is it, remove it from the handler's list */ 379 380 *LastObjPtr = ObjDesc->Region.Next; 381 ObjDesc->Region.Next = NULL; /* Must clear field */ 382 383 if (AcpiNsIsLocked) 384 { 385 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 386 if (ACPI_FAILURE (Status)) 387 { 388 return_VOID; 389 } 390 } 391 392 /* Now stop region accesses by executing the _REG method */ 393 394 Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); 395 if (ACPI_FAILURE (Status)) 396 { 397 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", 398 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 399 } 400 401 if (AcpiNsIsLocked) 402 { 403 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 404 if (ACPI_FAILURE (Status)) 405 { 406 return_VOID; 407 } 408 } 409 410 /* 411 * If the region has been activated, call the setup handler with 412 * the deactivate notification 413 */ 414 if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 415 { 416 RegionSetup = HandlerObj->AddressSpace.Setup; 417 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, 418 HandlerObj->AddressSpace.Context, RegionContext); 419 420 /* 421 * RegionContext should have been released by the deactivate 422 * operation. We don't need access to it anymore here. 423 */ 424 if (RegionContext) 425 { 426 *RegionContext = NULL; 427 } 428 429 /* Init routine may fail, Just ignore errors */ 430 431 if (ACPI_FAILURE (Status)) 432 { 433 ACPI_EXCEPTION ((AE_INFO, Status, 434 "from region handler - deactivate, [%s]", 435 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 436 } 437 438 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 439 } 440 441 /* 442 * Remove handler reference in the region 443 * 444 * NOTE: this doesn't mean that the region goes away, the region 445 * is just inaccessible as indicated to the _REG method 446 * 447 * If the region is on the handler's list, this must be the 448 * region's handler 449 */ 450 RegionObj->Region.Handler = NULL; 451 AcpiUtRemoveReference (HandlerObj); 452 453 return_VOID; 454 } 455 456 /* Walk the linked list of handlers */ 457 458 LastObjPtr = &ObjDesc->Region.Next; 459 ObjDesc = ObjDesc->Region.Next; 460 } 461 462 /* If we get here, the region was not in the handler's region list */ 463 464 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 465 "Cannot remove region %p from address handler %p\n", 466 RegionObj, HandlerObj)); 467 468 return_VOID; 469 } 470 471 472 /******************************************************************************* 473 * 474 * FUNCTION: AcpiEvAttachRegion 475 * 476 * PARAMETERS: HandlerObj - Handler Object 477 * RegionObj - Region Object 478 * AcpiNsIsLocked - Namespace Region Already Locked? 479 * 480 * RETURN: None 481 * 482 * DESCRIPTION: Create the association between the handler and the region 483 * this is a two way association. 484 * 485 ******************************************************************************/ 486 487 ACPI_STATUS 488 AcpiEvAttachRegion ( 489 ACPI_OPERAND_OBJECT *HandlerObj, 490 ACPI_OPERAND_OBJECT *RegionObj, 491 BOOLEAN AcpiNsIsLocked) 492 { 493 494 ACPI_FUNCTION_TRACE (EvAttachRegion); 495 496 497 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 498 "Adding Region [%4.4s] %p to address handler %p [%s]\n", 499 AcpiUtGetNodeName (RegionObj->Region.Node), 500 RegionObj, HandlerObj, 501 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 502 503 /* Link this region to the front of the handler's list */ 504 505 RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; 506 HandlerObj->AddressSpace.RegionList = RegionObj; 507 508 /* Install the region's handler */ 509 510 if (RegionObj->Region.Handler) 511 { 512 return_ACPI_STATUS (AE_ALREADY_EXISTS); 513 } 514 515 RegionObj->Region.Handler = HandlerObj; 516 AcpiUtAddReference (HandlerObj); 517 518 return_ACPI_STATUS (AE_OK); 519 } 520 521 522 /******************************************************************************* 523 * 524 * FUNCTION: AcpiEvExecuteRegMethod 525 * 526 * PARAMETERS: RegionObj - Region object 527 * Function - Passed to _REG: On (1) or Off (0) 528 * 529 * RETURN: Status 530 * 531 * DESCRIPTION: Execute _REG method for a region 532 * 533 ******************************************************************************/ 534 535 ACPI_STATUS 536 AcpiEvExecuteRegMethod ( 537 ACPI_OPERAND_OBJECT *RegionObj, 538 UINT32 Function) 539 { 540 ACPI_EVALUATE_INFO *Info; 541 ACPI_OPERAND_OBJECT *Args[3]; 542 ACPI_OPERAND_OBJECT *RegionObj2; 543 ACPI_STATUS Status; 544 545 546 ACPI_FUNCTION_TRACE (EvExecuteRegMethod); 547 548 549 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 550 if (!RegionObj2) 551 { 552 return_ACPI_STATUS (AE_NOT_EXIST); 553 } 554 555 if (RegionObj2->Extra.Method_REG == NULL) 556 { 557 return_ACPI_STATUS (AE_OK); 558 } 559 560 /* Allocate and initialize the evaluation information block */ 561 562 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 563 if (!Info) 564 { 565 return_ACPI_STATUS (AE_NO_MEMORY); 566 } 567 568 Info->PrefixNode = RegionObj2->Extra.Method_REG; 569 Info->RelativePathname = NULL; 570 Info->Parameters = Args; 571 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 572 573 /* 574 * The _REG method has two arguments: 575 * 576 * Arg0 - Integer: 577 * Operation region space ID Same value as RegionObj->Region.SpaceId 578 * 579 * Arg1 - Integer: 580 * connection status 1 for connecting the handler, 0 for disconnecting 581 * the handler (Passed as a parameter) 582 */ 583 Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); 584 if (!Args[0]) 585 { 586 Status = AE_NO_MEMORY; 587 goto Cleanup1; 588 } 589 590 Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); 591 if (!Args[1]) 592 { 593 Status = AE_NO_MEMORY; 594 goto Cleanup2; 595 } 596 597 Args[2] = NULL; /* Terminate list */ 598 599 /* Execute the method, no return value */ 600 601 ACPI_DEBUG_EXEC ( 602 AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); 603 604 Status = AcpiNsEvaluate (Info); 605 AcpiUtRemoveReference (Args[1]); 606 607 Cleanup2: 608 AcpiUtRemoveReference (Args[0]); 609 610 Cleanup1: 611 ACPI_FREE (Info); 612 return_ACPI_STATUS (Status); 613 } 614 615 616 /******************************************************************************* 617 * 618 * FUNCTION: AcpiEvExecuteRegMethods 619 * 620 * PARAMETERS: Node - Namespace node for the device 621 * SpaceId - The address space ID 622 * 623 * RETURN: Status 624 * 625 * DESCRIPTION: Run all _REG methods for the input Space ID; 626 * Note: assumes namespace is locked, or system init time. 627 * 628 ******************************************************************************/ 629 630 ACPI_STATUS 631 AcpiEvExecuteRegMethods ( 632 ACPI_NAMESPACE_NODE *Node, 633 ACPI_ADR_SPACE_TYPE SpaceId) 634 { 635 ACPI_STATUS Status; 636 637 638 ACPI_FUNCTION_TRACE (EvExecuteRegMethods); 639 640 641 /* 642 * Run all _REG methods for all Operation Regions for this space ID. This 643 * is a separate walk in order to handle any interdependencies between 644 * regions and _REG methods. (i.e. handlers must be installed for all 645 * regions of this Space ID before we can run any _REG methods) 646 */ 647 Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 648 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, 649 &SpaceId, NULL); 650 651 /* Special case for EC: handle "orphan" _REG methods with no region */ 652 653 if (SpaceId == ACPI_ADR_SPACE_EC) 654 { 655 AcpiEvOrphanEcRegMethod (Node); 656 } 657 658 return_ACPI_STATUS (Status); 659 } 660 661 662 /******************************************************************************* 663 * 664 * FUNCTION: AcpiEvRegRun 665 * 666 * PARAMETERS: WalkNamespace callback 667 * 668 * DESCRIPTION: Run _REG method for region objects of the requested spaceID 669 * 670 ******************************************************************************/ 671 672 static ACPI_STATUS 673 AcpiEvRegRun ( 674 ACPI_HANDLE ObjHandle, 675 UINT32 Level, 676 void *Context, 677 void **ReturnValue) 678 { 679 ACPI_OPERAND_OBJECT *ObjDesc; 680 ACPI_NAMESPACE_NODE *Node; 681 ACPI_ADR_SPACE_TYPE SpaceId; 682 ACPI_STATUS Status; 683 684 685 SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); 686 687 /* Convert and validate the device handle */ 688 689 Node = AcpiNsValidateHandle (ObjHandle); 690 if (!Node) 691 { 692 return (AE_BAD_PARAMETER); 693 } 694 695 /* 696 * We only care about regions.and objects that are allowed to have address 697 * space handlers 698 */ 699 if ((Node->Type != ACPI_TYPE_REGION) && 700 (Node != AcpiGbl_RootNode)) 701 { 702 return (AE_OK); 703 } 704 705 /* Check for an existing internal object */ 706 707 ObjDesc = AcpiNsGetAttachedObject (Node); 708 if (!ObjDesc) 709 { 710 /* No object, just exit */ 711 712 return (AE_OK); 713 } 714 715 /* Object is a Region */ 716 717 if (ObjDesc->Region.SpaceId != SpaceId) 718 { 719 /* This region is for a different address space, just ignore it */ 720 721 return (AE_OK); 722 } 723 724 Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT); 725 return (Status); 726 } 727 728 729 /******************************************************************************* 730 * 731 * FUNCTION: AcpiEvOrphanEcRegMethod 732 * 733 * PARAMETERS: EcDeviceNode - Namespace node for an EC device 734 * 735 * RETURN: None 736 * 737 * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC 738 * device. This is a _REG method that has no corresponding region 739 * within the EC device scope. The orphan _REG method appears to 740 * have been enabled by the description of the ECDT in the ACPI 741 * specification: "The availability of the region space can be 742 * detected by providing a _REG method object underneath the 743 * Embedded Controller device." 744 * 745 * To quickly access the EC device, we use the EcDeviceNode used 746 * during EC handler installation. Otherwise, we would need to 747 * perform a time consuming namespace walk, executing _HID 748 * methods to find the EC device. 749 * 750 * MUTEX: Assumes the namespace is locked 751 * 752 ******************************************************************************/ 753 754 static void 755 AcpiEvOrphanEcRegMethod ( 756 ACPI_NAMESPACE_NODE *EcDeviceNode) 757 { 758 ACPI_HANDLE RegMethod; 759 ACPI_NAMESPACE_NODE *NextNode; 760 ACPI_STATUS Status; 761 ACPI_OBJECT_LIST Args; 762 ACPI_OBJECT Objects[2]; 763 764 765 ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); 766 767 768 if (!EcDeviceNode) 769 { 770 return_VOID; 771 } 772 773 /* Namespace is currently locked, must release */ 774 775 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 776 777 /* Get a handle to a _REG method immediately under the EC device */ 778 779 Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod); 780 if (ACPI_FAILURE (Status)) 781 { 782 goto Exit; /* There is no _REG method present */ 783 } 784 785 /* 786 * Execute the _REG method only if there is no Operation Region in 787 * this scope with the Embedded Controller space ID. Otherwise, it 788 * will already have been executed. Note, this allows for Regions 789 * with other space IDs to be present; but the code below will then 790 * execute the _REG method with the EmbeddedControl SpaceID argument. 791 */ 792 NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); 793 while (NextNode) 794 { 795 if ((NextNode->Type == ACPI_TYPE_REGION) && 796 (NextNode->Object) && 797 (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) 798 { 799 goto Exit; /* Do not execute the _REG */ 800 } 801 802 NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); 803 } 804 805 /* Evaluate the _REG(EmbeddedControl,Connect) method */ 806 807 Args.Count = 2; 808 Args.Pointer = Objects; 809 Objects[0].Type = ACPI_TYPE_INTEGER; 810 Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; 811 Objects[1].Type = ACPI_TYPE_INTEGER; 812 Objects[1].Integer.Value = ACPI_REG_CONNECT; 813 814 Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); 815 816 Exit: 817 /* We ignore all errors from above, don't care */ 818 819 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 820 return_VOID; 821 }