1 /******************************************************************************
   2  *
   3  * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2011, 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 __EVRGNINI_C__
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "acevents.h"
  50 #include "acnamesp.h"
  51 
  52 #define _COMPONENT          ACPI_EVENTS
  53         ACPI_MODULE_NAME    ("evrgnini")
  54 
  55 /* Local prototypes */
  56 
  57 static BOOLEAN
  58 AcpiEvIsPciRootBridge (
  59     ACPI_NAMESPACE_NODE     *Node);
  60 
  61 
  62 /*******************************************************************************
  63  *
  64  * FUNCTION:    AcpiEvSystemMemoryRegionSetup
  65  *
  66  * PARAMETERS:  Handle              - Region we are interested in
  67  *              Function            - Start or stop
  68  *              HandlerContext      - Address space handler context
  69  *              RegionContext       - Region specific context
  70  *
  71  * RETURN:      Status
  72  *
  73  * DESCRIPTION: Setup a SystemMemory operation region
  74  *
  75  ******************************************************************************/
  76 
  77 ACPI_STATUS
  78 AcpiEvSystemMemoryRegionSetup (
  79     ACPI_HANDLE             Handle,
  80     UINT32                  Function,
  81     void                    *HandlerContext,
  82     void                    **RegionContext)
  83 {
  84     ACPI_OPERAND_OBJECT     *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle;
  85     ACPI_MEM_SPACE_CONTEXT  *LocalRegionContext;
  86 
  87 
  88     ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup);
  89 
  90 
  91     if (Function == ACPI_REGION_DEACTIVATE)
  92     {
  93         if (*RegionContext)
  94         {
  95             LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext;
  96 
  97             /* Delete a cached mapping if present */
  98 
  99             if (LocalRegionContext->MappedLength)
 100             {
 101                 AcpiOsUnmapMemory (LocalRegionContext->MappedLogicalAddress,
 102                     LocalRegionContext->MappedLength);
 103             }
 104             ACPI_FREE (LocalRegionContext);
 105             *RegionContext = NULL;
 106         }
 107         return_ACPI_STATUS (AE_OK);
 108     }
 109 
 110     /* Create a new context */
 111 
 112     LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT));
 113     if (!(LocalRegionContext))
 114     {
 115         return_ACPI_STATUS (AE_NO_MEMORY);
 116     }
 117 
 118     /* Save the region length and address for use in the handler */
 119 
 120     LocalRegionContext->Length  = RegionDesc->Region.Length;
 121     LocalRegionContext->Address = RegionDesc->Region.Address;
 122 
 123     *RegionContext = LocalRegionContext;
 124     return_ACPI_STATUS (AE_OK);
 125 }
 126 
 127 
 128 /*******************************************************************************
 129  *
 130  * FUNCTION:    AcpiEvIoSpaceRegionSetup
 131  *
 132  * PARAMETERS:  Handle              - Region we are interested in
 133  *              Function            - Start or stop
 134  *              HandlerContext      - Address space handler context
 135  *              RegionContext       - Region specific context
 136  *
 137  * RETURN:      Status
 138  *
 139  * DESCRIPTION: Setup a IO operation region
 140  *
 141  ******************************************************************************/
 142 
 143 ACPI_STATUS
 144 AcpiEvIoSpaceRegionSetup (
 145     ACPI_HANDLE             Handle,
 146     UINT32                  Function,
 147     void                    *HandlerContext,
 148     void                    **RegionContext)
 149 {
 150     ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup);
 151 
 152 
 153     if (Function == ACPI_REGION_DEACTIVATE)
 154     {
 155         *RegionContext = NULL;
 156     }
 157     else
 158     {
 159         *RegionContext = HandlerContext;
 160     }
 161 
 162     return_ACPI_STATUS (AE_OK);
 163 }
 164 
 165 
 166 /*******************************************************************************
 167  *
 168  * FUNCTION:    AcpiEvPciConfigRegionSetup
 169  *
 170  * PARAMETERS:  Handle              - Region we are interested in
 171  *              Function            - Start or stop
 172  *              HandlerContext      - Address space handler context
 173  *              RegionContext       - Region specific context
 174  *
 175  * RETURN:      Status
 176  *
 177  * DESCRIPTION: Setup a PCI_Config operation region
 178  *
 179  * MUTEX:       Assumes namespace is not locked
 180  *
 181  ******************************************************************************/
 182 
 183 ACPI_STATUS
 184 AcpiEvPciConfigRegionSetup (
 185     ACPI_HANDLE             Handle,
 186     UINT32                  Function,
 187     void                    *HandlerContext,
 188     void                    **RegionContext)
 189 {
 190     ACPI_STATUS             Status = AE_OK;
 191     UINT64                  PciValue;
 192     ACPI_PCI_ID             *PciId = *RegionContext;
 193     ACPI_OPERAND_OBJECT     *HandlerObj;
 194     ACPI_NAMESPACE_NODE     *ParentNode;
 195     ACPI_NAMESPACE_NODE     *PciRootNode;
 196     ACPI_NAMESPACE_NODE     *PciDeviceNode;
 197     ACPI_OPERAND_OBJECT     *RegionObj = (ACPI_OPERAND_OBJECT  *) Handle;
 198 
 199 
 200     ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup);
 201 
 202 
 203     HandlerObj = RegionObj->Region.Handler;
 204     if (!HandlerObj)
 205     {
 206         /*
 207          * No installed handler. This shouldn't happen because the dispatch
 208          * routine checks before we get here, but we check again just in case.
 209          */
 210         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
 211             "Attempting to init a region %p, with no handler\n", RegionObj));
 212         return_ACPI_STATUS (AE_NOT_EXIST);
 213     }
 214 
 215     *RegionContext = NULL;
 216     if (Function == ACPI_REGION_DEACTIVATE)
 217     {
 218         if (PciId)
 219         {
 220             ACPI_FREE (PciId);
 221         }
 222         return_ACPI_STATUS (Status);
 223     }
 224 
 225     ParentNode = RegionObj->Region.Node->Parent;
 226 
 227     /*
 228      * Get the _SEG and _BBN values from the device upon which the handler
 229      * is installed.
 230      *
 231      * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
 232      * This is the device the handler has been registered to handle.
 233      */
 234 
 235     /*
 236      * If the AddressSpace.Node is still pointing to the root, we need
 237      * to scan upward for a PCI Root bridge and re-associate the OpRegion
 238      * handlers with that device.
 239      */
 240     if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode)
 241     {
 242         /* Start search from the parent object */
 243 
 244         PciRootNode = ParentNode;
 245         while (PciRootNode != AcpiGbl_RootNode)
 246         {
 247             /* Get the _HID/_CID in order to detect a RootBridge */
 248 
 249             if (AcpiEvIsPciRootBridge (PciRootNode))
 250             {
 251                 /* Install a handler for this PCI root bridge */
 252 
 253                 Status = AcpiInstallAddressSpaceHandler (
 254                             (ACPI_HANDLE) PciRootNode,
 255                             ACPI_ADR_SPACE_PCI_CONFIG,
 256                             ACPI_DEFAULT_HANDLER, NULL, NULL);
 257                 if (ACPI_FAILURE (Status))
 258                 {
 259                     if (Status == AE_SAME_HANDLER)
 260                     {
 261                         /*
 262                          * It is OK if the handler is already installed on the
 263                          * root bridge. Still need to return a context object
 264                          * for the new PCI_Config operation region, however.
 265                          */
 266                         Status = AE_OK;
 267                     }
 268                     else
 269                     {
 270                         ACPI_EXCEPTION ((AE_INFO, Status,
 271                             "Could not install PciConfig handler "
 272                             "for Root Bridge %4.4s",
 273                             AcpiUtGetNodeName (PciRootNode)));
 274                     }
 275                 }
 276                 break;
 277             }
 278 
 279             PciRootNode = PciRootNode->Parent;
 280         }
 281 
 282         /* PCI root bridge not found, use namespace root node */
 283     }
 284     else
 285     {
 286         PciRootNode = HandlerObj->AddressSpace.Node;
 287     }
 288 
 289     /*
 290      * If this region is now initialized, we are done.
 291      * (InstallAddressSpaceHandler could have initialized it)
 292      */
 293     if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
 294     {
 295         return_ACPI_STATUS (AE_OK);
 296     }
 297 
 298     /* Region is still not initialized. Create a new context */
 299 
 300     PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID));
 301     if (!PciId)
 302     {
 303         return_ACPI_STATUS (AE_NO_MEMORY);
 304     }
 305 
 306     /*
 307      * For PCI_Config space access, we need the segment, bus, device and
 308      * function numbers. Acquire them here.
 309      *
 310      * Find the parent device object. (This allows the operation region to be
 311      * within a subscope under the device, such as a control method.)
 312      */
 313     PciDeviceNode = RegionObj->Region.Node;
 314     while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE))
 315     {
 316         PciDeviceNode = PciDeviceNode->Parent;
 317     }
 318 
 319     if (!PciDeviceNode)
 320     {
 321         ACPI_FREE (PciId);
 322         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
 323     }
 324 
 325     /*
 326      * Get the PCI device and function numbers from the _ADR object
 327      * contained in the parent's scope.
 328      */
 329     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR,
 330                 PciDeviceNode, &PciValue);
 331 
 332     /*
 333      * The default is zero, and since the allocation above zeroed the data,
 334      * just do nothing on failure.
 335      */
 336     if (ACPI_SUCCESS (Status))
 337     {
 338         PciId->Device   = ACPI_HIWORD (ACPI_LODWORD (PciValue));
 339         PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue));
 340     }
 341 
 342     /* The PCI segment number comes from the _SEG method */
 343 
 344     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG,
 345                 PciRootNode, &PciValue);
 346     if (ACPI_SUCCESS (Status))
 347     {
 348         PciId->Segment = ACPI_LOWORD (PciValue);
 349     }
 350 
 351     /* The PCI bus number comes from the _BBN method */
 352 
 353     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN,
 354                 PciRootNode, &PciValue);
 355     if (ACPI_SUCCESS (Status))
 356     {
 357         PciId->Bus = ACPI_LOWORD (PciValue);
 358     }
 359 
 360     /* Complete/update the PCI ID for this device */
 361 
 362     Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node);
 363     if (ACPI_FAILURE (Status))
 364     {
 365         ACPI_FREE (PciId);
 366         return_ACPI_STATUS (Status);
 367     }
 368 
 369     *RegionContext = PciId;
 370     return_ACPI_STATUS (AE_OK);
 371 }
 372 
 373 
 374 /*******************************************************************************
 375  *
 376  * FUNCTION:    AcpiEvIsPciRootBridge
 377  *
 378  * PARAMETERS:  Node            - Device node being examined
 379  *
 380  * RETURN:      TRUE if device is a PCI/PCI-Express Root Bridge
 381  *
 382  * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by
 383  *              examining the _HID and _CID for the device.
 384  *
 385  ******************************************************************************/
 386 
 387 static BOOLEAN
 388 AcpiEvIsPciRootBridge (
 389     ACPI_NAMESPACE_NODE     *Node)
 390 {
 391     ACPI_STATUS             Status;
 392     ACPI_DEVICE_ID          *Hid;
 393     ACPI_DEVICE_ID_LIST     *Cid;
 394     UINT32                  i;
 395     BOOLEAN                 Match;
 396 
 397 
 398     /* Get the _HID and check for a PCI Root Bridge */
 399 
 400     Status = AcpiUtExecute_HID (Node, &Hid);
 401     if (ACPI_FAILURE (Status))
 402     {
 403         return (FALSE);
 404     }
 405 
 406     Match = AcpiUtIsPciRootBridge (Hid->String);
 407     ACPI_FREE (Hid);
 408 
 409     if (Match)
 410     {
 411         return (TRUE);
 412     }
 413 
 414     /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */
 415 
 416     Status = AcpiUtExecute_CID (Node, &Cid);
 417     if (ACPI_FAILURE (Status))
 418     {
 419         return (FALSE);
 420     }
 421 
 422     /* Check all _CIDs in the returned list */
 423 
 424     for (i = 0; i < Cid->Count; i++)
 425     {
 426         if (AcpiUtIsPciRootBridge (Cid->Ids[i].String))
 427         {
 428             ACPI_FREE (Cid);
 429             return (TRUE);
 430         }
 431     }
 432 
 433     ACPI_FREE (Cid);
 434     return (FALSE);
 435 }
 436 
 437 
 438 /*******************************************************************************
 439  *
 440  * FUNCTION:    AcpiEvPciBarRegionSetup
 441  *
 442  * PARAMETERS:  Handle              - Region we are interested in
 443  *              Function            - Start or stop
 444  *              HandlerContext      - Address space handler context
 445  *              RegionContext       - Region specific context
 446  *
 447  * RETURN:      Status
 448  *
 449  * DESCRIPTION: Setup a PciBAR operation region
 450  *
 451  * MUTEX:       Assumes namespace is not locked
 452  *
 453  ******************************************************************************/
 454 
 455 ACPI_STATUS
 456 AcpiEvPciBarRegionSetup (
 457     ACPI_HANDLE             Handle,
 458     UINT32                  Function,
 459     void                    *HandlerContext,
 460     void                    **RegionContext)
 461 {
 462     ACPI_FUNCTION_TRACE (EvPciBarRegionSetup);
 463 
 464 
 465     return_ACPI_STATUS (AE_OK);
 466 }
 467 
 468 
 469 /*******************************************************************************
 470  *
 471  * FUNCTION:    AcpiEvCmosRegionSetup
 472  *
 473  * PARAMETERS:  Handle              - Region we are interested in
 474  *              Function            - Start or stop
 475  *              HandlerContext      - Address space handler context
 476  *              RegionContext       - Region specific context
 477  *
 478  * RETURN:      Status
 479  *
 480  * DESCRIPTION: Setup a CMOS operation region
 481  *
 482  * MUTEX:       Assumes namespace is not locked
 483  *
 484  ******************************************************************************/
 485 
 486 ACPI_STATUS
 487 AcpiEvCmosRegionSetup (
 488     ACPI_HANDLE             Handle,
 489     UINT32                  Function,
 490     void                    *HandlerContext,
 491     void                    **RegionContext)
 492 {
 493     ACPI_FUNCTION_TRACE (EvCmosRegionSetup);
 494 
 495 
 496     return_ACPI_STATUS (AE_OK);
 497 }
 498 
 499 
 500 /*******************************************************************************
 501  *
 502  * FUNCTION:    AcpiEvDefaultRegionSetup
 503  *
 504  * PARAMETERS:  Handle              - Region we are interested in
 505  *              Function            - Start or stop
 506  *              HandlerContext      - Address space handler context
 507  *              RegionContext       - Region specific context
 508  *
 509  * RETURN:      Status
 510  *
 511  * DESCRIPTION: Default region initialization
 512  *
 513  ******************************************************************************/
 514 
 515 ACPI_STATUS
 516 AcpiEvDefaultRegionSetup (
 517     ACPI_HANDLE             Handle,
 518     UINT32                  Function,
 519     void                    *HandlerContext,
 520     void                    **RegionContext)
 521 {
 522     ACPI_FUNCTION_TRACE (EvDefaultRegionSetup);
 523 
 524 
 525     if (Function == ACPI_REGION_DEACTIVATE)
 526     {
 527         *RegionContext = NULL;
 528     }
 529     else
 530     {
 531         *RegionContext = HandlerContext;
 532     }
 533 
 534     return_ACPI_STATUS (AE_OK);
 535 }
 536 
 537 
 538 /*******************************************************************************
 539  *
 540  * FUNCTION:    AcpiEvInitializeRegion
 541  *
 542  * PARAMETERS:  RegionObj       - Region we are initializing
 543  *              AcpiNsLocked    - Is namespace locked?
 544  *
 545  * RETURN:      Status
 546  *
 547  * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
 548  *              for execution at a later time
 549  *
 550  *              Get the appropriate address space handler for a newly
 551  *              created region.
 552  *
 553  *              This also performs address space specific initialization. For
 554  *              example, PCI regions must have an _ADR object that contains
 555  *              a PCI address in the scope of the definition. This address is
 556  *              required to perform an access to PCI config space.
 557  *
 558  * MUTEX:       Interpreter should be unlocked, because we may run the _REG
 559  *              method for this region.
 560  *
 561  ******************************************************************************/
 562 
 563 ACPI_STATUS
 564 AcpiEvInitializeRegion (
 565     ACPI_OPERAND_OBJECT     *RegionObj,
 566     BOOLEAN                 AcpiNsLocked)
 567 {
 568     ACPI_OPERAND_OBJECT     *HandlerObj;
 569     ACPI_OPERAND_OBJECT     *ObjDesc;
 570     ACPI_ADR_SPACE_TYPE     SpaceId;
 571     ACPI_NAMESPACE_NODE     *Node;
 572     ACPI_STATUS             Status;
 573     ACPI_NAMESPACE_NODE     *MethodNode;
 574     ACPI_NAME               *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG;
 575     ACPI_OPERAND_OBJECT     *RegionObj2;
 576 
 577 
 578     ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked);
 579 
 580 
 581     if (!RegionObj)
 582     {
 583         return_ACPI_STATUS (AE_BAD_PARAMETER);
 584     }
 585 
 586     if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED)
 587     {
 588         return_ACPI_STATUS (AE_OK);
 589     }
 590 
 591     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
 592     if (!RegionObj2)
 593     {
 594         return_ACPI_STATUS (AE_NOT_EXIST);
 595     }
 596 
 597     Node = RegionObj->Region.Node->Parent;
 598     SpaceId = RegionObj->Region.SpaceId;
 599 
 600     /* Setup defaults */
 601 
 602     RegionObj->Region.Handler = NULL;
 603     RegionObj2->Extra.Method_REG = NULL;
 604     RegionObj->Common.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
 605     RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED;
 606 
 607     /* Find any "_REG" method associated with this region definition */
 608 
 609     Status = AcpiNsSearchOneScope (
 610                 *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
 611     if (ACPI_SUCCESS (Status))
 612     {
 613         /*
 614          * The _REG method is optional and there can be only one per region
 615          * definition. This will be executed when the handler is attached
 616          * or removed
 617          */
 618         RegionObj2->Extra.Method_REG = MethodNode;
 619     }
 620 
 621     /*
 622      * The following loop depends upon the root Node having no parent
 623      * ie: AcpiGbl_RootNode->ParentEntry being set to NULL
 624      */
 625     while (Node)
 626     {
 627         /* Check to see if a handler exists */
 628 
 629         HandlerObj = NULL;
 630         ObjDesc = AcpiNsGetAttachedObject (Node);
 631         if (ObjDesc)
 632         {
 633             /* Can only be a handler if the object exists */
 634 
 635             switch (Node->Type)
 636             {
 637             case ACPI_TYPE_DEVICE:
 638 
 639                 HandlerObj = ObjDesc->Device.Handler;
 640                 break;
 641 
 642             case ACPI_TYPE_PROCESSOR:
 643 
 644                 HandlerObj = ObjDesc->Processor.Handler;
 645                 break;
 646 
 647             case ACPI_TYPE_THERMAL:
 648 
 649                 HandlerObj = ObjDesc->ThermalZone.Handler;
 650                 break;
 651 
 652             case ACPI_TYPE_METHOD:
 653                 /*
 654                  * If we are executing module level code, the original
 655                  * Node's object was replaced by this Method object and we
 656                  * saved the handler in the method object.
 657                  *
 658                  * See AcpiNsExecModuleCode
 659                  */
 660                 if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)
 661                 {
 662                     HandlerObj = ObjDesc->Method.Dispatch.Handler;
 663                 }
 664                 break;
 665 
 666             default:
 667                 /* Ignore other objects */
 668                 break;
 669             }
 670 
 671             while (HandlerObj)
 672             {
 673                 /* Is this handler of the correct type? */
 674 
 675                 if (HandlerObj->AddressSpace.SpaceId == SpaceId)
 676                 {
 677                     /* Found correct handler */
 678 
 679                     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
 680                         "Found handler %p for region %p in obj %p\n",
 681                         HandlerObj, RegionObj, ObjDesc));
 682 
 683                     Status = AcpiEvAttachRegion (HandlerObj, RegionObj,
 684                                 AcpiNsLocked);
 685 
 686                     /*
 687                      * Tell all users that this region is usable by
 688                      * running the _REG method
 689                      */
 690                     if (AcpiNsLocked)
 691                     {
 692                         Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 693                         if (ACPI_FAILURE (Status))
 694                         {
 695                             return_ACPI_STATUS (Status);
 696                         }
 697                     }
 698 
 699                     Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT);
 700 
 701                     if (AcpiNsLocked)
 702                     {
 703                         Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 704                         if (ACPI_FAILURE (Status))
 705                         {
 706                             return_ACPI_STATUS (Status);
 707                         }
 708                     }
 709 
 710                     return_ACPI_STATUS (AE_OK);
 711                 }
 712 
 713                 /* Try next handler in the list */
 714 
 715                 HandlerObj = HandlerObj->AddressSpace.Next;
 716             }
 717         }
 718 
 719         /* This node does not have the handler we need; Pop up one level */
 720 
 721         Node = Node->Parent;
 722     }
 723 
 724     /* If we get here, there is no handler for this region */
 725 
 726     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
 727         "No handler for RegionType %s(%X) (RegionObj %p)\n",
 728         AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj));
 729 
 730     return_ACPI_STATUS (AE_NOT_EXIST);
 731 }
 732