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