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