Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/evregion.c need to be fixed.

0001 /******************************************************************************
0002  *
0003  * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
0004  *
0005  *****************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights.  You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code.  No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision.  In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change.  Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee.  Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution.  In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0088  * PARTICULAR PURPOSE.
0089  *
0090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0097  * LIMITED REMEDY.
0098  *
0099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0100  * software or system incorporating such software without first obtaining any
0101  * required license or other approval from the U. S. Department of Commerce or
0102  * any other agency or department of the United States Government.  In the
0103  * event Licensee exports any such software from the United States or
0104  * re-exports any such software from a foreign destination, Licensee shall
0105  * ensure that the distribution and export/re-export of the software is in
0106  * compliance with all laws, regulations, orders, or other restrictions of the
0107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0108  * any of its subsidiaries will export/re-export any technical data, process,
0109  * software, or service, directly or indirectly, to any country for which the
0110  * United States government or any agency thereof requires an export license,
0111  * other governmental approval, or letter of assurance, without first obtaining
0112  * such license, approval or letter.
0113  *
0114  *****************************************************************************/
0115 
0116 
0117 #define __EVREGION_C__
0118 
0119 #include "acpi.h"
0120 #include "accommon.h"
0121 #include "acevents.h"
0122 #include "acnamesp.h"
0123 #include "acinterp.h"
0124 
0125 #define _COMPONENT          ACPI_EVENTS
0126         ACPI_MODULE_NAME    ("evregion")
0127 
0128 
0129 /* Local prototypes */
0130 
0131 static ACPI_STATUS
0132 AcpiEvRegRun (
0133     ACPI_HANDLE             ObjHandle,
0134     UINT32                  Level,
0135     void                    *Context,
0136     void                    **ReturnValue);
0137 
0138 static ACPI_STATUS
0139 AcpiEvInstallHandler (
0140     ACPI_HANDLE             ObjHandle,
0141     UINT32                  Level,
0142     void                    *Context,
0143     void                    **ReturnValue);
0144 
0145 /* These are the address spaces that will get default handlers */
0146 
0147 #define ACPI_NUM_DEFAULT_SPACES     4
0148 
0149 static UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
0150 {
0151     ACPI_ADR_SPACE_SYSTEM_MEMORY,
0152     ACPI_ADR_SPACE_SYSTEM_IO,
0153     ACPI_ADR_SPACE_PCI_CONFIG,
0154     ACPI_ADR_SPACE_DATA_TABLE
0155 };
0156 
0157 
0158 /*******************************************************************************
0159  *
0160  * FUNCTION:    AcpiEvInstallRegionHandlers
0161  *
0162  * PARAMETERS:  None
0163  *
0164  * RETURN:      Status
0165  *
0166  * DESCRIPTION: Installs the core subsystem default address space handlers.
0167  *
0168  ******************************************************************************/
0169 
0170 ACPI_STATUS
0171 AcpiEvInstallRegionHandlers (
0172     void)
0173 {
0174     ACPI_STATUS             Status;
0175     UINT32                  i;
0176 
0177 
0178     ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
0179 
0180 
0181     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
0182     if (ACPI_FAILURE (Status))
0183     {
0184         return_ACPI_STATUS (Status);
0185     }
0186 
0187     /*
0188      * All address spaces (PCI Config, EC, SMBus) are scope dependent and
0189      * registration must occur for a specific device.
0190      *
0191      * In the case of the system memory and IO address spaces there is
0192      * currently no device associated with the address space. For these we
0193      * use the root.
0194      *
0195      * We install the default PCI config space handler at the root so that
0196      * this space is immediately available even though the we have not
0197      * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
0198      * specification which states that the PCI config space must be always
0199      * available -- even though we are nowhere near ready to find the PCI root
0200      * buses at this point.
0201      *
0202      * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
0203      * has already been installed (via AcpiInstallAddressSpaceHandler).
0204      * Similar for AE_SAME_HANDLER.
0205      */
0206     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
0207     {
0208         Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
0209                     AcpiGbl_DefaultAddressSpaces[i],
0210                     ACPI_DEFAULT_HANDLER, NULL, NULL);
0211         switch (Status)
0212         {
0213         case AE_OK:
0214         case AE_SAME_HANDLER:
0215         case AE_ALREADY_EXISTS:
0216 
0217             /* These exceptions are all OK */
0218 
0219             Status = AE_OK;
0220             break;
0221 
0222         default:
0223 
0224             goto UnlockAndExit;
0225         }
0226     }
0227 
0228 UnlockAndExit:
0229     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
0230     return_ACPI_STATUS (Status);
0231 }
0232 
0233 
0234 /*******************************************************************************
0235  *
0236  * FUNCTION:    AcpiEvInitializeOpRegions
0237  *
0238  * PARAMETERS:  None
0239  *
0240  * RETURN:      Status
0241  *
0242  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
0243  *              an installed default region handler.
0244  *
0245  ******************************************************************************/
0246 
0247 ACPI_STATUS
0248 AcpiEvInitializeOpRegions (
0249     void)
0250 {
0251     ACPI_STATUS             Status;
0252     UINT32                  i;
0253 
0254 
0255     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
0256 
0257 
0258     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
0259     if (ACPI_FAILURE (Status))
0260     {
0261         return_ACPI_STATUS (Status);
0262     }
0263 
0264     /* Run the _REG methods for OpRegions in each default address space */
0265 
0266     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
0267     {
0268         /*
0269          * TBD: Make sure handler is the DEFAULT handler, otherwise
0270          * _REG will have already been run.
0271          */
0272         Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
0273                     AcpiGbl_DefaultAddressSpaces[i]);
0274     }
0275 
0276     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
0277     return_ACPI_STATUS (Status);
0278 }
0279 
0280 
0281 /*******************************************************************************
0282  *
0283  * FUNCTION:    AcpiEvExecuteRegMethod
0284  *
0285  * PARAMETERS:  RegionObj           - Region object
0286  *              Function            - Passed to _REG: On (1) or Off (0)
0287  *
0288  * RETURN:      Status
0289  *
0290  * DESCRIPTION: Execute _REG method for a region
0291  *
0292  ******************************************************************************/
0293 
0294 ACPI_STATUS
0295 AcpiEvExecuteRegMethod (
0296     ACPI_OPERAND_OBJECT     *RegionObj,
0297     UINT32                  Function)
0298 {
0299     ACPI_EVALUATE_INFO      *Info;
0300     ACPI_OPERAND_OBJECT     *Args[3];
0301     ACPI_OPERAND_OBJECT     *RegionObj2;
0302     ACPI_STATUS             Status;
0303 
0304 
0305     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
0306 
0307 
0308     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
0309     if (!RegionObj2)
0310     {
0311         return_ACPI_STATUS (AE_NOT_EXIST);
0312     }
0313 
0314     if (RegionObj2->Extra.Method_REG == NULL)
0315     {
0316         return_ACPI_STATUS (AE_OK);
0317     }
0318 
0319     /* Allocate and initialize the evaluation information block */
0320 
0321     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
0322     if (!Info)
0323     {
0324         return_ACPI_STATUS (AE_NO_MEMORY);
0325     }
0326 
0327     Info->PrefixNode = RegionObj2->Extra.Method_REG;
0328     Info->Pathname = NULL;
0329     Info->Parameters = Args;
0330     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
0331 
0332     /*
0333      * The _REG method has two arguments:
0334      *
0335      * Arg0 - Integer:
0336      *  Operation region space ID Same value as RegionObj->Region.SpaceId
0337      *
0338      * Arg1 - Integer:
0339      *  connection status 1 for connecting the handler, 0 for disconnecting
0340      *  the handler (Passed as a parameter)
0341      */
0342     Args[0] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
0343     if (!Args[0])
0344     {
0345         Status = AE_NO_MEMORY;
0346         goto Cleanup1;
0347     }
0348 
0349     Args[1] = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
0350     if (!Args[1])
0351     {
0352         Status = AE_NO_MEMORY;
0353         goto Cleanup2;
0354     }
0355 
0356     /* Setup the parameter objects */
0357 
0358     Args[0]->Integer.Value = RegionObj->Region.SpaceId;
0359     Args[1]->Integer.Value = Function;
0360     Args[2] = NULL;
0361 
0362     /* Execute the method, no return value */
0363 
0364     ACPI_DEBUG_EXEC (
0365         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
0366 
0367     Status = AcpiNsEvaluate (Info);
0368     AcpiUtRemoveReference (Args[1]);
0369 
0370 Cleanup2:
0371     AcpiUtRemoveReference (Args[0]);
0372 
0373 Cleanup1:
0374     ACPI_FREE (Info);
0375     return_ACPI_STATUS (Status);
0376 }
0377 
0378 
0379 /*******************************************************************************
0380  *
0381  * FUNCTION:    AcpiEvAddressSpaceDispatch
0382  *
0383  * PARAMETERS:  RegionObj           - Internal region object
0384  *              Function            - Read or Write operation
0385  *              RegionOffset        - Where in the region to read or write
0386  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
0387  *              Value               - Pointer to in or out value, must be
0388  *                                    full 64-bit ACPI_INTEGER
0389  *
0390  * RETURN:      Status
0391  *
0392  * DESCRIPTION: Dispatch an address space or operation region access to
0393  *              a previously installed handler.
0394  *
0395  ******************************************************************************/
0396 
0397 ACPI_STATUS
0398 AcpiEvAddressSpaceDispatch (
0399     ACPI_OPERAND_OBJECT     *RegionObj,
0400     UINT32                  Function,
0401     UINT32                  RegionOffset,
0402     UINT32                  BitWidth,
0403     ACPI_INTEGER            *Value)
0404 {
0405     ACPI_STATUS             Status;
0406     ACPI_ADR_SPACE_HANDLER  Handler;
0407     ACPI_ADR_SPACE_SETUP    RegionSetup;
0408     ACPI_OPERAND_OBJECT     *HandlerDesc;
0409     ACPI_OPERAND_OBJECT     *RegionObj2;
0410     void                    *RegionContext = NULL;
0411 
0412 
0413     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
0414 
0415 
0416     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
0417     if (!RegionObj2)
0418     {
0419         return_ACPI_STATUS (AE_NOT_EXIST);
0420     }
0421 
0422     /* Ensure that there is a handler associated with this region */
0423 
0424     HandlerDesc = RegionObj->Region.Handler;
0425     if (!HandlerDesc)
0426     {
0427         ACPI_ERROR ((AE_INFO,
0428             "No handler for Region [%4.4s] (%p) [%s]",
0429             AcpiUtGetNodeName (RegionObj->Region.Node),
0430             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0431 
0432         return_ACPI_STATUS (AE_NOT_EXIST);
0433     }
0434 
0435     /*
0436      * It may be the case that the region has never been initialized.
0437      * Some types of regions require special init code
0438      */
0439     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
0440     {
0441         /* This region has not been initialized yet, do it */
0442 
0443         RegionSetup = HandlerDesc->AddressSpace.Setup;
0444         if (!RegionSetup)
0445         {
0446             /* No initialization routine, exit with error */
0447 
0448             ACPI_ERROR ((AE_INFO,
0449                 "No init routine for region(%p) [%s]",
0450                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0451             return_ACPI_STATUS (AE_NOT_EXIST);
0452         }
0453 
0454         /*
0455          * We must exit the interpreter because the region setup will
0456          * potentially execute control methods (for example, the _REG method
0457          * for this region)
0458          */
0459         AcpiExExitInterpreter ();
0460 
0461         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
0462                     HandlerDesc->AddressSpace.Context, &RegionContext);
0463 
0464         /* Re-enter the interpreter */
0465 
0466         AcpiExEnterInterpreter ();
0467 
0468         /* Check for failure of the Region Setup */
0469 
0470         if (ACPI_FAILURE (Status))
0471         {
0472             ACPI_EXCEPTION ((AE_INFO, Status,
0473                 "During region initialization: [%s]",
0474                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0475             return_ACPI_STATUS (Status);
0476         }
0477 
0478         /* Region initialization may have been completed by RegionSetup */
0479 
0480         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
0481         {
0482             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
0483 
0484             if (RegionObj2->Extra.RegionContext)
0485             {
0486                 /* The handler for this region was already installed */
0487 
0488                 ACPI_FREE (RegionContext);
0489             }
0490             else
0491             {
0492                 /*
0493                  * Save the returned context for use in all accesses to
0494                  * this particular region
0495                  */
0496                 RegionObj2->Extra.RegionContext = RegionContext;
0497             }
0498         }
0499     }
0500 
0501     /* We have everything we need, we can invoke the address space handler */
0502 
0503     Handler = HandlerDesc->AddressSpace.Handler;
0504 
0505     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0506         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
0507         &RegionObj->Region.Handler->AddressSpace, Handler,
0508         ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
0509         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0510 
0511     if (!(HandlerDesc->AddressSpace.HandlerFlags &
0512             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
0513     {
0514         /*
0515          * For handlers other than the default (supplied) handlers, we must
0516          * exit the interpreter because the handler *might* block -- we don't
0517          * know what it will do, so we can't hold the lock on the intepreter.
0518          */
0519         AcpiExExitInterpreter();
0520     }
0521 
0522     /* Call the handler */
0523 
0524     Status = Handler (Function,
0525         (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
0526         HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);
0527 
0528     if (ACPI_FAILURE (Status))
0529     {
0530         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
0531             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0532     }
0533 
0534     if (!(HandlerDesc->AddressSpace.HandlerFlags &
0535             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
0536     {
0537         /*
0538          * We just returned from a non-default handler, we must re-enter the
0539          * interpreter
0540          */
0541        AcpiExEnterInterpreter ();
0542     }
0543 
0544     return_ACPI_STATUS (Status);
0545 }
0546 
0547 
0548 /*******************************************************************************
0549  *
0550  * FUNCTION:    AcpiEvDetachRegion
0551  *
0552  * PARAMETERS:  RegionObj           - Region Object
0553  *              AcpiNsIsLocked      - Namespace Region Already Locked?
0554  *
0555  * RETURN:      None
0556  *
0557  * DESCRIPTION: Break the association between the handler and the region
0558  *              this is a two way association.
0559  *
0560  ******************************************************************************/
0561 
0562 void
0563 AcpiEvDetachRegion(
0564     ACPI_OPERAND_OBJECT     *RegionObj,
0565     BOOLEAN                 AcpiNsIsLocked)
0566 {
0567     ACPI_OPERAND_OBJECT     *HandlerObj;
0568     ACPI_OPERAND_OBJECT     *ObjDesc;
0569     ACPI_OPERAND_OBJECT     **LastObjPtr;
0570     ACPI_ADR_SPACE_SETUP    RegionSetup;
0571     void                    **RegionContext;
0572     ACPI_OPERAND_OBJECT     *RegionObj2;
0573     ACPI_STATUS             Status;
0574 
0575 
0576     ACPI_FUNCTION_TRACE (EvDetachRegion);
0577 
0578 
0579     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
0580     if (!RegionObj2)
0581     {
0582         return_VOID;
0583     }
0584     RegionContext = &RegionObj2->Extra.RegionContext;
0585 
0586     /* Get the address handler from the region object */
0587 
0588     HandlerObj = RegionObj->Region.Handler;
0589     if (!HandlerObj)
0590     {
0591         /* This region has no handler, all done */
0592 
0593         return_VOID;
0594     }
0595 
0596     /* Find this region in the handler's list */
0597 
0598     ObjDesc = HandlerObj->AddressSpace.RegionList;
0599     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
0600 
0601     while (ObjDesc)
0602     {
0603         /* Is this the correct Region? */
0604 
0605         if (ObjDesc == RegionObj)
0606         {
0607             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0608                 "Removing Region %p from address handler %p\n",
0609                 RegionObj, HandlerObj));
0610 
0611             /* This is it, remove it from the handler's list */
0612 
0613             *LastObjPtr = ObjDesc->Region.Next;
0614             ObjDesc->Region.Next = NULL;        /* Must clear field */
0615 
0616             if (AcpiNsIsLocked)
0617             {
0618                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
0619                 if (ACPI_FAILURE (Status))
0620                 {
0621                     return_VOID;
0622                 }
0623             }
0624 
0625             /* Now stop region accesses by executing the _REG method */
0626 
0627             Status = AcpiEvExecuteRegMethod (RegionObj, 0);
0628             if (ACPI_FAILURE (Status))
0629             {
0630                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
0631                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0632             }
0633 
0634             if (AcpiNsIsLocked)
0635             {
0636                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
0637                 if (ACPI_FAILURE (Status))
0638                 {
0639                     return_VOID;
0640                 }
0641             }
0642 
0643             /*
0644              * If the region has been activated, call the setup handler with
0645              * the deactivate notification
0646              */
0647             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
0648             {
0649                 RegionSetup = HandlerObj->AddressSpace.Setup;
0650                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
0651                     HandlerObj->AddressSpace.Context, RegionContext);
0652 
0653                 /* Init routine may fail, Just ignore errors */
0654 
0655                 if (ACPI_FAILURE (Status))
0656                 {
0657                     ACPI_EXCEPTION ((AE_INFO, Status,
0658                         "from region handler - deactivate, [%s]",
0659                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0660                 }
0661 
0662                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
0663             }
0664 
0665             /*
0666              * Remove handler reference in the region
0667              *
0668              * NOTE: this doesn't mean that the region goes away, the region
0669              * is just inaccessible as indicated to the _REG method
0670              *
0671              * If the region is on the handler's list, this must be the
0672              * region's handler
0673              */
0674             RegionObj->Region.Handler = NULL;
0675             AcpiUtRemoveReference (HandlerObj);
0676 
0677             return_VOID;
0678         }
0679 
0680         /* Walk the linked list of handlers */
0681 
0682         LastObjPtr = &ObjDesc->Region.Next;
0683         ObjDesc = ObjDesc->Region.Next;
0684     }
0685 
0686     /* If we get here, the region was not in the handler's region list */
0687 
0688     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0689         "Cannot remove region %p from address handler %p\n",
0690         RegionObj, HandlerObj));
0691 
0692     return_VOID;
0693 }
0694 
0695 
0696 /*******************************************************************************
0697  *
0698  * FUNCTION:    AcpiEvAttachRegion
0699  *
0700  * PARAMETERS:  HandlerObj          - Handler Object
0701  *              RegionObj           - Region Object
0702  *              AcpiNsIsLocked      - Namespace Region Already Locked?
0703  *
0704  * RETURN:      None
0705  *
0706  * DESCRIPTION: Create the association between the handler and the region
0707  *              this is a two way association.
0708  *
0709  ******************************************************************************/
0710 
0711 ACPI_STATUS
0712 AcpiEvAttachRegion (
0713     ACPI_OPERAND_OBJECT     *HandlerObj,
0714     ACPI_OPERAND_OBJECT     *RegionObj,
0715     BOOLEAN                 AcpiNsIsLocked)
0716 {
0717 
0718     ACPI_FUNCTION_TRACE (EvAttachRegion);
0719 
0720 
0721     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0722         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
0723         AcpiUtGetNodeName (RegionObj->Region.Node),
0724         RegionObj, HandlerObj,
0725         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0726 
0727     /* Link this region to the front of the handler's list */
0728 
0729     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
0730     HandlerObj->AddressSpace.RegionList = RegionObj;
0731 
0732     /* Install the region's handler */
0733 
0734     if (RegionObj->Region.Handler)
0735     {
0736         return_ACPI_STATUS (AE_ALREADY_EXISTS);
0737     }
0738 
0739     RegionObj->Region.Handler = HandlerObj;
0740     AcpiUtAddReference (HandlerObj);
0741 
0742     return_ACPI_STATUS (AE_OK);
0743 }
0744 
0745 
0746 /*******************************************************************************
0747  *
0748  * FUNCTION:    AcpiEvInstallHandler
0749  *
0750  * PARAMETERS:  WalkNamespace callback
0751  *
0752  * DESCRIPTION: This routine installs an address handler into objects that are
0753  *              of type Region or Device.
0754  *
0755  *              If the Object is a Device, and the device has a handler of
0756  *              the same type then the search is terminated in that branch.
0757  *
0758  *              This is because the existing handler is closer in proximity
0759  *              to any more regions than the one we are trying to install.
0760  *
0761  ******************************************************************************/
0762 
0763 static ACPI_STATUS
0764 AcpiEvInstallHandler (
0765     ACPI_HANDLE             ObjHandle,
0766     UINT32                  Level,
0767     void                    *Context,
0768     void                    **ReturnValue)
0769 {
0770     ACPI_OPERAND_OBJECT     *HandlerObj;
0771     ACPI_OPERAND_OBJECT     *NextHandlerObj;
0772     ACPI_OPERAND_OBJECT     *ObjDesc;
0773     ACPI_NAMESPACE_NODE     *Node;
0774     ACPI_STATUS             Status;
0775 
0776 
0777     ACPI_FUNCTION_NAME (EvInstallHandler);
0778 
0779 
0780     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
0781 
0782     /* Parameter validation */
0783 
0784     if (!HandlerObj)
0785     {
0786         return (AE_OK);
0787     }
0788 
0789     /* Convert and validate the device handle */
0790 
0791     Node = AcpiNsMapHandleToNode (ObjHandle);
0792     if (!Node)
0793     {
0794         return (AE_BAD_PARAMETER);
0795     }
0796 
0797     /*
0798      * We only care about regions and objects that are allowed to have
0799      * address space handlers
0800      */
0801     if ((Node->Type != ACPI_TYPE_DEVICE) &&
0802         (Node->Type != ACPI_TYPE_REGION) &&
0803         (Node != AcpiGbl_RootNode))
0804     {
0805         return (AE_OK);
0806     }
0807 
0808     /* Check for an existing internal object */
0809 
0810     ObjDesc = AcpiNsGetAttachedObject (Node);
0811     if (!ObjDesc)
0812     {
0813         /* No object, just exit */
0814 
0815         return (AE_OK);
0816     }
0817 
0818     /* Devices are handled different than regions */
0819 
0820     if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
0821     {
0822         /* Check if this Device already has a handler for this address space */
0823 
0824         NextHandlerObj = ObjDesc->Device.Handler;
0825         while (NextHandlerObj)
0826         {
0827             /* Found a handler, is it for the same address space? */
0828 
0829             if (NextHandlerObj->AddressSpace.SpaceId ==
0830                     HandlerObj->AddressSpace.SpaceId)
0831             {
0832                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0833                     "Found handler for region [%s] in device %p(%p) "
0834                     "handler %p\n",
0835                     AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
0836                     ObjDesc, NextHandlerObj, HandlerObj));
0837 
0838                 /*
0839                  * Since the object we found it on was a device, then it
0840                  * means that someone has already installed a handler for
0841                  * the branch of the namespace from this device on. Just
0842                  * bail out telling the walk routine to not traverse this
0843                  * branch. This preserves the scoping rule for handlers.
0844                  */
0845                 return (AE_CTRL_DEPTH);
0846             }
0847 
0848             /* Walk the linked list of handlers attached to this device */
0849 
0850             NextHandlerObj = NextHandlerObj->AddressSpace.Next;
0851         }
0852 
0853         /*
0854          * As long as the device didn't have a handler for this space we
0855          * don't care about it. We just ignore it and proceed.
0856          */
0857         return (AE_OK);
0858     }
0859 
0860     /* Object is a Region */
0861 
0862     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
0863     {
0864         /* This region is for a different address space, just ignore it */
0865 
0866         return (AE_OK);
0867     }
0868 
0869     /*
0870      * Now we have a region and it is for the handler's address space type.
0871      *
0872      * First disconnect region for any previous handler (if any)
0873      */
0874     AcpiEvDetachRegion (ObjDesc, FALSE);
0875 
0876     /* Connect the region to the new handler */
0877 
0878     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
0879     return (Status);
0880 }
0881 
0882 
0883 /*******************************************************************************
0884  *
0885  * FUNCTION:    AcpiEvInstallSpaceHandler
0886  *
0887  * PARAMETERS:  Node            - Namespace node for the device
0888  *              SpaceId         - The address space ID
0889  *              Handler         - Address of the handler
0890  *              Setup           - Address of the setup function
0891  *              Context         - Value passed to the handler on each access
0892  *
0893  * RETURN:      Status
0894  *
0895  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
0896  *              Assumes namespace is locked
0897  *
0898  ******************************************************************************/
0899 
0900 ACPI_STATUS
0901 AcpiEvInstallSpaceHandler (
0902     ACPI_NAMESPACE_NODE     *Node,
0903     ACPI_ADR_SPACE_TYPE     SpaceId,
0904     ACPI_ADR_SPACE_HANDLER  Handler,
0905     ACPI_ADR_SPACE_SETUP    Setup,
0906     void                    *Context)
0907 {
0908     ACPI_OPERAND_OBJECT     *ObjDesc;
0909     ACPI_OPERAND_OBJECT     *HandlerObj;
0910     ACPI_STATUS             Status;
0911     ACPI_OBJECT_TYPE        Type;
0912     UINT8                  Flags = 0;
0913 
0914 
0915     ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
0916 
0917 
0918     /*
0919      * This registration is valid for only the types below and the root. This
0920      * is where the default handlers get placed.
0921      */
0922     if ((Node->Type != ACPI_TYPE_DEVICE)     &&
0923         (Node->Type != ACPI_TYPE_PROCESSOR)  &&
0924         (Node->Type != ACPI_TYPE_THERMAL)    &&
0925         (Node != AcpiGbl_RootNode))
0926     {
0927         Status = AE_BAD_PARAMETER;
0928         goto UnlockAndExit;
0929     }
0930 
0931     if (Handler == ACPI_DEFAULT_HANDLER)
0932     {
0933         Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
0934 
0935         switch (SpaceId)
0936         {
0937         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
0938             Handler = AcpiExSystemMemorySpaceHandler;
0939             Setup   = AcpiEvSystemMemoryRegionSetup;
0940             break;
0941 
0942         case ACPI_ADR_SPACE_SYSTEM_IO:
0943             Handler = AcpiExSystemIoSpaceHandler;
0944             Setup   = AcpiEvIoSpaceRegionSetup;
0945             break;
0946 
0947         case ACPI_ADR_SPACE_PCI_CONFIG:
0948             Handler = AcpiExPciConfigSpaceHandler;
0949             Setup   = AcpiEvPciConfigRegionSetup;
0950             break;
0951 
0952         case ACPI_ADR_SPACE_CMOS:
0953             Handler = AcpiExCmosSpaceHandler;
0954             Setup   = AcpiEvCmosRegionSetup;
0955             break;
0956 
0957         case ACPI_ADR_SPACE_PCI_BAR_TARGET:
0958             Handler = AcpiExPciBarSpaceHandler;
0959             Setup   = AcpiEvPciBarRegionSetup;
0960             break;
0961 
0962         case ACPI_ADR_SPACE_DATA_TABLE:
0963             Handler = AcpiExDataTableSpaceHandler;
0964             Setup   = NULL;
0965             break;
0966 
0967         default:
0968             Status = AE_BAD_PARAMETER;
0969             goto UnlockAndExit;
0970         }
0971     }
0972 
0973     /* If the caller hasn't specified a setup routine, use the default */
0974 
0975     if (!Setup)
0976     {
0977         Setup = AcpiEvDefaultRegionSetup;
0978     }
0979 
0980     /* Check for an existing internal object */
0981 
0982     ObjDesc = AcpiNsGetAttachedObject (Node);
0983     if (ObjDesc)
0984     {
0985         /*
0986          * The attached device object already exists. Make sure the handler
0987          * is not already installed.
0988          */
0989         HandlerObj = ObjDesc->Device.Handler;
0990 
0991         /* Walk the handler list for this device */
0992 
0993         while (HandlerObj)
0994         {
0995             /* Same SpaceId indicates a handler already installed */
0996 
0997             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
0998             {
0999                 if (HandlerObj->AddressSpace.Handler == Handler)
1000                 {
1001                     /*
1002                      * It is (relatively) OK to attempt to install the SAME
1003                      * handler twice. This can easily happen with the
1004                      * PCI_Config space.
1005                      */
1006                     Status = AE_SAME_HANDLER;
1007                     goto UnlockAndExit;
1008                 }
1009                 else
1010                 {
1011                     /* A handler is already installed */
1012 
1013                     Status = AE_ALREADY_EXISTS;
1014                 }
1015                 goto UnlockAndExit;
1016             }
1017 
1018             /* Walk the linked list of handlers */
1019 
1020             HandlerObj = HandlerObj->AddressSpace.Next;
1021         }
1022     }
1023     else
1024     {
1025         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1026             "Creating object on Device %p while installing handler\n", Node));
1027 
1028         /* ObjDesc does not exist, create one */
1029 
1030         if (Node->Type == ACPI_TYPE_ANY)
1031         {
1032             Type = ACPI_TYPE_DEVICE;
1033         }
1034         else
1035         {
1036             Type = Node->Type;
1037         }
1038 
1039         ObjDesc = AcpiUtCreateInternalObject (Type);
1040         if (!ObjDesc)
1041         {
1042             Status = AE_NO_MEMORY;
1043             goto UnlockAndExit;
1044         }
1045 
1046         /* Init new descriptor */
1047 
1048         ObjDesc->Common.Type = (UINT8) Type;
1049 
1050         /* Attach the new object to the Node */
1051 
1052         Status = AcpiNsAttachObject (Node, ObjDesc, Type);
1053 
1054         /* Remove local reference to the object */
1055 
1056         AcpiUtRemoveReference (ObjDesc);
1057 
1058         if (ACPI_FAILURE (Status))
1059         {
1060             goto UnlockAndExit;
1061         }
1062     }
1063 
1064     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
1065         "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
1066         AcpiUtGetRegionName (SpaceId), SpaceId,
1067         AcpiUtGetNodeName (Node), Node, ObjDesc));
1068 
1069     /*
1070      * Install the handler
1071      *
1072      * At this point there is no existing handler. Just allocate the object
1073      * for the handler and link it into the list.
1074      */
1075     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
1076     if (!HandlerObj)
1077     {
1078         Status = AE_NO_MEMORY;
1079         goto UnlockAndExit;
1080     }
1081 
1082     /* Init handler obj */
1083 
1084     HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
1085     HandlerObj->AddressSpace.HandlerFlags = Flags;
1086     HandlerObj->AddressSpace.RegionList = NULL;
1087     HandlerObj->AddressSpace.Node = Node;
1088     HandlerObj->AddressSpace.Handler = Handler;
1089     HandlerObj->AddressSpace.Context = Context;
1090     HandlerObj->AddressSpace.Setup  = Setup;
1091 
1092     /* Install at head of Device.AddressSpace list */
1093 
1094     HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
1095 
1096     /*
1097      * The Device object is the first reference on the HandlerObj.
1098      * Each region that uses the handler adds a reference.
1099      */
1100     ObjDesc->Device.Handler = HandlerObj;
1101 
1102     /*
1103      * Walk the namespace finding all of the regions this
1104      * handler will manage.
1105      *
1106      * Start at the device and search the branch toward
1107      * the leaf nodes until either the leaf is encountered or
1108      * a device is detected that has an address handler of the
1109      * same type.
1110      *
1111      * In either case, back up and search down the remainder
1112      * of the branch
1113      */
1114     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1115                 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler,
1116                 HandlerObj, NULL);
1117 
1118 UnlockAndExit:
1119     return_ACPI_STATUS (Status);
1120 }
1121 
1122 
1123 /*******************************************************************************
1124  *
1125  * FUNCTION:    AcpiEvExecuteRegMethods
1126  *
1127  * PARAMETERS:  Node            - Namespace node for the device
1128  *              SpaceId         - The address space ID
1129  *
1130  * RETURN:      Status
1131  *
1132  * DESCRIPTION: Run all _REG methods for the input Space ID;
1133  *              Note: assumes namespace is locked, or system init time.
1134  *
1135  ******************************************************************************/
1136 
1137 ACPI_STATUS
1138 AcpiEvExecuteRegMethods (
1139     ACPI_NAMESPACE_NODE     *Node,
1140     ACPI_ADR_SPACE_TYPE     SpaceId)
1141 {
1142     ACPI_STATUS             Status;
1143 
1144 
1145     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
1146 
1147 
1148     /*
1149      * Run all _REG methods for all Operation Regions for this space ID. This
1150      * is a separate walk in order to handle any interdependencies between
1151      * regions and _REG methods. (i.e. handlers must be installed for all
1152      * regions of this Space ID before we can run any _REG methods)
1153      */
1154     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
1155                 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun,
1156                 &SpaceId, NULL);
1157 
1158     return_ACPI_STATUS (Status);
1159 }
1160 
1161 
1162 /*******************************************************************************
1163  *
1164  * FUNCTION:    AcpiEvRegRun
1165  *
1166  * PARAMETERS:  WalkNamespace callback
1167  *
1168  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
1169  *
1170  ******************************************************************************/
1171 
1172 static ACPI_STATUS
1173 AcpiEvRegRun (
1174     ACPI_HANDLE             ObjHandle,
1175     UINT32                  Level,
1176     void                    *Context,
1177     void                    **ReturnValue)
1178 {
1179     ACPI_OPERAND_OBJECT     *ObjDesc;
1180     ACPI_NAMESPACE_NODE     *Node;
1181     ACPI_ADR_SPACE_TYPE     SpaceId;
1182     ACPI_STATUS             Status;
1183 
1184 
1185     SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
1186 
1187     /* Convert and validate the device handle */
1188 
1189     Node = AcpiNsMapHandleToNode (ObjHandle);
1190     if (!Node)
1191     {
1192         return (AE_BAD_PARAMETER);
1193     }
1194 
1195     /*
1196      * We only care about regions.and objects that are allowed to have address
1197      * space handlers
1198      */
1199     if ((Node->Type != ACPI_TYPE_REGION) &&
1200         (Node != AcpiGbl_RootNode))
1201     {
1202         return (AE_OK);
1203     }
1204 
1205     /* Check for an existing internal object */
1206 
1207     ObjDesc = AcpiNsGetAttachedObject (Node);
1208     if (!ObjDesc)
1209     {
1210         /* No object, just exit */
1211 
1212         return (AE_OK);
1213     }
1214 
1215     /* Object is a Region */
1216 
1217     if (ObjDesc->Region.SpaceId != SpaceId)
1218     {
1219         /* This region is for a different address space, just ignore it */
1220 
1221         return (AE_OK);
1222     }
1223 
1224     Status = AcpiEvExecuteRegMethod (ObjDesc, 1);
1225     return (Status);
1226 }
1227