Path: blob/main/sys/contrib/dev/acpica/components/events/evregion.c
48525 views
/******************************************************************************1*2* Module Name: evregion - Operation Region support3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/include/acpi.h>152#include <contrib/dev/acpica/include/accommon.h>153#include <contrib/dev/acpica/include/acevents.h>154#include <contrib/dev/acpica/include/acnamesp.h>155#include <contrib/dev/acpica/include/acinterp.h>156157#define _COMPONENT ACPI_EVENTS158ACPI_MODULE_NAME ("evregion")159160161extern UINT8 AcpiGbl_DefaultAddressSpaces[];162163/* Local prototypes */164165static void166AcpiEvExecuteOrphanRegMethod (167ACPI_NAMESPACE_NODE *DeviceNode,168ACPI_ADR_SPACE_TYPE SpaceId);169170171static ACPI_STATUS172AcpiEvRegRun (173ACPI_HANDLE ObjHandle,174UINT32 Level,175void *Context,176void **ReturnValue);177178179/*******************************************************************************180*181* FUNCTION: AcpiEvInitializeOpRegions182*183* PARAMETERS: None184*185* RETURN: Status186*187* DESCRIPTION: Execute _REG methods for all Operation Regions that have188* an installed default region handler.189*190******************************************************************************/191192ACPI_STATUS193AcpiEvInitializeOpRegions (194void)195{196ACPI_STATUS Status;197UINT32 i;198199200ACPI_FUNCTION_TRACE (EvInitializeOpRegions);201202203Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);204if (ACPI_FAILURE (Status))205{206return_ACPI_STATUS (Status);207}208209/* Run the _REG methods for OpRegions in each default address space */210211for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)212{213/*214* Make sure the installed handler is the DEFAULT handler. If not the215* default, the _REG methods will have already been run (when the216* handler was installed)217*/218if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,219AcpiGbl_DefaultAddressSpaces[i]))220{221AcpiEvExecuteRegMethods (AcpiGbl_RootNode,222AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT);223}224}225226(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);227return_ACPI_STATUS (Status);228}229230231/*******************************************************************************232*233* FUNCTION: AcpiEvAddressSpaceDispatch234*235* PARAMETERS: RegionObj - Internal region object236* FieldObj - Corresponding field. Can be NULL.237* Function - Read or Write operation238* RegionOffset - Where in the region to read or write239* BitWidth - Field width in bits (8, 16, 32, or 64)240* Value - Pointer to in or out value, must be241* a full 64-bit integer242*243* RETURN: Status244*245* DESCRIPTION: Dispatch an address space or operation region access to246* a previously installed handler.247*248* NOTE: During early initialization, we always install the default region249* handlers for Memory, I/O and PCI_Config. This ensures that these operation250* region address spaces are always available as per the ACPI specification.251* This is especially needed in order to support the execution of252* module-level AML code during loading of the ACPI tables.253*254******************************************************************************/255256ACPI_STATUS257AcpiEvAddressSpaceDispatch (258ACPI_OPERAND_OBJECT *RegionObj,259ACPI_OPERAND_OBJECT *FieldObj,260UINT32 Function,261UINT32 RegionOffset,262UINT32 BitWidth,263UINT64 *Value)264{265ACPI_STATUS Status;266ACPI_ADR_SPACE_HANDLER Handler;267ACPI_ADR_SPACE_SETUP RegionSetup;268ACPI_OPERAND_OBJECT *HandlerDesc;269ACPI_OPERAND_OBJECT *RegionObj2;270void *RegionContext = NULL;271ACPI_CONNECTION_INFO *Context;272ACPI_MUTEX ContextMutex;273BOOLEAN ContextLocked;274ACPI_PHYSICAL_ADDRESS Address;275276277ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);278279280RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);281if (!RegionObj2)282{283return_ACPI_STATUS (AE_NOT_EXIST);284}285286/* Ensure that there is a handler associated with this region */287288HandlerDesc = RegionObj->Region.Handler;289if (!HandlerDesc)290{291ACPI_ERROR ((AE_INFO,292"No handler for Region [%4.4s] (%p) [%s]",293AcpiUtGetNodeName (RegionObj->Region.Node),294RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));295296return_ACPI_STATUS (AE_NOT_EXIST);297}298299Context = HandlerDesc->AddressSpace.Context;300ContextMutex = HandlerDesc->AddressSpace.ContextMutex;301ContextLocked = FALSE;302303/*304* It may be the case that the region has never been initialized.305* Some types of regions require special init code306*/307if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))308{309/* This region has not been initialized yet, do it */310311RegionSetup = HandlerDesc->AddressSpace.Setup;312if (!RegionSetup)313{314/* No initialization routine, exit with error */315316ACPI_ERROR ((AE_INFO,317"No init routine for region(%p) [%s]",318RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));319return_ACPI_STATUS (AE_NOT_EXIST);320}321322if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)323{324ACPI_PCC_INFO *Ctx = HandlerDesc->AddressSpace.Context;325326Ctx->InternalBuffer = FieldObj->Field.InternalPccBuffer;327Ctx->Length = (UINT16) RegionObj->Region.Length;328Ctx->SubspaceId = (UINT8) RegionObj->Region.Address;329}330331if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE)332{333ACPI_FFH_INFO *Ctx = HandlerDesc->AddressSpace.Context;334335Ctx->Length = RegionObj->Region.Length;336Ctx->Offset = RegionObj->Region.Address;337}338339/*340* We must exit the interpreter because the region setup will341* potentially execute control methods (for example, the _REG method342* for this region)343*/344AcpiExExitInterpreter ();345346Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,347Context, &RegionContext);348349/* Re-enter the interpreter */350351AcpiExEnterInterpreter ();352353/* Check for failure of the Region Setup */354355if (ACPI_FAILURE (Status))356{357ACPI_EXCEPTION ((AE_INFO, Status,358"During region initialization: [%s]",359AcpiUtGetRegionName (RegionObj->Region.SpaceId)));360return_ACPI_STATUS (Status);361}362363/* Region initialization may have been completed by RegionSetup */364365if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))366{367RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;368369/*370* Save the returned context for use in all accesses to371* the handler for this particular region372*/373if (!(RegionObj2->Extra.RegionContext))374{375RegionObj2->Extra.RegionContext = RegionContext;376}377}378}379380/* We have everything we need, we can invoke the address space handler */381382Handler = HandlerDesc->AddressSpace.Handler;383Address = (RegionObj->Region.Address + RegionOffset);384385ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,386"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",387&RegionObj->Region.Handler->AddressSpace, Handler,388ACPI_FORMAT_UINT64 (Address),389AcpiUtGetRegionName (RegionObj->Region.SpaceId)));390391if (!(HandlerDesc->AddressSpace.HandlerFlags &392ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))393{394/*395* For handlers other than the default (supplied) handlers, we must396* exit the interpreter because the handler *might* block -- we don't397* know what it will do, so we can't hold the lock on the interpreter.398*/399AcpiExExitInterpreter();400}401402/*403* Special handling for GenericSerialBus and GeneralPurposeIo:404* There are three extra parameters that must be passed to the405* handler via the context:406* 1) Connection buffer, a resource template from Connection() op407* 2) Length of the above buffer408* 3) Actual access length from the AccessAs() op409*410* Since we pass these extra parameters via the context, which is411* shared between threads, we must lock the context to avoid these412* parameters being changed from another thread before the handler413* has completed running.414*415* In addition, for GeneralPurposeIo, the Address and BitWidth fields416* are defined as follows:417* 1) Address is the pin number index of the field (bit offset from418* the previous Connection)419* 2) BitWidth is the actual bit length of the field (number of pins)420*/421if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS ||422RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&423Context &&424FieldObj)425{426427Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER);428if (ACPI_FAILURE (Status))429{430goto ReEnterInterpreter;431}432433ContextLocked = TRUE;434435/* Get the Connection (ResourceTemplate) buffer */436437Context->Connection = FieldObj->Field.ResourceBuffer;438Context->Length = FieldObj->Field.ResourceLength;439Context->AccessLength = FieldObj->Field.AccessLength;440441if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)442{443Address = FieldObj->Field.PinNumberIndex;444BitWidth = FieldObj->Field.BitLength;445}446}447448/* Call the handler */449450Status = Handler (Function, Address, BitWidth, Value, Context,451RegionObj2->Extra.RegionContext);452453if (ContextLocked)454{455AcpiOsReleaseMutex (ContextMutex);456}457458if (ACPI_FAILURE (Status))459{460ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",461AcpiUtGetRegionName (RegionObj->Region.SpaceId)));462463/*464* Special case for an EC timeout. These are seen so frequently465* that an additional error message is helpful466*/467if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&468(Status == AE_TIME))469{470ACPI_ERROR ((AE_INFO,471"Timeout from EC hardware or EC device driver"));472}473}474475ReEnterInterpreter:476if (!(HandlerDesc->AddressSpace.HandlerFlags &477ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))478{479/*480* We just returned from a non-default handler, we must re-enter the481* interpreter482*/483AcpiExEnterInterpreter ();484}485486return_ACPI_STATUS (Status);487}488489490/*******************************************************************************491*492* FUNCTION: AcpiEvDetachRegion493*494* PARAMETERS: RegionObj - Region Object495* AcpiNsIsLocked - Namespace Region Already Locked?496*497* RETURN: None498*499* DESCRIPTION: Break the association between the handler and the region500* this is a two way association.501*502******************************************************************************/503504void505AcpiEvDetachRegion (506ACPI_OPERAND_OBJECT *RegionObj,507BOOLEAN AcpiNsIsLocked)508{509ACPI_OPERAND_OBJECT *HandlerObj;510ACPI_OPERAND_OBJECT *ObjDesc;511ACPI_OPERAND_OBJECT *StartDesc;512ACPI_OPERAND_OBJECT **LastObjPtr;513ACPI_ADR_SPACE_SETUP RegionSetup;514void **RegionContext;515ACPI_OPERAND_OBJECT *RegionObj2;516ACPI_STATUS Status;517518519ACPI_FUNCTION_TRACE (EvDetachRegion);520521522RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);523if (!RegionObj2)524{525return_VOID;526}527RegionContext = &RegionObj2->Extra.RegionContext;528529/* Get the address handler from the region object */530531HandlerObj = RegionObj->Region.Handler;532if (!HandlerObj)533{534/* This region has no handler, all done */535536return_VOID;537}538539/* Find this region in the handler's list */540541ObjDesc = HandlerObj->AddressSpace.RegionList;542StartDesc = ObjDesc;543LastObjPtr = &HandlerObj->AddressSpace.RegionList;544545while (ObjDesc)546{547/* Is this the correct Region? */548549if (ObjDesc == RegionObj)550{551ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,552"Removing Region %p from address handler %p\n",553RegionObj, HandlerObj));554555/* This is it, remove it from the handler's list */556557*LastObjPtr = ObjDesc->Region.Next;558ObjDesc->Region.Next = NULL; /* Must clear field */559560if (AcpiNsIsLocked)561{562Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);563if (ACPI_FAILURE (Status))564{565return_VOID;566}567}568569/* Now stop region accesses by executing the _REG method */570571Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);572if (ACPI_FAILURE (Status))573{574ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",575AcpiUtGetRegionName (RegionObj->Region.SpaceId)));576}577578if (AcpiNsIsLocked)579{580Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);581if (ACPI_FAILURE (Status))582{583return_VOID;584}585}586587/*588* If the region has been activated, call the setup handler with589* the deactivate notification590*/591if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)592{593RegionSetup = HandlerObj->AddressSpace.Setup;594Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,595HandlerObj->AddressSpace.Context, RegionContext);596597/*598* RegionContext should have been released by the deactivate599* operation. We don't need access to it anymore here.600*/601if (RegionContext)602{603*RegionContext = NULL;604}605606/* Init routine may fail, Just ignore errors */607608if (ACPI_FAILURE (Status))609{610ACPI_EXCEPTION ((AE_INFO, Status,611"from region handler - deactivate, [%s]",612AcpiUtGetRegionName (RegionObj->Region.SpaceId)));613}614615RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);616}617618/*619* Remove handler reference in the region620*621* NOTE: this doesn't mean that the region goes away, the region622* is just inaccessible as indicated to the _REG method623*624* If the region is on the handler's list, this must be the625* region's handler626*/627RegionObj->Region.Handler = NULL;628AcpiUtRemoveReference (HandlerObj);629630return_VOID;631}632633/* Walk the linked list of handlers */634635LastObjPtr = &ObjDesc->Region.Next;636ObjDesc = ObjDesc->Region.Next;637638/* Prevent infinite loop if list is corrupted */639640if (ObjDesc == StartDesc)641{642ACPI_ERROR ((AE_INFO,643"Circular handler list in region object %p",644RegionObj));645return_VOID;646}647}648649/* If we get here, the region was not in the handler's region list */650651ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,652"Cannot remove region %p from address handler %p\n",653RegionObj, HandlerObj));654655return_VOID;656}657658659/*******************************************************************************660*661* FUNCTION: AcpiEvAttachRegion662*663* PARAMETERS: HandlerObj - Handler Object664* RegionObj - Region Object665* AcpiNsIsLocked - Namespace Region Already Locked?666*667* RETURN: None668*669* DESCRIPTION: Create the association between the handler and the region670* this is a two way association.671*672******************************************************************************/673674ACPI_STATUS675AcpiEvAttachRegion (676ACPI_OPERAND_OBJECT *HandlerObj,677ACPI_OPERAND_OBJECT *RegionObj,678BOOLEAN AcpiNsIsLocked)679{680681ACPI_FUNCTION_TRACE (EvAttachRegion);682683684/* Install the region's handler */685686if (RegionObj->Region.Handler)687{688return_ACPI_STATUS (AE_ALREADY_EXISTS);689}690691ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,692"Adding Region [%4.4s] %p to address handler %p [%s]\n",693AcpiUtGetNodeName (RegionObj->Region.Node),694RegionObj, HandlerObj,695AcpiUtGetRegionName (RegionObj->Region.SpaceId)));696697/* Link this region to the front of the handler's list */698699RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;700HandlerObj->AddressSpace.RegionList = RegionObj;701RegionObj->Region.Handler = HandlerObj;702AcpiUtAddReference (HandlerObj);703704return_ACPI_STATUS (AE_OK);705}706707708/*******************************************************************************709*710* FUNCTION: AcpiEvExecuteRegMethod711*712* PARAMETERS: RegionObj - Region object713* Function - Passed to _REG: On (1) or Off (0)714*715* RETURN: Status716*717* DESCRIPTION: Execute _REG method for a region718*719******************************************************************************/720721ACPI_STATUS722AcpiEvExecuteRegMethod (723ACPI_OPERAND_OBJECT *RegionObj,724UINT32 Function)725{726ACPI_EVALUATE_INFO *Info;727ACPI_OPERAND_OBJECT *Args[3];728ACPI_OPERAND_OBJECT *RegionObj2;729const ACPI_NAME *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG);730ACPI_NAMESPACE_NODE *MethodNode;731ACPI_NAMESPACE_NODE *Node;732ACPI_STATUS Status;733734735ACPI_FUNCTION_TRACE (EvExecuteRegMethod);736737738if (!AcpiGbl_NamespaceInitialized ||739RegionObj->Region.Handler == NULL)740{741return_ACPI_STATUS (AE_OK);742}743744RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);745if (!RegionObj2)746{747return_ACPI_STATUS (AE_NOT_EXIST);748}749750/*751* Find any "_REG" method associated with this region definition.752* The method should always be updated as this function may be753* invoked after a namespace change.754*/755Node = RegionObj->Region.Node->Parent;756Status = AcpiNsSearchOneScope (757*RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);758if (ACPI_SUCCESS (Status))759{760/*761* The _REG method is optional and there can be only one per762* region definition. This will be executed when the handler is763* attached or removed.764*/765RegionObj2->Extra.Method_REG = MethodNode;766}767if (RegionObj2->Extra.Method_REG == NULL)768{769return_ACPI_STATUS (AE_OK);770}771772/* _REG(DISCONNECT) should be paired with _REG(CONNECT) */773774if ((Function == ACPI_REG_CONNECT &&775RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) ||776(Function == ACPI_REG_DISCONNECT &&777!(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED)))778{779return_ACPI_STATUS (AE_OK);780}781782/* Allocate and initialize the evaluation information block */783784Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));785if (!Info)786{787return_ACPI_STATUS (AE_NO_MEMORY);788}789790Info->PrefixNode = RegionObj2->Extra.Method_REG;791Info->RelativePathname = NULL;792Info->Parameters = Args;793Info->Flags = ACPI_IGNORE_RETURN_VALUE;794795/*796* The _REG method has two arguments:797*798* Arg0 - Integer:799* Operation region space ID Same value as RegionObj->Region.SpaceId800*801* Arg1 - Integer:802* connection status 1 for connecting the handler, 0 for disconnecting803* the handler (Passed as a parameter)804*/805Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);806if (!Args[0])807{808Status = AE_NO_MEMORY;809goto Cleanup1;810}811812Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);813if (!Args[1])814{815Status = AE_NO_MEMORY;816goto Cleanup2;817}818819Args[2] = NULL; /* Terminate list */820821/* Execute the method, no return value */822823ACPI_DEBUG_EXEC (824AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));825826Status = AcpiNsEvaluate (Info);827AcpiUtRemoveReference (Args[1]);828829if (ACPI_FAILURE (Status))830{831goto Cleanup2;832}833834if (Function == ACPI_REG_CONNECT)835{836RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED;837}838else839{840RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED;841}842843Cleanup2:844AcpiUtRemoveReference (Args[0]);845846Cleanup1:847ACPI_FREE (Info);848return_ACPI_STATUS (Status);849}850851852/*******************************************************************************853*854* FUNCTION: AcpiEvExecuteRegMethods855*856* PARAMETERS: Node - Namespace node for the device857* SpaceId - The address space ID858* Function - Passed to _REG: On (1) or Off (0)859*860* RETURN: None861*862* DESCRIPTION: Run all _REG methods for the input Space ID;863* Note: assumes namespace is locked, or system init time.864*865******************************************************************************/866867void868AcpiEvExecuteRegMethods (869ACPI_NAMESPACE_NODE *Node,870ACPI_ADR_SPACE_TYPE SpaceId,871UINT32 Function)872{873ACPI_REG_WALK_INFO Info;874875876ACPI_FUNCTION_TRACE (EvExecuteRegMethods);877878/*879* These address spaces do not need a call to _REG, since the ACPI880* specification defines them as: "must always be accessible". Since881* they never change state (never become unavailable), no need to ever882* call _REG on them. Also, a DataTable is not a "real" address space,883* so do not call _REG. September 2018.884*/885if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||886(SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) ||887(SpaceId == ACPI_ADR_SPACE_DATA_TABLE))888{889return_VOID;890}891892Info.SpaceId = SpaceId;893Info.Function = Function;894Info.RegRunCount = 0;895896ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,897" Running _REG methods for SpaceId %s\n",898AcpiUtGetRegionName (Info.SpaceId)));899900/*901* Run all _REG methods for all Operation Regions for this space ID. This902* is a separate walk in order to handle any interdependencies between903* regions and _REG methods. (i.e. handlers must be installed for all904* regions of this Space ID before we can run any _REG methods)905*/906(void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,907ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL);908909/*910* Special case for EC and GPIO: handle "orphan" _REG methods with911* no region.912*/913if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO)914{915AcpiEvExecuteOrphanRegMethod (Node, SpaceId);916}917918ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,919" Executed %u _REG methods for SpaceId %s\n",920Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId)));921922return_VOID;923}924925926/*******************************************************************************927*928* FUNCTION: AcpiEvRegRun929*930* PARAMETERS: WalkNamespace callback931*932* DESCRIPTION: Run _REG method for region objects of the requested spaceID933*934******************************************************************************/935936static ACPI_STATUS937AcpiEvRegRun (938ACPI_HANDLE ObjHandle,939UINT32 Level,940void *Context,941void **ReturnValue)942{943ACPI_OPERAND_OBJECT *ObjDesc;944ACPI_NAMESPACE_NODE *Node;945ACPI_STATUS Status;946ACPI_REG_WALK_INFO *Info;947948949Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, Context);950951/* Convert and validate the device handle */952953Node = AcpiNsValidateHandle (ObjHandle);954if (!Node)955{956return (AE_BAD_PARAMETER);957}958959/*960* We only care about regions and objects that are allowed to have961* address space handlers962*/963if ((Node->Type != ACPI_TYPE_REGION) &&964(Node != AcpiGbl_RootNode))965{966return (AE_OK);967}968969/* Check for an existing internal object */970971ObjDesc = AcpiNsGetAttachedObject (Node);972if (!ObjDesc)973{974/* No object, just exit */975976return (AE_OK);977}978979/* Object is a Region */980981if (ObjDesc->Region.SpaceId != Info->SpaceId)982{983/* This region is for a different address space, just ignore it */984985return (AE_OK);986}987988Info->RegRunCount++;989Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function);990return (Status);991}992993994/*******************************************************************************995*996* FUNCTION: AcpiEvExecuteOrphanRegMethod997*998* PARAMETERS: DeviceNode - Namespace node for an ACPI device999* SpaceId - The address space ID1000*1001* RETURN: None1002*1003* DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI1004* device. This is a _REG method that has no corresponding region1005* within the device's scope. ACPI tables depending on these1006* "orphan" _REG methods have been seen for both EC and GPIO1007* Operation Regions. Presumably the Windows ACPI implementation1008* always calls the _REG method independent of the presence of1009* an actual Operation Region with the correct address space ID.1010*1011* MUTEX: Assumes the namespace is locked1012*1013******************************************************************************/10141015static void1016AcpiEvExecuteOrphanRegMethod (1017ACPI_NAMESPACE_NODE *DeviceNode,1018ACPI_ADR_SPACE_TYPE SpaceId)1019{1020ACPI_HANDLE RegMethod;1021ACPI_NAMESPACE_NODE *NextNode;1022ACPI_STATUS Status;1023ACPI_OBJECT_LIST Args;1024ACPI_OBJECT Objects[2];102510261027ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod);102810291030if (!DeviceNode)1031{1032return_VOID;1033}10341035/* Namespace is currently locked, must release */10361037(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);10381039/* Get a handle to a _REG method immediately under the EC device */10401041Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod);1042if (ACPI_FAILURE (Status))1043{1044goto Exit; /* There is no _REG method present */1045}10461047/*1048* Execute the _REG method only if there is no Operation Region in1049* this scope with the Embedded Controller space ID. Otherwise, it1050* will already have been executed. Note, this allows for Regions1051* with other space IDs to be present; but the code below will then1052* execute the _REG method with the EmbeddedControl SpaceID argument.1053*/1054NextNode = AcpiNsGetNextNode (DeviceNode, NULL);1055while (NextNode)1056{1057if ((NextNode->Type == ACPI_TYPE_REGION) &&1058(NextNode->Object) &&1059(NextNode->Object->Region.SpaceId == SpaceId))1060{1061goto Exit; /* Do not execute the _REG */1062}10631064NextNode = AcpiNsGetNextNode (DeviceNode, NextNode);1065}10661067/* Evaluate the _REG(SpaceId,Connect) method */10681069Args.Count = 2;1070Args.Pointer = Objects;1071Objects[0].Type = ACPI_TYPE_INTEGER;1072Objects[0].Integer.Value = SpaceId;1073Objects[1].Type = ACPI_TYPE_INTEGER;1074Objects[1].Integer.Value = ACPI_REG_CONNECT;10751076(void) AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);10771078Exit:1079/* We ignore all errors from above, don't care */10801081(void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);1082return_VOID;1083}108410851086