The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/acpica/components/events/evregion.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /******************************************************************************
    2  *
    3  * Module Name: evregion - Operation Region support
    4  *
    5  *****************************************************************************/
    6 
    7 /******************************************************************************
    8  *
    9  * 1. Copyright Notice
   10  *
   11  * Some or all of this work - Copyright (c) 1999 - 2022, Intel Corp.
   12  * All rights reserved.
   13  *
   14  * 2. License
   15  *
   16  * 2.1. This is your license from Intel Corp. under its intellectual property
   17  * rights. You may have additional license terms from the party that provided
   18  * you this software, covering your right to use that party's intellectual
   19  * property rights.
   20  *
   21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
   22  * copy of the source code appearing in this file ("Covered Code") an
   23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
   24  * base code distributed originally by Intel ("Original Intel Code") to copy,
   25  * make derivatives, distribute, use and display any portion of the Covered
   26  * Code in any form, with the right to sublicense such rights; and
   27  *
   28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
   29  * license (with the right to sublicense), under only those claims of Intel
   30  * patents that are infringed by the Original Intel Code, to make, use, sell,
   31  * offer to sell, and import the Covered Code and derivative works thereof
   32  * solely to the minimum extent necessary to exercise the above copyright
   33  * license, and in no event shall the patent license extend to any additions
   34  * to or modifications of the Original Intel Code. No other license or right
   35  * is granted directly or by implication, estoppel or otherwise;
   36  *
   37  * The above copyright and patent license is granted only if the following
   38  * conditions are met:
   39  *
   40  * 3. Conditions
   41  *
   42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
   43  * Redistribution of source code of any substantial portion of the Covered
   44  * Code or modification with rights to further distribute source must include
   45  * the above Copyright Notice, the above License, this list of Conditions,
   46  * and the following Disclaimer and Export Compliance provision. In addition,
   47  * Licensee must cause all Covered Code to which Licensee contributes to
   48  * contain a file documenting the changes Licensee made to create that Covered
   49  * Code and the date of any change. Licensee must include in that file the
   50  * documentation of any changes made by any predecessor Licensee. Licensee
   51  * must include a prominent statement that the modification is derived,
   52  * directly or indirectly, from Original Intel Code.
   53  *
   54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
   55  * Redistribution of source code of any substantial portion of the Covered
   56  * Code or modification without rights to further distribute source must
   57  * include the following Disclaimer and Export Compliance provision in the
   58  * documentation and/or other materials provided with distribution. In
   59  * addition, Licensee may not authorize further sublicense of source of any
   60  * portion of the Covered Code, and must include terms to the effect that the
   61  * license from Licensee to its licensee is limited to the intellectual
   62  * property embodied in the software Licensee provides to its licensee, and
   63  * not to intellectual property embodied in modifications its licensee may
   64  * make.
   65  *
   66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
   67  * substantial portion of the Covered Code or modification must reproduce the
   68  * above Copyright Notice, and the following Disclaimer and Export Compliance
   69  * provision in the documentation and/or other materials provided with the
   70  * distribution.
   71  *
   72  * 3.4. Intel retains all right, title, and interest in and to the Original
   73  * Intel Code.
   74  *
   75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
   76  * Intel shall be used in advertising or otherwise to promote the sale, use or
   77  * other dealings in products derived from or relating to the Covered Code
   78  * without prior written authorization from Intel.
   79  *
   80  * 4. Disclaimer and Export Compliance
   81  *
   82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
   83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
   84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
   85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
   86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
   87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
   88  * PARTICULAR PURPOSE.
   89  *
   90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
   91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
   92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
   93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
   94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
   95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
   96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
   97  * LIMITED REMEDY.
   98  *
   99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
  100  * software or system incorporating such software without first obtaining any
  101  * required license or other approval from the U. S. Department of Commerce or
  102  * any other agency or department of the United States Government. In the
  103  * event Licensee exports any such software from the United States or
  104  * re-exports any such software from a foreign destination, Licensee shall
  105  * ensure that the distribution and export/re-export of the software is in
  106  * compliance with all laws, regulations, orders, or other restrictions of the
  107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
  108  * any of its subsidiaries will export/re-export any technical data, process,
  109  * software, or service, directly or indirectly, to any country for which the
  110  * United States government or any agency thereof requires an export license,
  111  * other governmental approval, or letter of assurance, without first obtaining
  112  * such license, approval or letter.
  113  *
  114  *****************************************************************************
  115  *
  116  * Alternatively, you may choose to be licensed under the terms of the
  117  * following license:
  118  *
  119  * Redistribution and use in source and binary forms, with or without
  120  * modification, are permitted provided that the following conditions
  121  * are met:
  122  * 1. Redistributions of source code must retain the above copyright
  123  *    notice, this list of conditions, and the following disclaimer,
  124  *    without modification.
  125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  126  *    substantially similar to the "NO WARRANTY" disclaimer below
  127  *    ("Disclaimer") and any redistribution must be conditioned upon
  128  *    including a substantially similar Disclaimer requirement for further
  129  *    binary redistribution.
  130  * 3. Neither the names of the above-listed copyright holders nor the names
  131  *    of any contributors may be used to endorse or promote products derived
  132  *    from this software without specific prior written permission.
  133  *
  134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  145  *
  146  * Alternatively, you may choose to be licensed under the terms of the
  147  * GNU General Public License ("GPL") version 2 as published by the Free
  148  * Software Foundation.
  149  *
  150  *****************************************************************************/
  151 
  152 #include <contrib/dev/acpica/include/acpi.h>
  153 #include <contrib/dev/acpica/include/accommon.h>
  154 #include <contrib/dev/acpica/include/acevents.h>
  155 #include <contrib/dev/acpica/include/acnamesp.h>
  156 #include <contrib/dev/acpica/include/acinterp.h>
  157 
  158 #define _COMPONENT          ACPI_EVENTS
  159         ACPI_MODULE_NAME    ("evregion")
  160 
  161 
  162 extern UINT8        AcpiGbl_DefaultAddressSpaces[];
  163 
  164 /* Local prototypes */
  165 
  166 static void
  167 AcpiEvExecuteOrphanRegMethod (
  168     ACPI_NAMESPACE_NODE     *DeviceNode,
  169     ACPI_ADR_SPACE_TYPE     SpaceId);
  170 
  171 
  172 static ACPI_STATUS
  173 AcpiEvRegRun (
  174     ACPI_HANDLE             ObjHandle,
  175     UINT32                  Level,
  176     void                    *Context,
  177     void                    **ReturnValue);
  178 
  179 
  180 /*******************************************************************************
  181  *
  182  * FUNCTION:    AcpiEvInitializeOpRegions
  183  *
  184  * PARAMETERS:  None
  185  *
  186  * RETURN:      Status
  187  *
  188  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
  189  *              an installed default region handler.
  190  *
  191  ******************************************************************************/
  192 
  193 ACPI_STATUS
  194 AcpiEvInitializeOpRegions (
  195     void)
  196 {
  197     ACPI_STATUS             Status;
  198     UINT32                  i;
  199 
  200 
  201     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
  202 
  203 
  204     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
  205     if (ACPI_FAILURE (Status))
  206     {
  207         return_ACPI_STATUS (Status);
  208     }
  209 
  210     /* Run the _REG methods for OpRegions in each default address space */
  211 
  212     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
  213     {
  214         /*
  215          * Make sure the installed handler is the DEFAULT handler. If not the
  216          * default, the _REG methods will have already been run (when the
  217          * handler was installed)
  218          */
  219         if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
  220                AcpiGbl_DefaultAddressSpaces[i]))
  221         {
  222             AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
  223                 AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT);
  224         }
  225     }
  226 
  227     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
  228     return_ACPI_STATUS (Status);
  229 }
  230 
  231 
  232 /*******************************************************************************
  233  *
  234  * FUNCTION:    AcpiEvAddressSpaceDispatch
  235  *
  236  * PARAMETERS:  RegionObj           - Internal region object
  237  *              FieldObj            - Corresponding field. Can be NULL.
  238  *              Function            - Read or Write operation
  239  *              RegionOffset        - Where in the region to read or write
  240  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
  241  *              Value               - Pointer to in or out value, must be
  242  *                                    a full 64-bit integer
  243  *
  244  * RETURN:      Status
  245  *
  246  * DESCRIPTION: Dispatch an address space or operation region access to
  247  *              a previously installed handler.
  248  *
  249  * NOTE: During early initialization, we always install the default region
  250  * handlers for Memory, I/O and PCI_Config. This ensures that these operation
  251  * region address spaces are always available as per the ACPI specification.
  252  * This is especially needed in order to support the execution of
  253  * module-level AML code during loading of the ACPI tables.
  254  *
  255  ******************************************************************************/
  256 
  257 ACPI_STATUS
  258 AcpiEvAddressSpaceDispatch (
  259     ACPI_OPERAND_OBJECT     *RegionObj,
  260     ACPI_OPERAND_OBJECT     *FieldObj,
  261     UINT32                  Function,
  262     UINT32                  RegionOffset,
  263     UINT32                  BitWidth,
  264     UINT64                  *Value)
  265 {
  266     ACPI_STATUS             Status;
  267     ACPI_ADR_SPACE_HANDLER  Handler;
  268     ACPI_ADR_SPACE_SETUP    RegionSetup;
  269     ACPI_OPERAND_OBJECT     *HandlerDesc;
  270     ACPI_OPERAND_OBJECT     *RegionObj2;
  271     void                    *RegionContext = NULL;
  272     ACPI_CONNECTION_INFO    *Context;
  273     ACPI_MUTEX              ContextMutex;
  274     BOOLEAN                 ContextLocked;
  275     ACPI_PHYSICAL_ADDRESS   Address;
  276 
  277 
  278     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
  279 
  280 
  281     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
  282     if (!RegionObj2)
  283     {
  284         return_ACPI_STATUS (AE_NOT_EXIST);
  285     }
  286 
  287     /* Ensure that there is a handler associated with this region */
  288 
  289     HandlerDesc = RegionObj->Region.Handler;
  290     if (!HandlerDesc)
  291     {
  292         ACPI_ERROR ((AE_INFO,
  293             "No handler for Region [%4.4s] (%p) [%s]",
  294             AcpiUtGetNodeName (RegionObj->Region.Node),
  295             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  296 
  297         return_ACPI_STATUS (AE_NOT_EXIST);
  298     }
  299 
  300     Context = HandlerDesc->AddressSpace.Context;
  301     ContextMutex = HandlerDesc->AddressSpace.ContextMutex;
  302     ContextLocked = FALSE;
  303 
  304     /*
  305      * It may be the case that the region has never been initialized.
  306      * Some types of regions require special init code
  307      */
  308     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
  309     {
  310         /* This region has not been initialized yet, do it */
  311 
  312         RegionSetup = HandlerDesc->AddressSpace.Setup;
  313         if (!RegionSetup)
  314         {
  315             /* No initialization routine, exit with error */
  316 
  317             ACPI_ERROR ((AE_INFO,
  318                 "No init routine for region(%p) [%s]",
  319                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  320             return_ACPI_STATUS (AE_NOT_EXIST);
  321         }
  322 
  323         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)
  324         {
  325             ACPI_PCC_INFO *Ctx = HandlerDesc->AddressSpace.Context;
  326 
  327             Ctx->InternalBuffer = FieldObj->Field.InternalPccBuffer;
  328             Ctx->Length = (UINT16) RegionObj->Region.Length;
  329             Ctx->SubspaceId = (UINT8) RegionObj->Region.Address;
  330         }
  331 
  332         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE)
  333         {
  334             ACPI_FFH_INFO *Ctx = HandlerDesc->AddressSpace.Context;
  335 
  336             Ctx->Length = RegionObj->Region.Length;
  337             Ctx->Offset = RegionObj->Region.Address;
  338         }
  339 
  340         /*
  341          * We must exit the interpreter because the region setup will
  342          * potentially execute control methods (for example, the _REG method
  343          * for this region)
  344          */
  345         AcpiExExitInterpreter ();
  346 
  347         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
  348             Context, &RegionContext);
  349 
  350         /* Re-enter the interpreter */
  351 
  352         AcpiExEnterInterpreter ();
  353 
  354         /* Check for failure of the Region Setup */
  355 
  356         if (ACPI_FAILURE (Status))
  357         {
  358             ACPI_EXCEPTION ((AE_INFO, Status,
  359                 "During region initialization: [%s]",
  360                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  361             return_ACPI_STATUS (Status);
  362         }
  363 
  364         /* Region initialization may have been completed by RegionSetup */
  365 
  366         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
  367         {
  368             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
  369 
  370             /*
  371              * Save the returned context for use in all accesses to
  372              * the handler for this particular region
  373              */
  374             if (!(RegionObj2->Extra.RegionContext))
  375             {
  376                 RegionObj2->Extra.RegionContext = RegionContext;
  377             }
  378         }
  379     }
  380 
  381     /* We have everything we need, we can invoke the address space handler */
  382 
  383     Handler = HandlerDesc->AddressSpace.Handler;
  384     Address = (RegionObj->Region.Address + RegionOffset);
  385 
  386     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
  387         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
  388         &RegionObj->Region.Handler->AddressSpace, Handler,
  389         ACPI_FORMAT_UINT64 (Address),
  390         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  391 
  392     if (!(HandlerDesc->AddressSpace.HandlerFlags &
  393         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
  394     {
  395         /*
  396          * For handlers other than the default (supplied) handlers, we must
  397          * exit the interpreter because the handler *might* block -- we don't
  398          * know what it will do, so we can't hold the lock on the interpreter.
  399          */
  400         AcpiExExitInterpreter();
  401     }
  402 
  403     /*
  404      * Special handling for GenericSerialBus and GeneralPurposeIo:
  405      * There are three extra parameters that must be passed to the
  406      * handler via the context:
  407      *   1) Connection buffer, a resource template from Connection() op
  408      *   2) Length of the above buffer
  409      *   3) Actual access length from the AccessAs() op
  410      *
  411      * Since we pass these extra parameters via the context, which is
  412      * shared between threads, we must lock the context to avoid these
  413      * parameters being changed from another thread before the handler
  414      * has completed running.
  415      *
  416      * In addition, for GeneralPurposeIo, the Address and BitWidth fields
  417      * are defined as follows:
  418      *   1) Address is the pin number index of the field (bit offset from
  419      *      the previous Connection)
  420      *   2) BitWidth is the actual bit length of the field (number of pins)
  421      */
  422     if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS ||
  423          RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&
  424         Context &&
  425         FieldObj)
  426     {
  427 
  428         Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER);
  429         if (ACPI_FAILURE (Status))
  430         {
  431             goto ReEnterInterpreter;
  432         }
  433 
  434         ContextLocked = TRUE;
  435 
  436         /* Get the Connection (ResourceTemplate) buffer */
  437 
  438         Context->Connection = FieldObj->Field.ResourceBuffer;
  439         Context->Length = FieldObj->Field.ResourceLength;
  440         Context->AccessLength = FieldObj->Field.AccessLength;
  441 
  442         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)
  443         {
  444             Address = FieldObj->Field.PinNumberIndex;
  445             BitWidth = FieldObj->Field.BitLength;
  446         }
  447     }
  448 
  449     /* Call the handler */
  450 
  451     Status = Handler (Function, Address, BitWidth, Value, Context,
  452         RegionObj2->Extra.RegionContext);
  453 
  454     if (ContextLocked)
  455     {
  456         AcpiOsReleaseMutex (ContextMutex);
  457     }
  458 
  459     if (ACPI_FAILURE (Status))
  460     {
  461         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
  462             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  463 
  464         /*
  465          * Special case for an EC timeout. These are seen so frequently
  466          * that an additional error message is helpful
  467          */
  468         if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
  469             (Status == AE_TIME))
  470         {
  471             ACPI_ERROR ((AE_INFO,
  472                 "Timeout from EC hardware or EC device driver"));
  473         }
  474     }
  475 
  476 ReEnterInterpreter:
  477     if (!(HandlerDesc->AddressSpace.HandlerFlags &
  478         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
  479     {
  480         /*
  481          * We just returned from a non-default handler, we must re-enter the
  482          * interpreter
  483          */
  484         AcpiExEnterInterpreter ();
  485     }
  486 
  487     return_ACPI_STATUS (Status);
  488 }
  489 
  490 
  491 /*******************************************************************************
  492  *
  493  * FUNCTION:    AcpiEvDetachRegion
  494  *
  495  * PARAMETERS:  RegionObj           - Region Object
  496  *              AcpiNsIsLocked      - Namespace Region Already Locked?
  497  *
  498  * RETURN:      None
  499  *
  500  * DESCRIPTION: Break the association between the handler and the region
  501  *              this is a two way association.
  502  *
  503  ******************************************************************************/
  504 
  505 void
  506 AcpiEvDetachRegion (
  507     ACPI_OPERAND_OBJECT     *RegionObj,
  508     BOOLEAN                 AcpiNsIsLocked)
  509 {
  510     ACPI_OPERAND_OBJECT     *HandlerObj;
  511     ACPI_OPERAND_OBJECT     *ObjDesc;
  512     ACPI_OPERAND_OBJECT     *StartDesc;
  513     ACPI_OPERAND_OBJECT     **LastObjPtr;
  514     ACPI_ADR_SPACE_SETUP    RegionSetup;
  515     void                    **RegionContext;
  516     ACPI_OPERAND_OBJECT     *RegionObj2;
  517     ACPI_STATUS             Status;
  518 
  519 
  520     ACPI_FUNCTION_TRACE (EvDetachRegion);
  521 
  522 
  523     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
  524     if (!RegionObj2)
  525     {
  526         return_VOID;
  527     }
  528     RegionContext = &RegionObj2->Extra.RegionContext;
  529 
  530     /* Get the address handler from the region object */
  531 
  532     HandlerObj = RegionObj->Region.Handler;
  533     if (!HandlerObj)
  534     {
  535         /* This region has no handler, all done */
  536 
  537         return_VOID;
  538     }
  539 
  540     /* Find this region in the handler's list */
  541 
  542     ObjDesc = HandlerObj->AddressSpace.RegionList;
  543     StartDesc = ObjDesc;
  544     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
  545 
  546     while (ObjDesc)
  547     {
  548         /* Is this the correct Region? */
  549 
  550         if (ObjDesc == RegionObj)
  551         {
  552             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
  553                 "Removing Region %p from address handler %p\n",
  554                 RegionObj, HandlerObj));
  555 
  556             /* This is it, remove it from the handler's list */
  557 
  558             *LastObjPtr = ObjDesc->Region.Next;
  559             ObjDesc->Region.Next = NULL;        /* Must clear field */
  560 
  561             if (AcpiNsIsLocked)
  562             {
  563                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
  564                 if (ACPI_FAILURE (Status))
  565                 {
  566                     return_VOID;
  567                 }
  568             }
  569 
  570             /* Now stop region accesses by executing the _REG method */
  571 
  572             Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
  573             if (ACPI_FAILURE (Status))
  574             {
  575                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
  576                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  577             }
  578 
  579             if (AcpiNsIsLocked)
  580             {
  581                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
  582                 if (ACPI_FAILURE (Status))
  583                 {
  584                     return_VOID;
  585                 }
  586             }
  587 
  588             /*
  589              * If the region has been activated, call the setup handler with
  590              * the deactivate notification
  591              */
  592             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
  593             {
  594                 RegionSetup = HandlerObj->AddressSpace.Setup;
  595                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
  596                     HandlerObj->AddressSpace.Context, RegionContext);
  597 
  598                 /*
  599                  * RegionContext should have been released by the deactivate
  600                  * operation. We don't need access to it anymore here.
  601                  */
  602                 if (RegionContext)
  603                 {
  604                     *RegionContext = NULL;
  605                 }
  606 
  607                 /* Init routine may fail, Just ignore errors */
  608 
  609                 if (ACPI_FAILURE (Status))
  610                 {
  611                     ACPI_EXCEPTION ((AE_INFO, Status,
  612                         "from region handler - deactivate, [%s]",
  613                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  614                 }
  615 
  616                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
  617             }
  618 
  619             /*
  620              * Remove handler reference in the region
  621              *
  622              * NOTE: this doesn't mean that the region goes away, the region
  623              * is just inaccessible as indicated to the _REG method
  624              *
  625              * If the region is on the handler's list, this must be the
  626              * region's handler
  627              */
  628             RegionObj->Region.Handler = NULL;
  629             AcpiUtRemoveReference (HandlerObj);
  630 
  631             return_VOID;
  632         }
  633 
  634         /* Walk the linked list of handlers */
  635 
  636         LastObjPtr = &ObjDesc->Region.Next;
  637         ObjDesc = ObjDesc->Region.Next;
  638 
  639         /* Prevent infinite loop if list is corrupted */
  640 
  641         if (ObjDesc == StartDesc)
  642         {
  643             ACPI_ERROR ((AE_INFO,
  644                 "Circular handler list in region object %p",
  645                 RegionObj));
  646             return_VOID;
  647         }
  648     }
  649 
  650     /* If we get here, the region was not in the handler's region list */
  651 
  652     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
  653         "Cannot remove region %p from address handler %p\n",
  654         RegionObj, HandlerObj));
  655 
  656     return_VOID;
  657 }
  658 
  659 
  660 /*******************************************************************************
  661  *
  662  * FUNCTION:    AcpiEvAttachRegion
  663  *
  664  * PARAMETERS:  HandlerObj          - Handler Object
  665  *              RegionObj           - Region Object
  666  *              AcpiNsIsLocked      - Namespace Region Already Locked?
  667  *
  668  * RETURN:      None
  669  *
  670  * DESCRIPTION: Create the association between the handler and the region
  671  *              this is a two way association.
  672  *
  673  ******************************************************************************/
  674 
  675 ACPI_STATUS
  676 AcpiEvAttachRegion (
  677     ACPI_OPERAND_OBJECT     *HandlerObj,
  678     ACPI_OPERAND_OBJECT     *RegionObj,
  679     BOOLEAN                 AcpiNsIsLocked)
  680 {
  681 
  682     ACPI_FUNCTION_TRACE (EvAttachRegion);
  683 
  684 
  685     /* Install the region's handler */
  686 
  687     if (RegionObj->Region.Handler)
  688     {
  689         return_ACPI_STATUS (AE_ALREADY_EXISTS);
  690     }
  691 
  692     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
  693         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
  694         AcpiUtGetNodeName (RegionObj->Region.Node),
  695         RegionObj, HandlerObj,
  696         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
  697 
  698     /* Link this region to the front of the handler's list */
  699 
  700     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
  701     HandlerObj->AddressSpace.RegionList = RegionObj;
  702     RegionObj->Region.Handler = HandlerObj;
  703     AcpiUtAddReference (HandlerObj);
  704 
  705     return_ACPI_STATUS (AE_OK);
  706 }
  707 
  708 
  709 /*******************************************************************************
  710  *
  711  * FUNCTION:    AcpiEvExecuteRegMethod
  712  *
  713  * PARAMETERS:  RegionObj           - Region object
  714  *              Function            - Passed to _REG: On (1) or Off (0)
  715  *
  716  * RETURN:      Status
  717  *
  718  * DESCRIPTION: Execute _REG method for a region
  719  *
  720  ******************************************************************************/
  721 
  722 ACPI_STATUS
  723 AcpiEvExecuteRegMethod (
  724     ACPI_OPERAND_OBJECT     *RegionObj,
  725     UINT32                  Function)
  726 {
  727     ACPI_EVALUATE_INFO      *Info;
  728     ACPI_OPERAND_OBJECT     *Args[3];
  729     ACPI_OPERAND_OBJECT     *RegionObj2;
  730     const ACPI_NAME         *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG);
  731     ACPI_NAMESPACE_NODE     *MethodNode;
  732     ACPI_NAMESPACE_NODE     *Node;
  733     ACPI_STATUS             Status;
  734 
  735 
  736     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
  737 
  738 
  739     if (!AcpiGbl_NamespaceInitialized ||
  740         RegionObj->Region.Handler == NULL)
  741     {
  742         return_ACPI_STATUS (AE_OK);
  743     }
  744 
  745     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
  746     if (!RegionObj2)
  747     {
  748         return_ACPI_STATUS (AE_NOT_EXIST);
  749     }
  750 
  751     /*
  752      * Find any "_REG" method associated with this region definition.
  753      * The method should always be updated as this function may be
  754      * invoked after a namespace change.
  755      */
  756     Node = RegionObj->Region.Node->Parent;
  757     Status = AcpiNsSearchOneScope (
  758         *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
  759     if (ACPI_SUCCESS (Status))
  760     {
  761         /*
  762          * The _REG method is optional and there can be only one per
  763          * region definition. This will be executed when the handler is
  764          * attached or removed.
  765          */
  766         RegionObj2->Extra.Method_REG = MethodNode;
  767     }
  768     if (RegionObj2->Extra.Method_REG == NULL)
  769     {
  770         return_ACPI_STATUS (AE_OK);
  771     }
  772 
  773     /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
  774 
  775     if ((Function == ACPI_REG_CONNECT &&
  776         RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) ||
  777         (Function == ACPI_REG_DISCONNECT &&
  778          !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED)))
  779     {
  780         return_ACPI_STATUS (AE_OK);
  781     }
  782 
  783     /* Allocate and initialize the evaluation information block */
  784 
  785     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
  786     if (!Info)
  787     {
  788         return_ACPI_STATUS (AE_NO_MEMORY);
  789     }
  790 
  791     Info->PrefixNode = RegionObj2->Extra.Method_REG;
  792     Info->RelativePathname = NULL;
  793     Info->Parameters = Args;
  794     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
  795 
  796     /*
  797      * The _REG method has two arguments:
  798      *
  799      * Arg0 - Integer:
  800      *  Operation region space ID Same value as RegionObj->Region.SpaceId
  801      *
  802      * Arg1 - Integer:
  803      *  connection status 1 for connecting the handler, 0 for disconnecting
  804      *  the handler (Passed as a parameter)
  805      */
  806     Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
  807     if (!Args[0])
  808     {
  809         Status = AE_NO_MEMORY;
  810         goto Cleanup1;
  811     }
  812 
  813     Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
  814     if (!Args[1])
  815     {
  816         Status = AE_NO_MEMORY;
  817         goto Cleanup2;
  818     }
  819 
  820     Args[2] = NULL; /* Terminate list */
  821 
  822     /* Execute the method, no return value */
  823 
  824     ACPI_DEBUG_EXEC (
  825         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
  826 
  827     Status = AcpiNsEvaluate (Info);
  828     AcpiUtRemoveReference (Args[1]);
  829 
  830     if (ACPI_FAILURE (Status))
  831     {
  832         goto Cleanup2;
  833     }
  834 
  835     if (Function == ACPI_REG_CONNECT)
  836     {
  837         RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED;
  838     }
  839     else
  840     {
  841         RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED;
  842     }
  843 
  844 Cleanup2:
  845     AcpiUtRemoveReference (Args[0]);
  846 
  847 Cleanup1:
  848     ACPI_FREE (Info);
  849     return_ACPI_STATUS (Status);
  850 }
  851 
  852 
  853 /*******************************************************************************
  854  *
  855  * FUNCTION:    AcpiEvExecuteRegMethods
  856  *
  857  * PARAMETERS:  Node            - Namespace node for the device
  858  *              SpaceId         - The address space ID
  859  *              Function        - Passed to _REG: On (1) or Off (0)
  860  *
  861  * RETURN:      None
  862  *
  863  * DESCRIPTION: Run all _REG methods for the input Space ID;
  864  *              Note: assumes namespace is locked, or system init time.
  865  *
  866  ******************************************************************************/
  867 
  868 void
  869 AcpiEvExecuteRegMethods (
  870     ACPI_NAMESPACE_NODE     *Node,
  871     ACPI_ADR_SPACE_TYPE     SpaceId,
  872     UINT32                  Function)
  873 {
  874     ACPI_REG_WALK_INFO      Info;
  875 
  876 
  877     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
  878 
  879     /*
  880      * These address spaces do not need a call to _REG, since the ACPI
  881      * specification defines them as: "must always be accessible". Since
  882      * they never change state (never become unavailable), no need to ever
  883      * call _REG on them. Also, a DataTable is not a "real" address space,
  884      * so do not call _REG. September 2018.
  885      */
  886     if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
  887         (SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) ||
  888         (SpaceId == ACPI_ADR_SPACE_DATA_TABLE))
  889     {
  890         return_VOID;
  891     }
  892 
  893     Info.SpaceId = SpaceId;
  894     Info.Function = Function;
  895     Info.RegRunCount = 0;
  896 
  897     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
  898         "    Running _REG methods for SpaceId %s\n",
  899         AcpiUtGetRegionName (Info.SpaceId)));
  900 
  901     /*
  902      * Run all _REG methods for all Operation Regions for this space ID. This
  903      * is a separate walk in order to handle any interdependencies between
  904      * regions and _REG methods. (i.e. handlers must be installed for all
  905      * regions of this Space ID before we can run any _REG methods)
  906      */
  907     (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
  908         ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL);
  909 
  910     /*
  911      * Special case for EC and GPIO: handle "orphan" _REG methods with
  912      * no region.
  913      */
  914     if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO)
  915     {
  916         AcpiEvExecuteOrphanRegMethod (Node, SpaceId);
  917     }
  918 
  919     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
  920         "    Executed %u _REG methods for SpaceId %s\n",
  921         Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId)));
  922 
  923     return_VOID;
  924 }
  925 
  926 
  927 /*******************************************************************************
  928  *
  929  * FUNCTION:    AcpiEvRegRun
  930  *
  931  * PARAMETERS:  WalkNamespace callback
  932  *
  933  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
  934  *
  935  ******************************************************************************/
  936 
  937 static ACPI_STATUS
  938 AcpiEvRegRun (
  939     ACPI_HANDLE             ObjHandle,
  940     UINT32                  Level,
  941     void                    *Context,
  942     void                    **ReturnValue)
  943 {
  944     ACPI_OPERAND_OBJECT     *ObjDesc;
  945     ACPI_NAMESPACE_NODE     *Node;
  946     ACPI_STATUS             Status;
  947     ACPI_REG_WALK_INFO      *Info;
  948 
  949 
  950     Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, Context);
  951 
  952     /* Convert and validate the device handle */
  953 
  954     Node = AcpiNsValidateHandle (ObjHandle);
  955     if (!Node)
  956     {
  957         return (AE_BAD_PARAMETER);
  958     }
  959 
  960     /*
  961      * We only care about regions and objects that are allowed to have
  962      * address space handlers
  963      */
  964     if ((Node->Type != ACPI_TYPE_REGION) &&
  965         (Node != AcpiGbl_RootNode))
  966     {
  967         return (AE_OK);
  968     }
  969 
  970     /* Check for an existing internal object */
  971 
  972     ObjDesc = AcpiNsGetAttachedObject (Node);
  973     if (!ObjDesc)
  974     {
  975         /* No object, just exit */
  976 
  977         return (AE_OK);
  978     }
  979 
  980     /* Object is a Region */
  981 
  982     if (ObjDesc->Region.SpaceId != Info->SpaceId)
  983     {
  984         /* This region is for a different address space, just ignore it */
  985 
  986         return (AE_OK);
  987     }
  988 
  989     Info->RegRunCount++;
  990     Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function);
  991     return (Status);
  992 }
  993 
  994 
  995 /*******************************************************************************
  996  *
  997  * FUNCTION:    AcpiEvExecuteOrphanRegMethod
  998  *
  999  * PARAMETERS:  DeviceNode          - Namespace node for an ACPI device
 1000  *              SpaceId             - The address space ID
 1001  *
 1002  * RETURN:      None
 1003  *
 1004  * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI
 1005  *              device. This is a _REG method that has no corresponding region
 1006  *              within the device's scope. ACPI tables depending on these
 1007  *              "orphan" _REG methods have been seen for both EC and GPIO
 1008  *              Operation Regions. Presumably the Windows ACPI implementation
 1009  *              always calls the _REG method independent of the presence of
 1010  *              an actual Operation Region with the correct address space ID.
 1011  *
 1012  *  MUTEX:      Assumes the namespace is locked
 1013  *
 1014  ******************************************************************************/
 1015 
 1016 static void
 1017 AcpiEvExecuteOrphanRegMethod (
 1018     ACPI_NAMESPACE_NODE     *DeviceNode,
 1019     ACPI_ADR_SPACE_TYPE     SpaceId)
 1020 {
 1021     ACPI_HANDLE             RegMethod;
 1022     ACPI_NAMESPACE_NODE     *NextNode;
 1023     ACPI_STATUS             Status;
 1024     ACPI_OBJECT_LIST        Args;
 1025     ACPI_OBJECT             Objects[2];
 1026 
 1027 
 1028     ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod);
 1029 
 1030 
 1031     if (!DeviceNode)
 1032     {
 1033         return_VOID;
 1034     }
 1035 
 1036     /* Namespace is currently locked, must release */
 1037 
 1038     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 1039 
 1040     /* Get a handle to a _REG method immediately under the EC device */
 1041 
 1042     Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod);
 1043     if (ACPI_FAILURE (Status))
 1044     {
 1045         goto Exit; /* There is no _REG method present */
 1046     }
 1047 
 1048     /*
 1049      * Execute the _REG method only if there is no Operation Region in
 1050      * this scope with the Embedded Controller space ID. Otherwise, it
 1051      * will already have been executed. Note, this allows for Regions
 1052      * with other space IDs to be present; but the code below will then
 1053      * execute the _REG method with the EmbeddedControl SpaceID argument.
 1054      */
 1055     NextNode = AcpiNsGetNextNode (DeviceNode, NULL);
 1056     while (NextNode)
 1057     {
 1058         if ((NextNode->Type == ACPI_TYPE_REGION) &&
 1059             (NextNode->Object) &&
 1060             (NextNode->Object->Region.SpaceId == SpaceId))
 1061         {
 1062             goto Exit; /* Do not execute the _REG */
 1063         }
 1064 
 1065         NextNode = AcpiNsGetNextNode (DeviceNode, NextNode);
 1066     }
 1067 
 1068     /* Evaluate the _REG(SpaceId,Connect) method */
 1069 
 1070     Args.Count = 2;
 1071     Args.Pointer = Objects;
 1072     Objects[0].Type = ACPI_TYPE_INTEGER;
 1073     Objects[0].Integer.Value = SpaceId;
 1074     Objects[1].Type = ACPI_TYPE_INTEGER;
 1075     Objects[1].Integer.Value = ACPI_REG_CONNECT;
 1076 
 1077     (void) AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
 1078 
 1079 Exit:
 1080     /* We ignore all errors from above, don't care */
 1081 
 1082     (void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 1083     return_VOID;
 1084 }

Cache object: a29564ef17139edda2462bd91242aa05


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.