Home | History | Annotate | Line # | Download | only in events
evregion.c revision 1.1.1.2.8.2
      1 /******************************************************************************
      2  *
      3  * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
      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 __EVREGION_C__
     46 
     47 #include "acpi.h"
     48 #include "accommon.h"
     49 #include "acevents.h"
     50 #include "acnamesp.h"
     51 #include "acinterp.h"
     52 
     53 #define _COMPONENT          ACPI_EVENTS
     54         ACPI_MODULE_NAME    ("evregion")
     55 
     56 
     57 /* Local prototypes */
     58 
     59 static BOOLEAN
     60 AcpiEvHasDefaultHandler (
     61     ACPI_NAMESPACE_NODE     *Node,
     62     ACPI_ADR_SPACE_TYPE     SpaceId);
     63 
     64 static ACPI_STATUS
     65 AcpiEvRegRun (
     66     ACPI_HANDLE             ObjHandle,
     67     UINT32                  Level,
     68     void                    *Context,
     69     void                    **ReturnValue);
     70 
     71 static ACPI_STATUS
     72 AcpiEvInstallHandler (
     73     ACPI_HANDLE             ObjHandle,
     74     UINT32                  Level,
     75     void                    *Context,
     76     void                    **ReturnValue);
     77 
     78 /* These are the address spaces that will get default handlers */
     79 
     80 #define ACPI_NUM_DEFAULT_SPACES     4
     81 
     82 static UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
     83 {
     84     ACPI_ADR_SPACE_SYSTEM_MEMORY,
     85     ACPI_ADR_SPACE_SYSTEM_IO,
     86     ACPI_ADR_SPACE_PCI_CONFIG,
     87     ACPI_ADR_SPACE_DATA_TABLE
     88 };
     89 
     90 
     91 /*******************************************************************************
     92  *
     93  * FUNCTION:    AcpiEvInstallRegionHandlers
     94  *
     95  * PARAMETERS:  None
     96  *
     97  * RETURN:      Status
     98  *
     99  * DESCRIPTION: Installs the core subsystem default address space handlers.
    100  *
    101  ******************************************************************************/
    102 
    103 ACPI_STATUS
    104 AcpiEvInstallRegionHandlers (
    105     void)
    106 {
    107     ACPI_STATUS             Status;
    108     UINT32                  i;
    109 
    110 
    111     ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
    112 
    113 
    114     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    115     if (ACPI_FAILURE (Status))
    116     {
    117         return_ACPI_STATUS (Status);
    118     }
    119 
    120     /*
    121      * All address spaces (PCI Config, EC, SMBus) are scope dependent and
    122      * registration must occur for a specific device.
    123      *
    124      * In the case of the system memory and IO address spaces there is
    125      * currently no device associated with the address space. For these we
    126      * use the root.
    127      *
    128      * We install the default PCI config space handler at the root so that
    129      * this space is immediately available even though the we have not
    130      * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
    131      * specification which states that the PCI config space must be always
    132      * available -- even though we are nowhere near ready to find the PCI root
    133      * buses at this point.
    134      *
    135      * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
    136      * has already been installed (via AcpiInstallAddressSpaceHandler).
    137      * Similar for AE_SAME_HANDLER.
    138      */
    139     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
    140     {
    141         Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
    142                     AcpiGbl_DefaultAddressSpaces[i],
    143                     ACPI_DEFAULT_HANDLER, NULL, NULL);
    144         switch (Status)
    145         {
    146         case AE_OK:
    147         case AE_SAME_HANDLER:
    148         case AE_ALREADY_EXISTS:
    149 
    150             /* These exceptions are all OK */
    151 
    152             Status = AE_OK;
    153             break;
    154 
    155         default:
    156 
    157             goto UnlockAndExit;
    158         }
    159     }
    160 
    161 UnlockAndExit:
    162     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    163     return_ACPI_STATUS (Status);
    164 }
    165 
    166 
    167 /*******************************************************************************
    168  *
    169  * FUNCTION:    AcpiEvHasDefaultHandler
    170  *
    171  * PARAMETERS:  Node                - Namespace node for the device
    172  *              SpaceId             - The address space ID
    173  *
    174  * RETURN:      TRUE if default handler is installed, FALSE otherwise
    175  *
    176  * DESCRIPTION: Check if the default handler is installed for the requested
    177  *              space ID.
    178  *
    179  ******************************************************************************/
    180 
    181 static BOOLEAN
    182 AcpiEvHasDefaultHandler (
    183     ACPI_NAMESPACE_NODE     *Node,
    184     ACPI_ADR_SPACE_TYPE     SpaceId)
    185 {
    186     ACPI_OPERAND_OBJECT     *ObjDesc;
    187     ACPI_OPERAND_OBJECT     *HandlerObj;
    188 
    189 
    190     /* Must have an existing internal object */
    191 
    192     ObjDesc = AcpiNsGetAttachedObject (Node);
    193     if (ObjDesc)
    194     {
    195         HandlerObj = ObjDesc->Device.Handler;
    196 
    197         /* Walk the linked list of handlers for this object */
    198 
    199         while (HandlerObj)
    200         {
    201             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
    202             {
    203                 if (HandlerObj->AddressSpace.HandlerFlags &
    204                         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
    205                 {
    206                     return (TRUE);
    207                 }
    208             }
    209 
    210             HandlerObj = HandlerObj->AddressSpace.Next;
    211         }
    212     }
    213 
    214     return (FALSE);
    215 }
    216 
    217 
    218 /*******************************************************************************
    219  *
    220  * FUNCTION:    AcpiEvInitializeOpRegions
    221  *
    222  * PARAMETERS:  None
    223  *
    224  * RETURN:      Status
    225  *
    226  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
    227  *              an installed default region handler.
    228  *
    229  ******************************************************************************/
    230 
    231 ACPI_STATUS
    232 AcpiEvInitializeOpRegions (
    233     void)
    234 {
    235     ACPI_STATUS             Status;
    236     UINT32                  i;
    237 
    238 
    239     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
    240 
    241 
    242     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    243     if (ACPI_FAILURE (Status))
    244     {
    245         return_ACPI_STATUS (Status);
    246     }
    247 
    248     /* Run the _REG methods for OpRegions in each default address space */
    249 
    250     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
    251     {
    252         /*
    253          * Make sure the installed handler is the DEFAULT handler. If not the
    254          * default, the _REG methods will have already been run (when the
    255          * handler was installed)
    256          */
    257         if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
    258                AcpiGbl_DefaultAddressSpaces[i]))
    259         {
    260             Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
    261                         AcpiGbl_DefaultAddressSpaces[i]);
    262         }
    263     }
    264 
    265     AcpiGbl_RegMethodsExecuted = TRUE;
    266 
    267     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    268     return_ACPI_STATUS (Status);
    269 }
    270 
    271 
    272 /*******************************************************************************
    273  *
    274  * FUNCTION:    AcpiEvExecuteRegMethod
    275  *
    276  * PARAMETERS:  RegionObj           - Region object
    277  *              Function            - Passed to _REG: On (1) or Off (0)
    278  *
    279  * RETURN:      Status
    280  *
    281  * DESCRIPTION: Execute _REG method for a region
    282  *
    283  ******************************************************************************/
    284 
    285 ACPI_STATUS
    286 AcpiEvExecuteRegMethod (
    287     ACPI_OPERAND_OBJECT     *RegionObj,
    288     UINT32                  Function)
    289 {
    290     ACPI_EVALUATE_INFO      *Info;
    291     ACPI_OPERAND_OBJECT     *Args[3];
    292     ACPI_OPERAND_OBJECT     *RegionObj2;
    293     ACPI_STATUS             Status;
    294 
    295 
    296     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
    297 
    298 
    299     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
    300     if (!RegionObj2)
    301     {
    302         return_ACPI_STATUS (AE_NOT_EXIST);
    303     }
    304 
    305     if (RegionObj2->Extra.Method_REG == NULL)
    306     {
    307         return_ACPI_STATUS (AE_OK);
    308     }
    309 
    310     /* Allocate and initialize the evaluation information block */
    311 
    312     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    313     if (!Info)
    314     {
    315         return_ACPI_STATUS (AE_NO_MEMORY);
    316     }
    317 
    318     Info->PrefixNode = RegionObj2->Extra.Method_REG;
    319     Info->Pathname = NULL;
    320     Info->Parameters = Args;
    321     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
    322 
    323     /*
    324      * The _REG method has two arguments:
    325      *
    326      * Arg0 - Integer:
    327      *  Operation region space ID Same value as RegionObj->Region.SpaceId
    328      *
    329      * Arg1 - Integer:
    330      *  connection status 1 for connecting the handler, 0 for disconnecting
    331      *  the handler (Passed as a parameter)
    332      */
    333     Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
    334     if (!Args[0])
    335     {
    336         Status = AE_NO_MEMORY;
    337         goto Cleanup1;
    338     }
    339 
    340     Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
    341     if (!Args[1])
    342     {
    343         Status = AE_NO_MEMORY;
    344         goto Cleanup2;
    345     }
    346 
    347     Args[2] = NULL; /* Terminate list */
    348 
    349     /* Execute the method, no return value */
    350 
    351     ACPI_DEBUG_EXEC (
    352         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
    353 
    354     Status = AcpiNsEvaluate (Info);
    355     AcpiUtRemoveReference (Args[1]);
    356 
    357 Cleanup2:
    358     AcpiUtRemoveReference (Args[0]);
    359 
    360 Cleanup1:
    361     ACPI_FREE (Info);
    362     return_ACPI_STATUS (Status);
    363 }
    364 
    365 
    366 /*******************************************************************************
    367  *
    368  * FUNCTION:    AcpiEvAddressSpaceDispatch
    369  *
    370  * PARAMETERS:  RegionObj           - Internal region object
    371  *              Function            - Read or Write operation
    372  *              RegionOffset        - Where in the region to read or write
    373  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
    374  *              Value               - Pointer to in or out value, must be
    375  *                                    a full 64-bit integer
    376  *
    377  * RETURN:      Status
    378  *
    379  * DESCRIPTION: Dispatch an address space or operation region access to
    380  *              a previously installed handler.
    381  *
    382  ******************************************************************************/
    383 
    384 ACPI_STATUS
    385 AcpiEvAddressSpaceDispatch (
    386     ACPI_OPERAND_OBJECT     *RegionObj,
    387     UINT32                  Function,
    388     UINT32                  RegionOffset,
    389     UINT32                  BitWidth,
    390     UINT64                  *Value)
    391 {
    392     ACPI_STATUS             Status;
    393     ACPI_ADR_SPACE_HANDLER  Handler;
    394     ACPI_ADR_SPACE_SETUP    RegionSetup;
    395     ACPI_OPERAND_OBJECT     *HandlerDesc;
    396     ACPI_OPERAND_OBJECT     *RegionObj2;
    397     void                    *RegionContext = NULL;
    398 
    399 
    400     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
    401 
    402 
    403     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
    404     if (!RegionObj2)
    405     {
    406         return_ACPI_STATUS (AE_NOT_EXIST);
    407     }
    408 
    409     /* Ensure that there is a handler associated with this region */
    410 
    411     HandlerDesc = RegionObj->Region.Handler;
    412     if (!HandlerDesc)
    413     {
    414         ACPI_ERROR ((AE_INFO,
    415             "No handler for Region [%4.4s] (%p) [%s]",
    416             AcpiUtGetNodeName (RegionObj->Region.Node),
    417             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    418 
    419         return_ACPI_STATUS (AE_NOT_EXIST);
    420     }
    421 
    422     /*
    423      * It may be the case that the region has never been initialized.
    424      * Some types of regions require special init code
    425      */
    426     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
    427     {
    428         /* This region has not been initialized yet, do it */
    429 
    430         RegionSetup = HandlerDesc->AddressSpace.Setup;
    431         if (!RegionSetup)
    432         {
    433             /* No initialization routine, exit with error */
    434 
    435             ACPI_ERROR ((AE_INFO,
    436                 "No init routine for region(%p) [%s]",
    437                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    438             return_ACPI_STATUS (AE_NOT_EXIST);
    439         }
    440 
    441         /*
    442          * We must exit the interpreter because the region setup will
    443          * potentially execute control methods (for example, the _REG method
    444          * for this region)
    445          */
    446         AcpiExExitInterpreter ();
    447 
    448         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
    449                     HandlerDesc->AddressSpace.Context, &RegionContext);
    450 
    451         /* Re-enter the interpreter */
    452 
    453         AcpiExEnterInterpreter ();
    454 
    455         /* Check for failure of the Region Setup */
    456 
    457         if (ACPI_FAILURE (Status))
    458         {
    459             ACPI_EXCEPTION ((AE_INFO, Status,
    460                 "During region initialization: [%s]",
    461                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    462             return_ACPI_STATUS (Status);
    463         }
    464 
    465         /* Region initialization may have been completed by RegionSetup */
    466 
    467         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
    468         {
    469             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
    470 
    471             if (RegionObj2->Extra.RegionContext)
    472             {
    473                 /* The handler for this region was already installed */
    474 
    475                 ACPI_FREE (RegionContext);
    476             }
    477             else
    478             {
    479                 /*
    480                  * Save the returned context for use in all accesses to
    481                  * this particular region
    482                  */
    483                 RegionObj2->Extra.RegionContext = RegionContext;
    484             }
    485         }
    486     }
    487 
    488     /* We have everything we need, we can invoke the address space handler */
    489 
    490     Handler = HandlerDesc->AddressSpace.Handler;
    491 
    492     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
    493         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
    494         &RegionObj->Region.Handler->AddressSpace, Handler,
    495         ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
    496         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    497 
    498     if (!(HandlerDesc->AddressSpace.HandlerFlags &
    499             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    500     {
    501         /*
    502          * For handlers other than the default (supplied) handlers, we must
    503          * exit the interpreter because the handler *might* block -- we don't
    504          * know what it will do, so we can't hold the lock on the intepreter.
    505          */
    506         AcpiExExitInterpreter();
    507     }
    508 
    509     /* Call the handler */
    510 
    511     Status = Handler (Function,
    512         (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
    513         HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);
    514 
    515     if (ACPI_FAILURE (Status))
    516     {
    517         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
    518             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    519     }
    520 
    521     if (!(HandlerDesc->AddressSpace.HandlerFlags &
    522             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    523     {
    524         /*
    525          * We just returned from a non-default handler, we must re-enter the
    526          * interpreter
    527          */
    528        AcpiExEnterInterpreter ();
    529     }
    530 
    531     return_ACPI_STATUS (Status);
    532 }
    533 
    534 
    535 /*******************************************************************************
    536  *
    537  * FUNCTION:    AcpiEvDetachRegion
    538  *
    539  * PARAMETERS:  RegionObj           - Region Object
    540  *              AcpiNsIsLocked      - Namespace Region Already Locked?
    541  *
    542  * RETURN:      None
    543  *
    544  * DESCRIPTION: Break the association between the handler and the region
    545  *              this is a two way association.
    546  *
    547  ******************************************************************************/
    548 
    549 void
    550 AcpiEvDetachRegion(
    551     ACPI_OPERAND_OBJECT     *RegionObj,
    552     BOOLEAN                 AcpiNsIsLocked)
    553 {
    554     ACPI_OPERAND_OBJECT     *HandlerObj;
    555     ACPI_OPERAND_OBJECT     *ObjDesc;
    556     ACPI_OPERAND_OBJECT     **LastObjPtr;
    557     ACPI_ADR_SPACE_SETUP    RegionSetup;
    558     void                    **RegionContext;
    559     ACPI_OPERAND_OBJECT     *RegionObj2;
    560     ACPI_STATUS             Status;
    561 
    562 
    563     ACPI_FUNCTION_TRACE (EvDetachRegion);
    564 
    565 
    566     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
    567     if (!RegionObj2)
    568     {
    569         return_VOID;
    570     }
    571     RegionContext = &RegionObj2->Extra.RegionContext;
    572 
    573     /* Get the address handler from the region object */
    574 
    575     HandlerObj = RegionObj->Region.Handler;
    576     if (!HandlerObj)
    577     {
    578         /* This region has no handler, all done */
    579 
    580         return_VOID;
    581     }
    582 
    583     /* Find this region in the handler's list */
    584 
    585     ObjDesc = HandlerObj->AddressSpace.RegionList;
    586     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
    587 
    588     while (ObjDesc)
    589     {
    590         /* Is this the correct Region? */
    591 
    592         if (ObjDesc == RegionObj)
    593         {
    594             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
    595                 "Removing Region %p from address handler %p\n",
    596                 RegionObj, HandlerObj));
    597 
    598             /* This is it, remove it from the handler's list */
    599 
    600             *LastObjPtr = ObjDesc->Region.Next;
    601             ObjDesc->Region.Next = NULL;        /* Must clear field */
    602 
    603             if (AcpiNsIsLocked)
    604             {
    605                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    606                 if (ACPI_FAILURE (Status))
    607                 {
    608                     return_VOID;
    609                 }
    610             }
    611 
    612             /* Now stop region accesses by executing the _REG method */
    613 
    614             Status = AcpiEvExecuteRegMethod (RegionObj, 0);
    615             if (ACPI_FAILURE (Status))
    616             {
    617                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
    618                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    619             }
    620 
    621             if (AcpiNsIsLocked)
    622             {
    623                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    624                 if (ACPI_FAILURE (Status))
    625                 {
    626                     return_VOID;
    627                 }
    628             }
    629 
    630             /*
    631              * If the region has been activated, call the setup handler with
    632              * the deactivate notification
    633              */
    634             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
    635             {
    636                 RegionSetup = HandlerObj->AddressSpace.Setup;
    637                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
    638                     HandlerObj->AddressSpace.Context, RegionContext);
    639 
    640                 /* Init routine may fail, Just ignore errors */
    641 
    642                 if (ACPI_FAILURE (Status))
    643                 {
    644                     ACPI_EXCEPTION ((AE_INFO, Status,
    645                         "from region handler - deactivate, [%s]",
    646                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    647                 }
    648 
    649                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
    650             }
    651 
    652             /*
    653              * Remove handler reference in the region
    654              *
    655              * NOTE: this doesn't mean that the region goes away, the region
    656              * is just inaccessible as indicated to the _REG method
    657              *
    658              * If the region is on the handler's list, this must be the
    659              * region's handler
    660              */
    661             RegionObj->Region.Handler = NULL;
    662             AcpiUtRemoveReference (HandlerObj);
    663 
    664             return_VOID;
    665         }
    666 
    667         /* Walk the linked list of handlers */
    668 
    669         LastObjPtr = &ObjDesc->Region.Next;
    670         ObjDesc = ObjDesc->Region.Next;
    671     }
    672 
    673     /* If we get here, the region was not in the handler's region list */
    674 
    675     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
    676         "Cannot remove region %p from address handler %p\n",
    677         RegionObj, HandlerObj));
    678 
    679     return_VOID;
    680 }
    681 
    682 
    683 /*******************************************************************************
    684  *
    685  * FUNCTION:    AcpiEvAttachRegion
    686  *
    687  * PARAMETERS:  HandlerObj          - Handler Object
    688  *              RegionObj           - Region Object
    689  *              AcpiNsIsLocked      - Namespace Region Already Locked?
    690  *
    691  * RETURN:      None
    692  *
    693  * DESCRIPTION: Create the association between the handler and the region
    694  *              this is a two way association.
    695  *
    696  ******************************************************************************/
    697 
    698 ACPI_STATUS
    699 AcpiEvAttachRegion (
    700     ACPI_OPERAND_OBJECT     *HandlerObj,
    701     ACPI_OPERAND_OBJECT     *RegionObj,
    702     BOOLEAN                 AcpiNsIsLocked)
    703 {
    704 
    705     ACPI_FUNCTION_TRACE (EvAttachRegion);
    706 
    707 
    708     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
    709         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
    710         AcpiUtGetNodeName (RegionObj->Region.Node),
    711         RegionObj, HandlerObj,
    712         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    713 
    714     /* Link this region to the front of the handler's list */
    715 
    716     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
    717     HandlerObj->AddressSpace.RegionList = RegionObj;
    718 
    719     /* Install the region's handler */
    720 
    721     if (RegionObj->Region.Handler)
    722     {
    723         return_ACPI_STATUS (AE_ALREADY_EXISTS);
    724     }
    725 
    726     RegionObj->Region.Handler = HandlerObj;
    727     AcpiUtAddReference (HandlerObj);
    728 
    729     return_ACPI_STATUS (AE_OK);
    730 }
    731 
    732 
    733 /*******************************************************************************
    734  *
    735  * FUNCTION:    AcpiEvInstallHandler
    736  *
    737  * PARAMETERS:  WalkNamespace callback
    738  *
    739  * DESCRIPTION: This routine installs an address handler into objects that are
    740  *              of type Region or Device.
    741  *
    742  *              If the Object is a Device, and the device has a handler of
    743  *              the same type then the search is terminated in that branch.
    744  *
    745  *              This is because the existing handler is closer in proximity
    746  *              to any more regions than the one we are trying to install.
    747  *
    748  ******************************************************************************/
    749 
    750 static ACPI_STATUS
    751 AcpiEvInstallHandler (
    752     ACPI_HANDLE             ObjHandle,
    753     UINT32                  Level,
    754     void                    *Context,
    755     void                    **ReturnValue)
    756 {
    757     ACPI_OPERAND_OBJECT     *HandlerObj;
    758     ACPI_OPERAND_OBJECT     *NextHandlerObj;
    759     ACPI_OPERAND_OBJECT     *ObjDesc;
    760     ACPI_NAMESPACE_NODE     *Node;
    761     ACPI_STATUS             Status;
    762 
    763 
    764     ACPI_FUNCTION_NAME (EvInstallHandler);
    765 
    766 
    767     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
    768 
    769     /* Parameter validation */
    770 
    771     if (!HandlerObj)
    772     {
    773         return (AE_OK);
    774     }
    775 
    776     /* Convert and validate the device handle */
    777 
    778     Node = AcpiNsValidateHandle (ObjHandle);
    779     if (!Node)
    780     {
    781         return (AE_BAD_PARAMETER);
    782     }
    783 
    784     /*
    785      * We only care about regions and objects that are allowed to have
    786      * address space handlers
    787      */
    788     if ((Node->Type != ACPI_TYPE_DEVICE) &&
    789         (Node->Type != ACPI_TYPE_REGION) &&
    790         (Node != AcpiGbl_RootNode))
    791     {
    792         return (AE_OK);
    793     }
    794 
    795     /* Check for an existing internal object */
    796 
    797     ObjDesc = AcpiNsGetAttachedObject (Node);
    798     if (!ObjDesc)
    799     {
    800         /* No object, just exit */
    801 
    802         return (AE_OK);
    803     }
    804 
    805     /* Devices are handled different than regions */
    806 
    807     if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
    808     {
    809         /* Check if this Device already has a handler for this address space */
    810 
    811         NextHandlerObj = ObjDesc->Device.Handler;
    812         while (NextHandlerObj)
    813         {
    814             /* Found a handler, is it for the same address space? */
    815 
    816             if (NextHandlerObj->AddressSpace.SpaceId ==
    817                     HandlerObj->AddressSpace.SpaceId)
    818             {
    819                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
    820                     "Found handler for region [%s] in device %p(%p) "
    821                     "handler %p\n",
    822                     AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
    823                     ObjDesc, NextHandlerObj, HandlerObj));
    824 
    825                 /*
    826                  * Since the object we found it on was a device, then it
    827                  * means that someone has already installed a handler for
    828                  * the branch of the namespace from this device on. Just
    829                  * bail out telling the walk routine to not traverse this
    830                  * branch. This preserves the scoping rule for handlers.
    831                  */
    832                 return (AE_CTRL_DEPTH);
    833             }
    834 
    835             /* Walk the linked list of handlers attached to this device */
    836 
    837             NextHandlerObj = NextHandlerObj->AddressSpace.Next;
    838         }
    839 
    840         /*
    841          * As long as the device didn't have a handler for this space we
    842          * don't care about it. We just ignore it and proceed.
    843          */
    844         return (AE_OK);
    845     }
    846 
    847     /* Object is a Region */
    848 
    849     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
    850     {
    851         /* This region is for a different address space, just ignore it */
    852 
    853         return (AE_OK);
    854     }
    855 
    856     /*
    857      * Now we have a region and it is for the handler's address space type.
    858      *
    859      * First disconnect region for any previous handler (if any)
    860      */
    861     AcpiEvDetachRegion (ObjDesc, FALSE);
    862 
    863     /* Connect the region to the new handler */
    864 
    865     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
    866     return (Status);
    867 }
    868 
    869 
    870 /*******************************************************************************
    871  *
    872  * FUNCTION:    AcpiEvInstallSpaceHandler
    873  *
    874  * PARAMETERS:  Node            - Namespace node for the device
    875  *              SpaceId         - The address space ID
    876  *              Handler         - Address of the handler
    877  *              Setup           - Address of the setup function
    878  *              Context         - Value passed to the handler on each access
    879  *
    880  * RETURN:      Status
    881  *
    882  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
    883  *              Assumes namespace is locked
    884  *
    885  ******************************************************************************/
    886 
    887 ACPI_STATUS
    888 AcpiEvInstallSpaceHandler (
    889     ACPI_NAMESPACE_NODE     *Node,
    890     ACPI_ADR_SPACE_TYPE     SpaceId,
    891     ACPI_ADR_SPACE_HANDLER  Handler,
    892     ACPI_ADR_SPACE_SETUP    Setup,
    893     void                    *Context)
    894 {
    895     ACPI_OPERAND_OBJECT     *ObjDesc;
    896     ACPI_OPERAND_OBJECT     *HandlerObj;
    897     ACPI_STATUS             Status;
    898     ACPI_OBJECT_TYPE        Type;
    899     UINT8                  Flags = 0;
    900 
    901 
    902     ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
    903 
    904 
    905     /*
    906      * This registration is valid for only the types below and the root. This
    907      * is where the default handlers get placed.
    908      */
    909     if ((Node->Type != ACPI_TYPE_DEVICE)     &&
    910         (Node->Type != ACPI_TYPE_PROCESSOR)  &&
    911         (Node->Type != ACPI_TYPE_THERMAL)    &&
    912         (Node != AcpiGbl_RootNode))
    913     {
    914         Status = AE_BAD_PARAMETER;
    915         goto UnlockAndExit;
    916     }
    917 
    918     if (Handler == ACPI_DEFAULT_HANDLER)
    919     {
    920         Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
    921 
    922         switch (SpaceId)
    923         {
    924         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
    925             Handler = AcpiExSystemMemorySpaceHandler;
    926             Setup   = AcpiEvSystemMemoryRegionSetup;
    927             break;
    928 
    929         case ACPI_ADR_SPACE_SYSTEM_IO:
    930             Handler = AcpiExSystemIoSpaceHandler;
    931             Setup   = AcpiEvIoSpaceRegionSetup;
    932             break;
    933 
    934         case ACPI_ADR_SPACE_PCI_CONFIG:
    935             Handler = AcpiExPciConfigSpaceHandler;
    936             Setup   = AcpiEvPciConfigRegionSetup;
    937             break;
    938 
    939         case ACPI_ADR_SPACE_CMOS:
    940             Handler = AcpiExCmosSpaceHandler;
    941             Setup   = AcpiEvCmosRegionSetup;
    942             break;
    943 
    944         case ACPI_ADR_SPACE_PCI_BAR_TARGET:
    945             Handler = AcpiExPciBarSpaceHandler;
    946             Setup   = AcpiEvPciBarRegionSetup;
    947             break;
    948 
    949         case ACPI_ADR_SPACE_DATA_TABLE:
    950             Handler = AcpiExDataTableSpaceHandler;
    951             Setup   = NULL;
    952             break;
    953 
    954         default:
    955             Status = AE_BAD_PARAMETER;
    956             goto UnlockAndExit;
    957         }
    958     }
    959 
    960     /* If the caller hasn't specified a setup routine, use the default */
    961 
    962     if (!Setup)
    963     {
    964         Setup = AcpiEvDefaultRegionSetup;
    965     }
    966 
    967     /* Check for an existing internal object */
    968 
    969     ObjDesc = AcpiNsGetAttachedObject (Node);
    970     if (ObjDesc)
    971     {
    972         /*
    973          * The attached device object already exists. Make sure the handler
    974          * is not already installed.
    975          */
    976         HandlerObj = ObjDesc->Device.Handler;
    977 
    978         /* Walk the handler list for this device */
    979 
    980         while (HandlerObj)
    981         {
    982             /* Same SpaceId indicates a handler already installed */
    983 
    984             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
    985             {
    986                 if (HandlerObj->AddressSpace.Handler == Handler)
    987                 {
    988                     /*
    989                      * It is (relatively) OK to attempt to install the SAME
    990                      * handler twice. This can easily happen with the
    991                      * PCI_Config space.
    992                      */
    993                     Status = AE_SAME_HANDLER;
    994                     goto UnlockAndExit;
    995                 }
    996                 else
    997                 {
    998                     /* A handler is already installed */
    999 
   1000                     Status = AE_ALREADY_EXISTS;
   1001                 }
   1002                 goto UnlockAndExit;
   1003             }
   1004 
   1005             /* Walk the linked list of handlers */
   1006 
   1007             HandlerObj = HandlerObj->AddressSpace.Next;
   1008         }
   1009     }
   1010     else
   1011     {
   1012         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
   1013             "Creating object on Device %p while installing handler\n", Node));
   1014 
   1015         /* ObjDesc does not exist, create one */
   1016 
   1017         if (Node->Type == ACPI_TYPE_ANY)
   1018         {
   1019             Type = ACPI_TYPE_DEVICE;
   1020         }
   1021         else
   1022         {
   1023             Type = Node->Type;
   1024         }
   1025 
   1026         ObjDesc = AcpiUtCreateInternalObject (Type);
   1027         if (!ObjDesc)
   1028         {
   1029             Status = AE_NO_MEMORY;
   1030             goto UnlockAndExit;
   1031         }
   1032 
   1033         /* Init new descriptor */
   1034 
   1035         ObjDesc->Common.Type = (UINT8) Type;
   1036 
   1037         /* Attach the new object to the Node */
   1038 
   1039         Status = AcpiNsAttachObject (Node, ObjDesc, Type);
   1040 
   1041         /* Remove local reference to the object */
   1042 
   1043         AcpiUtRemoveReference (ObjDesc);
   1044 
   1045         if (ACPI_FAILURE (Status))
   1046         {
   1047             goto UnlockAndExit;
   1048         }
   1049     }
   1050 
   1051     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
   1052         "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
   1053         AcpiUtGetRegionName (SpaceId), SpaceId,
   1054         AcpiUtGetNodeName (Node), Node, ObjDesc));
   1055 
   1056     /*
   1057      * Install the handler
   1058      *
   1059      * At this point there is no existing handler. Just allocate the object
   1060      * for the handler and link it into the list.
   1061      */
   1062     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
   1063     if (!HandlerObj)
   1064     {
   1065         Status = AE_NO_MEMORY;
   1066         goto UnlockAndExit;
   1067     }
   1068 
   1069     /* Init handler obj */
   1070 
   1071     HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
   1072     HandlerObj->AddressSpace.HandlerFlags = Flags;
   1073     HandlerObj->AddressSpace.RegionList = NULL;
   1074     HandlerObj->AddressSpace.Node = Node;
   1075     HandlerObj->AddressSpace.Handler = Handler;
   1076     HandlerObj->AddressSpace.Context = Context;
   1077     HandlerObj->AddressSpace.Setup  = Setup;
   1078 
   1079     /* Install at head of Device.AddressSpace list */
   1080 
   1081     HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
   1082 
   1083     /*
   1084      * The Device object is the first reference on the HandlerObj.
   1085      * Each region that uses the handler adds a reference.
   1086      */
   1087     ObjDesc->Device.Handler = HandlerObj;
   1088 
   1089     /*
   1090      * Walk the namespace finding all of the regions this
   1091      * handler will manage.
   1092      *
   1093      * Start at the device and search the branch toward
   1094      * the leaf nodes until either the leaf is encountered or
   1095      * a device is detected that has an address handler of the
   1096      * same type.
   1097      *
   1098      * In either case, back up and search down the remainder
   1099      * of the branch
   1100      */
   1101     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
   1102                 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
   1103                 HandlerObj, NULL);
   1104 
   1105 UnlockAndExit:
   1106     return_ACPI_STATUS (Status);
   1107 }
   1108 
   1109 
   1110 /*******************************************************************************
   1111  *
   1112  * FUNCTION:    AcpiEvExecuteRegMethods
   1113  *
   1114  * PARAMETERS:  Node            - Namespace node for the device
   1115  *              SpaceId         - The address space ID
   1116  *
   1117  * RETURN:      Status
   1118  *
   1119  * DESCRIPTION: Run all _REG methods for the input Space ID;
   1120  *              Note: assumes namespace is locked, or system init time.
   1121  *
   1122  ******************************************************************************/
   1123 
   1124 ACPI_STATUS
   1125 AcpiEvExecuteRegMethods (
   1126     ACPI_NAMESPACE_NODE     *Node,
   1127     ACPI_ADR_SPACE_TYPE     SpaceId)
   1128 {
   1129     ACPI_STATUS             Status;
   1130 
   1131 
   1132     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
   1133 
   1134 
   1135     /*
   1136      * Run all _REG methods for all Operation Regions for this space ID. This
   1137      * is a separate walk in order to handle any interdependencies between
   1138      * regions and _REG methods. (i.e. handlers must be installed for all
   1139      * regions of this Space ID before we can run any _REG methods)
   1140      */
   1141     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
   1142                 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL,
   1143                 &SpaceId, NULL);
   1144 
   1145     return_ACPI_STATUS (Status);
   1146 }
   1147 
   1148 
   1149 /*******************************************************************************
   1150  *
   1151  * FUNCTION:    AcpiEvRegRun
   1152  *
   1153  * PARAMETERS:  WalkNamespace callback
   1154  *
   1155  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
   1156  *
   1157  ******************************************************************************/
   1158 
   1159 static ACPI_STATUS
   1160 AcpiEvRegRun (
   1161     ACPI_HANDLE             ObjHandle,
   1162     UINT32                  Level,
   1163     void                    *Context,
   1164     void                    **ReturnValue)
   1165 {
   1166     ACPI_OPERAND_OBJECT     *ObjDesc;
   1167     ACPI_NAMESPACE_NODE     *Node;
   1168     ACPI_ADR_SPACE_TYPE     SpaceId;
   1169     ACPI_STATUS             Status;
   1170 
   1171 
   1172     SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
   1173 
   1174     /* Convert and validate the device handle */
   1175 
   1176     Node = AcpiNsValidateHandle (ObjHandle);
   1177     if (!Node)
   1178     {
   1179         return (AE_BAD_PARAMETER);
   1180     }
   1181 
   1182     /*
   1183      * We only care about regions.and objects that are allowed to have address
   1184      * space handlers
   1185      */
   1186     if ((Node->Type != ACPI_TYPE_REGION) &&
   1187         (Node != AcpiGbl_RootNode))
   1188     {
   1189         return (AE_OK);
   1190     }
   1191 
   1192     /* Check for an existing internal object */
   1193 
   1194     ObjDesc = AcpiNsGetAttachedObject (Node);
   1195     if (!ObjDesc)
   1196     {
   1197         /* No object, just exit */
   1198 
   1199         return (AE_OK);
   1200     }
   1201 
   1202     /* Object is a Region */
   1203 
   1204     if (ObjDesc->Region.SpaceId != SpaceId)
   1205     {
   1206         /* This region is for a different address space, just ignore it */
   1207 
   1208         return (AE_OK);
   1209     }
   1210 
   1211     Status = AcpiEvExecuteRegMethod (ObjDesc, 1);
   1212     return (Status);
   1213 }
   1214 
   1215