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