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