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