ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

evregion.c
Go to the documentation of this file.
00001 /******************************************************************************
00002  *
00003  * Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch
00004  *
00005  *****************************************************************************/
00006 
00007 /******************************************************************************
00008  *
00009  * 1. Copyright Notice
00010  *
00011  * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
00012  * All rights reserved.
00013  *
00014  * 2. License
00015  *
00016  * 2.1. This is your license from Intel Corp. under its intellectual property
00017  * rights.  You may have additional license terms from the party that provided
00018  * you this software, covering your right to use that party's intellectual
00019  * property rights.
00020  *
00021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
00022  * copy of the source code appearing in this file ("Covered Code") an
00023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
00024  * base code distributed originally by Intel ("Original Intel Code") to copy,
00025  * make derivatives, distribute, use and display any portion of the Covered
00026  * Code in any form, with the right to sublicense such rights; and
00027  *
00028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
00029  * license (with the right to sublicense), under only those claims of Intel
00030  * patents that are infringed by the Original Intel Code, to make, use, sell,
00031  * offer to sell, and import the Covered Code and derivative works thereof
00032  * solely to the minimum extent necessary to exercise the above copyright
00033  * license, and in no event shall the patent license extend to any additions
00034  * to or modifications of the Original Intel Code.  No other license or right
00035  * is granted directly or by implication, estoppel or otherwise;
00036  *
00037  * The above copyright and patent license is granted only if the following
00038  * conditions are met:
00039  *
00040  * 3. Conditions
00041  *
00042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
00043  * Redistribution of source code of any substantial portion of the Covered
00044  * Code or modification with rights to further distribute source must include
00045  * the above Copyright Notice, the above License, this list of Conditions,
00046  * and the following Disclaimer and Export Compliance provision.  In addition,
00047  * Licensee must cause all Covered Code to which Licensee contributes to
00048  * contain a file documenting the changes Licensee made to create that Covered
00049  * Code and the date of any change.  Licensee must include in that file the
00050  * documentation of any changes made by any predecessor Licensee.  Licensee
00051  * must include a prominent statement that the modification is derived,
00052  * directly or indirectly, from Original Intel Code.
00053  *
00054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
00055  * Redistribution of source code of any substantial portion of the Covered
00056  * Code or modification without rights to further distribute source must
00057  * include the following Disclaimer and Export Compliance provision in the
00058  * documentation and/or other materials provided with distribution.  In
00059  * addition, Licensee may not authorize further sublicense of source of any
00060  * portion of the Covered Code, and must include terms to the effect that the
00061  * license from Licensee to its licensee is limited to the intellectual
00062  * property embodied in the software Licensee provides to its licensee, and
00063  * not to intellectual property embodied in modifications its licensee may
00064  * make.
00065  *
00066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
00067  * substantial portion of the Covered Code or modification must reproduce the
00068  * above Copyright Notice, and the following Disclaimer and Export Compliance
00069  * provision in the documentation and/or other materials provided with the
00070  * distribution.
00071  *
00072  * 3.4. Intel retains all right, title, and interest in and to the Original
00073  * Intel Code.
00074  *
00075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
00076  * Intel shall be used in advertising or otherwise to promote the sale, use or
00077  * other dealings in products derived from or relating to the Covered Code
00078  * without prior written authorization from Intel.
00079  *
00080  * 4. Disclaimer and Export Compliance
00081  *
00082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
00083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
00084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
00085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
00086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
00087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
00088  * PARTICULAR PURPOSE.
00089  *
00090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
00091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
00092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
00093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
00094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
00095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
00096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
00097  * LIMITED REMEDY.
00098  *
00099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
00100  * software or system incorporating such software without first obtaining any
00101  * required license or other approval from the U. S. Department of Commerce or
00102  * any other agency or department of the United States Government.  In the
00103  * event Licensee exports any such software from the United States or
00104  * re-exports any such software from a foreign destination, Licensee shall
00105  * ensure that the distribution and export/re-export of the software is in
00106  * compliance with all laws, regulations, orders, or other restrictions of the
00107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
00108  * any of its subsidiaries will export/re-export any technical data, process,
00109  * software, or service, directly or indirectly, to any country for which the
00110  * United States government or any agency thereof requires an export license,
00111  * other governmental approval, or letter of assurance, without first obtaining
00112  * such license, approval or letter.
00113  *
00114  *****************************************************************************/
00115 
00116 
00117 #define __EVREGION_C__
00118 
00119 #include "acpi.h"
00120 #include "accommon.h"
00121 #include "acevents.h"
00122 #include "acnamesp.h"
00123 #include "acinterp.h"
00124 
00125 #define _COMPONENT          ACPI_EVENTS
00126         ACPI_MODULE_NAME    ("evregion")
00127 
00128 
00129 /* Local prototypes */
00130 
00131 static BOOLEAN
00132 AcpiEvHasDefaultHandler (
00133     ACPI_NAMESPACE_NODE     *Node,
00134     ACPI_ADR_SPACE_TYPE     SpaceId);
00135 
00136 static void
00137 AcpiEvOrphanEcRegMethod (
00138     void);
00139 
00140 static ACPI_STATUS
00141 AcpiEvRegRun (
00142     ACPI_HANDLE             ObjHandle,
00143     UINT32                  Level,
00144     void                    *Context,
00145     void                    **ReturnValue);
00146 
00147 static ACPI_STATUS
00148 AcpiEvInstallHandler (
00149     ACPI_HANDLE             ObjHandle,
00150     UINT32                  Level,
00151     void                    *Context,
00152     void                    **ReturnValue);
00153 
00154 /* These are the address spaces that will get default handlers */
00155 
00156 #define ACPI_NUM_DEFAULT_SPACES     4
00157 
00158 static UINT8        AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =
00159 {
00160     ACPI_ADR_SPACE_SYSTEM_MEMORY,
00161     ACPI_ADR_SPACE_SYSTEM_IO,
00162     ACPI_ADR_SPACE_PCI_CONFIG,
00163     ACPI_ADR_SPACE_DATA_TABLE
00164 };
00165 
00166 
00167 /*******************************************************************************
00168  *
00169  * FUNCTION:    AcpiEvInstallRegionHandlers
00170  *
00171  * PARAMETERS:  None
00172  *
00173  * RETURN:      Status
00174  *
00175  * DESCRIPTION: Installs the core subsystem default address space handlers.
00176  *
00177  ******************************************************************************/
00178 
00179 ACPI_STATUS
00180 AcpiEvInstallRegionHandlers (
00181     void)
00182 {
00183     ACPI_STATUS             Status;
00184     UINT32                  i;
00185 
00186 
00187     ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);
00188 
00189 
00190     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
00191     if (ACPI_FAILURE (Status))
00192     {
00193         return_ACPI_STATUS (Status);
00194     }
00195 
00196     /*
00197      * All address spaces (PCI Config, EC, SMBus) are scope dependent and
00198      * registration must occur for a specific device.
00199      *
00200      * In the case of the system memory and IO address spaces there is
00201      * currently no device associated with the address space. For these we
00202      * use the root.
00203      *
00204      * We install the default PCI config space handler at the root so that
00205      * this space is immediately available even though the we have not
00206      * enumerated all the PCI Root Buses yet. This is to conform to the ACPI
00207      * specification which states that the PCI config space must be always
00208      * available -- even though we are nowhere near ready to find the PCI root
00209      * buses at this point.
00210      *
00211      * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler
00212      * has already been installed (via AcpiInstallAddressSpaceHandler).
00213      * Similar for AE_SAME_HANDLER.
00214      */
00215     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
00216     {
00217         Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,
00218                     AcpiGbl_DefaultAddressSpaces[i],
00219                     ACPI_DEFAULT_HANDLER, NULL, NULL);
00220         switch (Status)
00221         {
00222         case AE_OK:
00223         case AE_SAME_HANDLER:
00224         case AE_ALREADY_EXISTS:
00225 
00226             /* These exceptions are all OK */
00227 
00228             Status = AE_OK;
00229             break;
00230 
00231         default:
00232 
00233             goto UnlockAndExit;
00234         }
00235     }
00236 
00237 UnlockAndExit:
00238     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
00239     return_ACPI_STATUS (Status);
00240 }
00241 
00242 
00243 /*******************************************************************************
00244  *
00245  * FUNCTION:    AcpiEvHasDefaultHandler
00246  *
00247  * PARAMETERS:  Node                - Namespace node for the device
00248  *              SpaceId             - The address space ID
00249  *
00250  * RETURN:      TRUE if default handler is installed, FALSE otherwise
00251  *
00252  * DESCRIPTION: Check if the default handler is installed for the requested
00253  *              space ID.
00254  *
00255  ******************************************************************************/
00256 
00257 static BOOLEAN
00258 AcpiEvHasDefaultHandler (
00259     ACPI_NAMESPACE_NODE     *Node,
00260     ACPI_ADR_SPACE_TYPE     SpaceId)
00261 {
00262     ACPI_OPERAND_OBJECT     *ObjDesc;
00263     ACPI_OPERAND_OBJECT     *HandlerObj;
00264 
00265 
00266     /* Must have an existing internal object */
00267 
00268     ObjDesc = AcpiNsGetAttachedObject (Node);
00269     if (ObjDesc)
00270     {
00271         HandlerObj = ObjDesc->Device.Handler;
00272 
00273         /* Walk the linked list of handlers for this object */
00274 
00275         while (HandlerObj)
00276         {
00277             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
00278             {
00279                 if (HandlerObj->AddressSpace.HandlerFlags &
00280                         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
00281                 {
00282                     return (TRUE);
00283                 }
00284             }
00285 
00286             HandlerObj = HandlerObj->AddressSpace.Next;
00287         }
00288     }
00289 
00290     return (FALSE);
00291 }
00292 
00293 
00294 /*******************************************************************************
00295  *
00296  * FUNCTION:    AcpiEvInitializeOpRegions
00297  *
00298  * PARAMETERS:  None
00299  *
00300  * RETURN:      Status
00301  *
00302  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
00303  *              an installed default region handler.
00304  *
00305  ******************************************************************************/
00306 
00307 ACPI_STATUS
00308 AcpiEvInitializeOpRegions (
00309     void)
00310 {
00311     ACPI_STATUS             Status;
00312     UINT32                  i;
00313 
00314 
00315     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
00316 
00317 
00318     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
00319     if (ACPI_FAILURE (Status))
00320     {
00321         return_ACPI_STATUS (Status);
00322     }
00323 
00324     /* Run the _REG methods for OpRegions in each default address space */
00325 
00326     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
00327     {
00328         /*
00329          * Make sure the installed handler is the DEFAULT handler. If not the
00330          * default, the _REG methods will have already been run (when the
00331          * handler was installed)
00332          */
00333         if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
00334                AcpiGbl_DefaultAddressSpaces[i]))
00335         {
00336             Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
00337                         AcpiGbl_DefaultAddressSpaces[i]);
00338         }
00339     }
00340 
00341     AcpiGbl_RegMethodsExecuted = TRUE;
00342 
00343     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
00344     return_ACPI_STATUS (Status);
00345 }
00346 
00347 
00348 /*******************************************************************************
00349  *
00350  * FUNCTION:    AcpiEvExecuteRegMethod
00351  *
00352  * PARAMETERS:  RegionObj           - Region object
00353  *              Function            - Passed to _REG: On (1) or Off (0)
00354  *
00355  * RETURN:      Status
00356  *
00357  * DESCRIPTION: Execute _REG method for a region
00358  *
00359  ******************************************************************************/
00360 
00361 ACPI_STATUS
00362 AcpiEvExecuteRegMethod (
00363     ACPI_OPERAND_OBJECT     *RegionObj,
00364     UINT32                  Function)
00365 {
00366     ACPI_EVALUATE_INFO      *Info;
00367     ACPI_OPERAND_OBJECT     *Args[3];
00368     ACPI_OPERAND_OBJECT     *RegionObj2;
00369     ACPI_STATUS             Status;
00370 
00371 
00372     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
00373 
00374 
00375     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
00376     if (!RegionObj2)
00377     {
00378         return_ACPI_STATUS (AE_NOT_EXIST);
00379     }
00380 
00381     if (RegionObj2->Extra.Method_REG == NULL)
00382     {
00383         return_ACPI_STATUS (AE_OK);
00384     }
00385 
00386     /* Allocate and initialize the evaluation information block */
00387 
00388     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
00389     if (!Info)
00390     {
00391         return_ACPI_STATUS (AE_NO_MEMORY);
00392     }
00393 
00394     Info->PrefixNode = RegionObj2->Extra.Method_REG;
00395     Info->Pathname = NULL;
00396     Info->Parameters = Args;
00397     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
00398 
00399     /*
00400      * The _REG method has two arguments:
00401      *
00402      * Arg0 - Integer:
00403      *  Operation region space ID Same value as RegionObj->Region.SpaceId
00404      *
00405      * Arg1 - Integer:
00406      *  connection status 1 for connecting the handler, 0 for disconnecting
00407      *  the handler (Passed as a parameter)
00408      */
00409     Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
00410     if (!Args[0])
00411     {
00412         Status = AE_NO_MEMORY;
00413         goto Cleanup1;
00414     }
00415 
00416     Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
00417     if (!Args[1])
00418     {
00419         Status = AE_NO_MEMORY;
00420         goto Cleanup2;
00421     }
00422 
00423     Args[2] = NULL; /* Terminate list */
00424 
00425     /* Execute the method, no return value */
00426 
00427     ACPI_DEBUG_EXEC (
00428         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
00429 
00430     Status = AcpiNsEvaluate (Info);
00431     AcpiUtRemoveReference (Args[1]);
00432 
00433 Cleanup2:
00434     AcpiUtRemoveReference (Args[0]);
00435 
00436 Cleanup1:
00437     ACPI_FREE (Info);
00438     return_ACPI_STATUS (Status);
00439 }
00440 
00441 
00442 /*******************************************************************************
00443  *
00444  * FUNCTION:    AcpiEvAddressSpaceDispatch
00445  *
00446  * PARAMETERS:  RegionObj           - Internal region object
00447  *              Function            - Read or Write operation
00448  *              RegionOffset        - Where in the region to read or write
00449  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
00450  *              Value               - Pointer to in or out value, must be
00451  *                                    a full 64-bit integer
00452  *
00453  * RETURN:      Status
00454  *
00455  * DESCRIPTION: Dispatch an address space or operation region access to
00456  *              a previously installed handler.
00457  *
00458  ******************************************************************************/
00459 
00460 ACPI_STATUS
00461 AcpiEvAddressSpaceDispatch (
00462     ACPI_OPERAND_OBJECT     *RegionObj,
00463     UINT32                  Function,
00464     UINT32                  RegionOffset,
00465     UINT32                  BitWidth,
00466     UINT64                  *Value)
00467 {
00468     ACPI_STATUS             Status;
00469     ACPI_ADR_SPACE_HANDLER  Handler;
00470     ACPI_ADR_SPACE_SETUP    RegionSetup;
00471     ACPI_OPERAND_OBJECT     *HandlerDesc;
00472     ACPI_OPERAND_OBJECT     *RegionObj2;
00473     void                    *RegionContext = NULL;
00474 
00475 
00476     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
00477 
00478 
00479     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
00480     if (!RegionObj2)
00481     {
00482         return_ACPI_STATUS (AE_NOT_EXIST);
00483     }
00484 
00485     /* Ensure that there is a handler associated with this region */
00486 
00487     HandlerDesc = RegionObj->Region.Handler;
00488     if (!HandlerDesc)
00489     {
00490         ACPI_ERROR ((AE_INFO,
00491             "No handler for Region [%4.4s] (%p) [%s]",
00492             AcpiUtGetNodeName (RegionObj->Region.Node),
00493             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00494 
00495         return_ACPI_STATUS (AE_NOT_EXIST);
00496     }
00497 
00498     /*
00499      * It may be the case that the region has never been initialized.
00500      * Some types of regions require special init code
00501      */
00502     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
00503     {
00504         /* This region has not been initialized yet, do it */
00505 
00506         RegionSetup = HandlerDesc->AddressSpace.Setup;
00507         if (!RegionSetup)
00508         {
00509             /* No initialization routine, exit with error */
00510 
00511             ACPI_ERROR ((AE_INFO,
00512                 "No init routine for region(%p) [%s]",
00513                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00514             return_ACPI_STATUS (AE_NOT_EXIST);
00515         }
00516 
00517         /*
00518          * We must exit the interpreter because the region setup will
00519          * potentially execute control methods (for example, the _REG method
00520          * for this region)
00521          */
00522         AcpiExExitInterpreter ();
00523 
00524         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
00525                     HandlerDesc->AddressSpace.Context, &RegionContext);
00526 
00527         /* Re-enter the interpreter */
00528 
00529         AcpiExEnterInterpreter ();
00530 
00531         /* Check for failure of the Region Setup */
00532 
00533         if (ACPI_FAILURE (Status))
00534         {
00535             ACPI_EXCEPTION ((AE_INFO, Status,
00536                 "During region initialization: [%s]",
00537                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00538             return_ACPI_STATUS (Status);
00539         }
00540 
00541         /* Region initialization may have been completed by RegionSetup */
00542 
00543         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
00544         {
00545             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
00546 
00547             if (RegionObj2->Extra.RegionContext)
00548             {
00549                 /* The handler for this region was already installed */
00550 
00551                 ACPI_FREE (RegionContext);
00552             }
00553             else
00554             {
00555                 /*
00556                  * Save the returned context for use in all accesses to
00557                  * this particular region
00558                  */
00559                 RegionObj2->Extra.RegionContext = RegionContext;
00560             }
00561         }
00562     }
00563 
00564     /* We have everything we need, we can invoke the address space handler */
00565 
00566     Handler = HandlerDesc->AddressSpace.Handler;
00567 
00568     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
00569         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
00570         &RegionObj->Region.Handler->AddressSpace, Handler,
00571         ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
00572         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00573 
00574     if (!(HandlerDesc->AddressSpace.HandlerFlags &
00575             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
00576     {
00577         /*
00578          * For handlers other than the default (supplied) handlers, we must
00579          * exit the interpreter because the handler *might* block -- we don't
00580          * know what it will do, so we can't hold the lock on the intepreter.
00581          */
00582         AcpiExExitInterpreter();
00583     }
00584 
00585     /* Call the handler */
00586 
00587     Status = Handler (Function,
00588         (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
00589         HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);
00590 
00591     if (ACPI_FAILURE (Status))
00592     {
00593         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
00594             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00595     }
00596 
00597     if (!(HandlerDesc->AddressSpace.HandlerFlags &
00598             ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
00599     {
00600         /*
00601          * We just returned from a non-default handler, we must re-enter the
00602          * interpreter
00603          */
00604        AcpiExEnterInterpreter ();
00605     }
00606 
00607     return_ACPI_STATUS (Status);
00608 }
00609 
00610 
00611 /*******************************************************************************
00612  *
00613  * FUNCTION:    AcpiEvDetachRegion
00614  *
00615  * PARAMETERS:  RegionObj           - Region Object
00616  *              AcpiNsIsLocked      - Namespace Region Already Locked?
00617  *
00618  * RETURN:      None
00619  *
00620  * DESCRIPTION: Break the association between the handler and the region
00621  *              this is a two way association.
00622  *
00623  ******************************************************************************/
00624 
00625 void
00626 AcpiEvDetachRegion(
00627     ACPI_OPERAND_OBJECT     *RegionObj,
00628     BOOLEAN                 AcpiNsIsLocked)
00629 {
00630     ACPI_OPERAND_OBJECT     *HandlerObj;
00631     ACPI_OPERAND_OBJECT     *ObjDesc;
00632     ACPI_OPERAND_OBJECT     **LastObjPtr;
00633     ACPI_ADR_SPACE_SETUP    RegionSetup;
00634     void                    **RegionContext;
00635     ACPI_OPERAND_OBJECT     *RegionObj2;
00636     ACPI_STATUS             Status;
00637 
00638 
00639     ACPI_FUNCTION_TRACE (EvDetachRegion);
00640 
00641 
00642     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
00643     if (!RegionObj2)
00644     {
00645         return_VOID;
00646     }
00647     RegionContext = &RegionObj2->Extra.RegionContext;
00648 
00649     /* Get the address handler from the region object */
00650 
00651     HandlerObj = RegionObj->Region.Handler;
00652     if (!HandlerObj)
00653     {
00654         /* This region has no handler, all done */
00655 
00656         return_VOID;
00657     }
00658 
00659     /* Find this region in the handler's list */
00660 
00661     ObjDesc = HandlerObj->AddressSpace.RegionList;
00662     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
00663 
00664     while (ObjDesc)
00665     {
00666         /* Is this the correct Region? */
00667 
00668         if (ObjDesc == RegionObj)
00669         {
00670             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
00671                 "Removing Region %p from address handler %p\n",
00672                 RegionObj, HandlerObj));
00673 
00674             /* This is it, remove it from the handler's list */
00675 
00676             *LastObjPtr = ObjDesc->Region.Next;
00677             ObjDesc->Region.Next = NULL;        /* Must clear field */
00678 
00679             if (AcpiNsIsLocked)
00680             {
00681                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
00682                 if (ACPI_FAILURE (Status))
00683                 {
00684                     return_VOID;
00685                 }
00686             }
00687 
00688             /* Now stop region accesses by executing the _REG method */
00689 
00690             Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
00691             if (ACPI_FAILURE (Status))
00692             {
00693                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
00694                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00695             }
00696 
00697             if (AcpiNsIsLocked)
00698             {
00699                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
00700                 if (ACPI_FAILURE (Status))
00701                 {
00702                     return_VOID;
00703                 }
00704             }
00705 
00706             /*
00707              * If the region has been activated, call the setup handler with
00708              * the deactivate notification
00709              */
00710             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
00711             {
00712                 RegionSetup = HandlerObj->AddressSpace.Setup;
00713                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
00714                     HandlerObj->AddressSpace.Context, RegionContext);
00715 
00716                 /* Init routine may fail, Just ignore errors */
00717 
00718                 if (ACPI_FAILURE (Status))
00719                 {
00720                     ACPI_EXCEPTION ((AE_INFO, Status,
00721                         "from region handler - deactivate, [%s]",
00722                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00723                 }
00724 
00725                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
00726             }
00727 
00728             /*
00729              * Remove handler reference in the region
00730              *
00731              * NOTE: this doesn't mean that the region goes away, the region
00732              * is just inaccessible as indicated to the _REG method
00733              *
00734              * If the region is on the handler's list, this must be the
00735              * region's handler
00736              */
00737             RegionObj->Region.Handler = NULL;
00738             AcpiUtRemoveReference (HandlerObj);
00739 
00740             return_VOID;
00741         }
00742 
00743         /* Walk the linked list of handlers */
00744 
00745         LastObjPtr = &ObjDesc->Region.Next;
00746         ObjDesc = ObjDesc->Region.Next;
00747     }
00748 
00749     /* If we get here, the region was not in the handler's region list */
00750 
00751     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
00752         "Cannot remove region %p from address handler %p\n",
00753         RegionObj, HandlerObj));
00754 
00755     return_VOID;
00756 }
00757 
00758 
00759 /*******************************************************************************
00760  *
00761  * FUNCTION:    AcpiEvAttachRegion
00762  *
00763  * PARAMETERS:  HandlerObj          - Handler Object
00764  *              RegionObj           - Region Object
00765  *              AcpiNsIsLocked      - Namespace Region Already Locked?
00766  *
00767  * RETURN:      None
00768  *
00769  * DESCRIPTION: Create the association between the handler and the region
00770  *              this is a two way association.
00771  *
00772  ******************************************************************************/
00773 
00774 ACPI_STATUS
00775 AcpiEvAttachRegion (
00776     ACPI_OPERAND_OBJECT     *HandlerObj,
00777     ACPI_OPERAND_OBJECT     *RegionObj,
00778     BOOLEAN                 AcpiNsIsLocked)
00779 {
00780 
00781     ACPI_FUNCTION_TRACE (EvAttachRegion);
00782 
00783 
00784     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
00785         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
00786         AcpiUtGetNodeName (RegionObj->Region.Node),
00787         RegionObj, HandlerObj,
00788         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
00789 
00790     /* Link this region to the front of the handler's list */
00791 
00792     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
00793     HandlerObj->AddressSpace.RegionList = RegionObj;
00794 
00795     /* Install the region's handler */
00796 
00797     if (RegionObj->Region.Handler)
00798     {
00799         return_ACPI_STATUS (AE_ALREADY_EXISTS);
00800     }
00801 
00802     RegionObj->Region.Handler = HandlerObj;
00803     AcpiUtAddReference (HandlerObj);
00804 
00805     return_ACPI_STATUS (AE_OK);
00806 }
00807 
00808 
00809 /*******************************************************************************
00810  *
00811  * FUNCTION:    AcpiEvInstallHandler
00812  *
00813  * PARAMETERS:  WalkNamespace callback
00814  *
00815  * DESCRIPTION: This routine installs an address handler into objects that are
00816  *              of type Region or Device.
00817  *
00818  *              If the Object is a Device, and the device has a handler of
00819  *              the same type then the search is terminated in that branch.
00820  *
00821  *              This is because the existing handler is closer in proximity
00822  *              to any more regions than the one we are trying to install.
00823  *
00824  ******************************************************************************/
00825 
00826 static ACPI_STATUS
00827 AcpiEvInstallHandler (
00828     ACPI_HANDLE             ObjHandle,
00829     UINT32                  Level,
00830     void                    *Context,
00831     void                    **ReturnValue)
00832 {
00833     ACPI_OPERAND_OBJECT     *HandlerObj;
00834     ACPI_OPERAND_OBJECT     *NextHandlerObj;
00835     ACPI_OPERAND_OBJECT     *ObjDesc;
00836     ACPI_NAMESPACE_NODE     *Node;
00837     ACPI_STATUS             Status;
00838 
00839 
00840     ACPI_FUNCTION_NAME (EvInstallHandler);
00841 
00842 
00843     HandlerObj = (ACPI_OPERAND_OBJECT  *) Context;
00844 
00845     /* Parameter validation */
00846 
00847     if (!HandlerObj)
00848     {
00849         return (AE_OK);
00850     }
00851 
00852     /* Convert and validate the device handle */
00853 
00854     Node = AcpiNsValidateHandle (ObjHandle);
00855     if (!Node)
00856     {
00857         return (AE_BAD_PARAMETER);
00858     }
00859 
00860     /*
00861      * We only care about regions and objects that are allowed to have
00862      * address space handlers
00863      */
00864     if ((Node->Type != ACPI_TYPE_DEVICE) &&
00865         (Node->Type != ACPI_TYPE_REGION) &&
00866         (Node != AcpiGbl_RootNode))
00867     {
00868         return (AE_OK);
00869     }
00870 
00871     /* Check for an existing internal object */
00872 
00873     ObjDesc = AcpiNsGetAttachedObject (Node);
00874     if (!ObjDesc)
00875     {
00876         /* No object, just exit */
00877 
00878         return (AE_OK);
00879     }
00880 
00881     /* Devices are handled different than regions */
00882 
00883     if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)
00884     {
00885         /* Check if this Device already has a handler for this address space */
00886 
00887         NextHandlerObj = ObjDesc->Device.Handler;
00888         while (NextHandlerObj)
00889         {
00890             /* Found a handler, is it for the same address space? */
00891 
00892             if (NextHandlerObj->AddressSpace.SpaceId ==
00893                     HandlerObj->AddressSpace.SpaceId)
00894             {
00895                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
00896                     "Found handler for region [%s] in device %p(%p) "
00897                     "handler %p\n",
00898                     AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),
00899                     ObjDesc, NextHandlerObj, HandlerObj));
00900 
00901                 /*
00902                  * Since the object we found it on was a device, then it
00903                  * means that someone has already installed a handler for
00904                  * the branch of the namespace from this device on. Just
00905                  * bail out telling the walk routine to not traverse this
00906                  * branch. This preserves the scoping rule for handlers.
00907                  */
00908                 return (AE_CTRL_DEPTH);
00909             }
00910 
00911             /* Walk the linked list of handlers attached to this device */
00912 
00913             NextHandlerObj = NextHandlerObj->AddressSpace.Next;
00914         }
00915 
00916         /*
00917          * As long as the device didn't have a handler for this space we
00918          * don't care about it. We just ignore it and proceed.
00919          */
00920         return (AE_OK);
00921     }
00922 
00923     /* Object is a Region */
00924 
00925     if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)
00926     {
00927         /* This region is for a different address space, just ignore it */
00928 
00929         return (AE_OK);
00930     }
00931 
00932     /*
00933      * Now we have a region and it is for the handler's address space type.
00934      *
00935      * First disconnect region for any previous handler (if any)
00936      */
00937     AcpiEvDetachRegion (ObjDesc, FALSE);
00938 
00939     /* Connect the region to the new handler */
00940 
00941     Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);
00942     return (Status);
00943 }
00944 
00945 
00946 /*******************************************************************************
00947  *
00948  * FUNCTION:    AcpiEvInstallSpaceHandler
00949  *
00950  * PARAMETERS:  Node            - Namespace node for the device
00951  *              SpaceId         - The address space ID
00952  *              Handler         - Address of the handler
00953  *              Setup           - Address of the setup function
00954  *              Context         - Value passed to the handler on each access
00955  *
00956  * RETURN:      Status
00957  *
00958  * DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.
00959  *              Assumes namespace is locked
00960  *
00961  ******************************************************************************/
00962 
00963 ACPI_STATUS
00964 AcpiEvInstallSpaceHandler (
00965     ACPI_NAMESPACE_NODE     *Node,
00966     ACPI_ADR_SPACE_TYPE     SpaceId,
00967     ACPI_ADR_SPACE_HANDLER  Handler,
00968     ACPI_ADR_SPACE_SETUP    Setup,
00969     void                    *Context)
00970 {
00971     ACPI_OPERAND_OBJECT     *ObjDesc;
00972     ACPI_OPERAND_OBJECT     *HandlerObj;
00973     ACPI_STATUS             Status;
00974     ACPI_OBJECT_TYPE        Type;
00975     UINT8                  Flags = 0;
00976 
00977 
00978     ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);
00979 
00980 
00981     /*
00982      * This registration is valid for only the types below and the root. This
00983      * is where the default handlers get placed.
00984      */
00985     if ((Node->Type != ACPI_TYPE_DEVICE)     &&
00986         (Node->Type != ACPI_TYPE_PROCESSOR)  &&
00987         (Node->Type != ACPI_TYPE_THERMAL)    &&
00988         (Node != AcpiGbl_RootNode))
00989     {
00990         Status = AE_BAD_PARAMETER;
00991         goto UnlockAndExit;
00992     }
00993 
00994     if (Handler == ACPI_DEFAULT_HANDLER)
00995     {
00996         Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;
00997 
00998         switch (SpaceId)
00999         {
01000         case ACPI_ADR_SPACE_SYSTEM_MEMORY:
01001             Handler = AcpiExSystemMemorySpaceHandler;
01002             Setup   = AcpiEvSystemMemoryRegionSetup;
01003             break;
01004 
01005         case ACPI_ADR_SPACE_SYSTEM_IO:
01006             Handler = AcpiExSystemIoSpaceHandler;
01007             Setup   = AcpiEvIoSpaceRegionSetup;
01008             break;
01009 
01010         case ACPI_ADR_SPACE_PCI_CONFIG:
01011             Handler = AcpiExPciConfigSpaceHandler;
01012             Setup   = AcpiEvPciConfigRegionSetup;
01013             break;
01014 
01015         case ACPI_ADR_SPACE_CMOS:
01016             Handler = AcpiExCmosSpaceHandler;
01017             Setup   = AcpiEvCmosRegionSetup;
01018             break;
01019 
01020         case ACPI_ADR_SPACE_PCI_BAR_TARGET:
01021             Handler = AcpiExPciBarSpaceHandler;
01022             Setup   = AcpiEvPciBarRegionSetup;
01023             break;
01024 
01025         case ACPI_ADR_SPACE_DATA_TABLE:
01026             Handler = AcpiExDataTableSpaceHandler;
01027             Setup   = NULL;
01028             break;
01029 
01030         default:
01031             Status = AE_BAD_PARAMETER;
01032             goto UnlockAndExit;
01033         }
01034     }
01035 
01036     /* If the caller hasn't specified a setup routine, use the default */
01037 
01038     if (!Setup)
01039     {
01040         Setup = AcpiEvDefaultRegionSetup;
01041     }
01042 
01043     /* Check for an existing internal object */
01044 
01045     ObjDesc = AcpiNsGetAttachedObject (Node);
01046     if (ObjDesc)
01047     {
01048         /*
01049          * The attached device object already exists. Make sure the handler
01050          * is not already installed.
01051          */
01052         HandlerObj = ObjDesc->Device.Handler;
01053 
01054         /* Walk the handler list for this device */
01055 
01056         while (HandlerObj)
01057         {
01058             /* Same SpaceId indicates a handler already installed */
01059 
01060             if (HandlerObj->AddressSpace.SpaceId == SpaceId)
01061             {
01062                 if (HandlerObj->AddressSpace.Handler == Handler)
01063                 {
01064                     /*
01065                      * It is (relatively) OK to attempt to install the SAME
01066                      * handler twice. This can easily happen with the
01067                      * PCI_Config space.
01068                      */
01069                     Status = AE_SAME_HANDLER;
01070                     goto UnlockAndExit;
01071                 }
01072                 else
01073                 {
01074                     /* A handler is already installed */
01075 
01076                     Status = AE_ALREADY_EXISTS;
01077                 }
01078                 goto UnlockAndExit;
01079             }
01080 
01081             /* Walk the linked list of handlers */
01082 
01083             HandlerObj = HandlerObj->AddressSpace.Next;
01084         }
01085     }
01086     else
01087     {
01088         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
01089             "Creating object on Device %p while installing handler\n", Node));
01090 
01091         /* ObjDesc does not exist, create one */
01092 
01093         if (Node->Type == ACPI_TYPE_ANY)
01094         {
01095             Type = ACPI_TYPE_DEVICE;
01096         }
01097         else
01098         {
01099             Type = Node->Type;
01100         }
01101 
01102         ObjDesc = AcpiUtCreateInternalObject (Type);
01103         if (!ObjDesc)
01104         {
01105             Status = AE_NO_MEMORY;
01106             goto UnlockAndExit;
01107         }
01108 
01109         /* Init new descriptor */
01110 
01111         ObjDesc->Common.Type = (UINT8) Type;
01112 
01113         /* Attach the new object to the Node */
01114 
01115         Status = AcpiNsAttachObject (Node, ObjDesc, Type);
01116 
01117         /* Remove local reference to the object */
01118 
01119         AcpiUtRemoveReference (ObjDesc);
01120 
01121         if (ACPI_FAILURE (Status))
01122         {
01123             goto UnlockAndExit;
01124         }
01125     }
01126 
01127     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
01128         "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
01129         AcpiUtGetRegionName (SpaceId), SpaceId,
01130         AcpiUtGetNodeName (Node), Node, ObjDesc));
01131 
01132     /*
01133      * Install the handler
01134      *
01135      * At this point there is no existing handler. Just allocate the object
01136      * for the handler and link it into the list.
01137      */
01138     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);
01139     if (!HandlerObj)
01140     {
01141         Status = AE_NO_MEMORY;
01142         goto UnlockAndExit;
01143     }
01144 
01145     /* Init handler obj */
01146 
01147     HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;
01148     HandlerObj->AddressSpace.HandlerFlags = Flags;
01149     HandlerObj->AddressSpace.RegionList = NULL;
01150     HandlerObj->AddressSpace.Node = Node;
01151     HandlerObj->AddressSpace.Handler = Handler;
01152     HandlerObj->AddressSpace.Context = Context;
01153     HandlerObj->AddressSpace.Setup  = Setup;
01154 
01155     /* Install at head of Device.AddressSpace list */
01156 
01157     HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler;
01158 
01159     /*
01160      * The Device object is the first reference on the HandlerObj.
01161      * Each region that uses the handler adds a reference.
01162      */
01163     ObjDesc->Device.Handler = HandlerObj;
01164 
01165     /*
01166      * Walk the namespace finding all of the regions this
01167      * handler will manage.
01168      *
01169      * Start at the device and search the branch toward
01170      * the leaf nodes until either the leaf is encountered or
01171      * a device is detected that has an address handler of the
01172      * same type.
01173      *
01174      * In either case, back up and search down the remainder
01175      * of the branch
01176      */
01177     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
01178                 ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL,
01179                 HandlerObj, NULL);
01180 
01181 UnlockAndExit:
01182     return_ACPI_STATUS (Status);
01183 }
01184 
01185 
01186 /*******************************************************************************
01187  *
01188  * FUNCTION:    AcpiEvExecuteRegMethods
01189  *
01190  * PARAMETERS:  Node            - Namespace node for the device
01191  *              SpaceId         - The address space ID
01192  *
01193  * RETURN:      Status
01194  *
01195  * DESCRIPTION: Run all _REG methods for the input Space ID;
01196  *              Note: assumes namespace is locked, or system init time.
01197  *
01198  ******************************************************************************/
01199 
01200 ACPI_STATUS
01201 AcpiEvExecuteRegMethods (
01202     ACPI_NAMESPACE_NODE     *Node,
01203     ACPI_ADR_SPACE_TYPE     SpaceId)
01204 {
01205     ACPI_STATUS             Status;
01206 
01207 
01208     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
01209 
01210 
01211     /*
01212      * Run all _REG methods for all Operation Regions for this space ID. This
01213      * is a separate walk in order to handle any interdependencies between
01214      * regions and _REG methods. (i.e. handlers must be installed for all
01215      * regions of this Space ID before we can run any _REG methods)
01216      */
01217     Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
01218                 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL,
01219                 &SpaceId, NULL);
01220 
01221     /* Special case for EC: handle "orphan" _REG methods with no region */
01222 
01223     if (SpaceId == ACPI_ADR_SPACE_EC)
01224     {
01225         AcpiEvOrphanEcRegMethod ();
01226     }
01227 
01228     return_ACPI_STATUS (Status);
01229 }
01230 
01231 
01232 /*******************************************************************************
01233  *
01234  * FUNCTION:    AcpiEvRegRun
01235  *
01236  * PARAMETERS:  WalkNamespace callback
01237  *
01238  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
01239  *
01240  ******************************************************************************/
01241 
01242 static ACPI_STATUS
01243 AcpiEvRegRun (
01244     ACPI_HANDLE             ObjHandle,
01245     UINT32                  Level,
01246     void                    *Context,
01247     void                    **ReturnValue)
01248 {
01249     ACPI_OPERAND_OBJECT     *ObjDesc;
01250     ACPI_NAMESPACE_NODE     *Node;
01251     ACPI_ADR_SPACE_TYPE     SpaceId;
01252     ACPI_STATUS             Status;
01253 
01254 
01255     SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context);
01256 
01257     /* Convert and validate the device handle */
01258 
01259     Node = AcpiNsValidateHandle (ObjHandle);
01260     if (!Node)
01261     {
01262         return (AE_BAD_PARAMETER);
01263     }
01264 
01265     /*
01266      * We only care about regions.and objects that are allowed to have address
01267      * space handlers
01268      */
01269     if ((Node->Type != ACPI_TYPE_REGION) &&
01270         (Node != AcpiGbl_RootNode))
01271     {
01272         return (AE_OK);
01273     }
01274 
01275     /* Check for an existing internal object */
01276 
01277     ObjDesc = AcpiNsGetAttachedObject (Node);
01278     if (!ObjDesc)
01279     {
01280         /* No object, just exit */
01281 
01282         return (AE_OK);
01283     }
01284 
01285     /* Object is a Region */
01286 
01287     if (ObjDesc->Region.SpaceId != SpaceId)
01288     {
01289         /* This region is for a different address space, just ignore it */
01290 
01291         return (AE_OK);
01292     }
01293 
01294     Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT);
01295     return (Status);
01296 }
01297 
01298 
01299 /*******************************************************************************
01300  *
01301  * FUNCTION:    AcpiEvOrphanEcRegMethod
01302  *
01303  * PARAMETERS:  None
01304  *
01305  * RETURN:      None
01306  *
01307  * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
01308  *              device. This is a _REG method that has no corresponding region
01309  *              within the EC device scope. The orphan _REG method appears to
01310  *              have been enabled by the description of the ECDT in the ACPI
01311  *              specification: "The availability of the region space can be
01312  *              detected by providing a _REG method object underneath the
01313  *              Embedded Controller device."
01314  *
01315  *              To quickly access the EC device, we use the EC_ID that appears
01316  *              within the ECDT. Otherwise, we would need to perform a time-
01317  *              consuming namespace walk, executing _HID methods to find the
01318  *              EC device.
01319  *
01320  ******************************************************************************/
01321 
01322 static void
01323 AcpiEvOrphanEcRegMethod (
01324     void)
01325 {
01326     ACPI_TABLE_ECDT         *Table;
01327     ACPI_STATUS             Status;
01328     ACPI_OBJECT_LIST        Args;
01329     ACPI_OBJECT             Objects[2];
01330     ACPI_NAMESPACE_NODE     *EcDeviceNode;
01331     ACPI_NAMESPACE_NODE     *RegMethod;
01332     ACPI_NAMESPACE_NODE     *NextNode;
01333 
01334 
01335     ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod);
01336 
01337 
01338     /* Get the ECDT (if present in system) */
01339 
01340     Status = AcpiGetTable (ACPI_SIG_ECDT, 0,
01341         ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Table));
01342     if (ACPI_FAILURE (Status))
01343     {
01344         return_VOID;
01345     }
01346 
01347     /* We need a valid EC_ID string */
01348 
01349     if (!(*Table->Id))
01350     {
01351         return_VOID;
01352     }
01353 
01354     /* Namespace is currently locked, must release */
01355 
01356     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
01357 
01358     /* Get a handle to the EC device referenced in the ECDT */
01359 
01360     Status = AcpiGetHandle (NULL,
01361         ACPI_CAST_PTR (char, Table->Id),
01362         ACPI_CAST_PTR (ACPI_HANDLE, &EcDeviceNode));
01363     if (ACPI_FAILURE (Status))
01364     {
01365         goto Exit;
01366     }
01367 
01368     /* Get a handle to a _REG method immediately under the EC device */
01369 
01370     Status = AcpiGetHandle (EcDeviceNode,
01371         METHOD_NAME__REG, ACPI_CAST_PTR (ACPI_HANDLE, &RegMethod));
01372     if (ACPI_FAILURE (Status))
01373     {
01374         goto Exit;
01375     }
01376 
01377     /*
01378      * Execute the _REG method only if there is no Operation Region in
01379      * this scope with the Embedded Controller space ID. Otherwise, it
01380      * will already have been executed. Note, this allows for Regions
01381      * with other space IDs to be present; but the code below will then
01382      * execute the _REG method with the EC space ID argument.
01383      */
01384     NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL);
01385     while (NextNode)
01386     {
01387         if ((NextNode->Type == ACPI_TYPE_REGION) &&
01388             (NextNode->Object) &&
01389             (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC))
01390         {
01391             goto Exit; /* Do not execute _REG */
01392         }
01393         NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode);
01394     }
01395 
01396     /* Evaluate the _REG(EC,Connect) method */
01397 
01398     Args.Count = 2;
01399     Args.Pointer = Objects;
01400     Objects[0].Type = ACPI_TYPE_INTEGER;
01401     Objects[0].Integer.Value = ACPI_ADR_SPACE_EC;
01402     Objects[1].Type = ACPI_TYPE_INTEGER;
01403     Objects[1].Integer.Value = ACPI_REG_CONNECT;
01404 
01405     Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
01406 
01407 Exit:
01408     /* We ignore all errors from above, don't care */
01409 
01410     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
01411     return_VOID;
01412 }

Generated on Sun May 27 2012 04:27:16 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.