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