Path: blob/main/sys/contrib/dev/acpica/components/events/evhandler.c
48524 views
/******************************************************************************1*2* Module Name: evhandler - Support for Address Space handlers3*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 ("evhandler")159160161/* Local prototypes */162163static ACPI_STATUS164AcpiEvInstallHandler (165ACPI_HANDLE ObjHandle,166UINT32 Level,167void *Context,168void **ReturnValue);169170171/* These are the address spaces that will get default handlers */172173UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] =174{175ACPI_ADR_SPACE_SYSTEM_MEMORY,176ACPI_ADR_SPACE_SYSTEM_IO,177ACPI_ADR_SPACE_PCI_CONFIG,178ACPI_ADR_SPACE_DATA_TABLE179};180181182/*******************************************************************************183*184* FUNCTION: AcpiEvInstallRegionHandlers185*186* PARAMETERS: None187*188* RETURN: Status189*190* DESCRIPTION: Installs the core subsystem default address space handlers.191*192******************************************************************************/193194ACPI_STATUS195AcpiEvInstallRegionHandlers (196void)197{198ACPI_STATUS Status;199UINT32 i;200201202ACPI_FUNCTION_TRACE (EvInstallRegionHandlers);203204205Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);206if (ACPI_FAILURE (Status))207{208return_ACPI_STATUS (Status);209}210211/*212* All address spaces (PCI Config, EC, SMBus) are scope dependent and213* registration must occur for a specific device.214*215* In the case of the system memory and IO address spaces there is216* currently no device associated with the address space. For these we217* use the root.218*219* We install the default PCI config space handler at the root so that220* this space is immediately available even though the we have not221* enumerated all the PCI Root Buses yet. This is to conform to the ACPI222* specification which states that the PCI config space must be always223* available -- even though we are nowhere near ready to find the PCI root224* buses at this point.225*226* NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler227* has already been installed (via AcpiInstallAddressSpaceHandler).228* Similar for AE_SAME_HANDLER.229*/230for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)231{232Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode,233AcpiGbl_DefaultAddressSpaces[i],234ACPI_DEFAULT_HANDLER, NULL, NULL);235switch (Status)236{237case AE_OK:238case AE_SAME_HANDLER:239case AE_ALREADY_EXISTS:240241/* These exceptions are all OK */242243Status = AE_OK;244break;245246default:247248goto UnlockAndExit;249}250}251252UnlockAndExit:253(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);254return_ACPI_STATUS (Status);255}256257258/*******************************************************************************259*260* FUNCTION: AcpiEvHasDefaultHandler261*262* PARAMETERS: Node - Namespace node for the device263* SpaceId - The address space ID264*265* RETURN: TRUE if default handler is installed, FALSE otherwise266*267* DESCRIPTION: Check if the default handler is installed for the requested268* space ID.269*270******************************************************************************/271272BOOLEAN273AcpiEvHasDefaultHandler (274ACPI_NAMESPACE_NODE *Node,275ACPI_ADR_SPACE_TYPE SpaceId)276{277ACPI_OPERAND_OBJECT *ObjDesc;278ACPI_OPERAND_OBJECT *HandlerObj;279280281/* Must have an existing internal object */282283ObjDesc = AcpiNsGetAttachedObject (Node);284if (ObjDesc)285{286HandlerObj = ObjDesc->CommonNotify.Handler;287288/* Walk the linked list of handlers for this object */289290while (HandlerObj)291{292if (HandlerObj->AddressSpace.SpaceId == SpaceId)293{294if (HandlerObj->AddressSpace.HandlerFlags &295ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)296{297return (TRUE);298}299}300301HandlerObj = HandlerObj->AddressSpace.Next;302}303}304305return (FALSE);306}307308309/*******************************************************************************310*311* FUNCTION: AcpiEvInstallHandler312*313* PARAMETERS: WalkNamespace callback314*315* DESCRIPTION: This routine installs an address handler into objects that are316* of type Region or Device.317*318* If the Object is a Device, and the device has a handler of319* the same type then the search is terminated in that branch.320*321* This is because the existing handler is closer in proximity322* to any more regions than the one we are trying to install.323*324******************************************************************************/325326static ACPI_STATUS327AcpiEvInstallHandler (328ACPI_HANDLE ObjHandle,329UINT32 Level,330void *Context,331void **ReturnValue)332{333ACPI_OPERAND_OBJECT *HandlerObj;334ACPI_OPERAND_OBJECT *NextHandlerObj;335ACPI_OPERAND_OBJECT *ObjDesc;336ACPI_NAMESPACE_NODE *Node;337ACPI_STATUS Status;338339340ACPI_FUNCTION_NAME (EvInstallHandler);341342343HandlerObj = (ACPI_OPERAND_OBJECT *) Context;344345/* Parameter validation */346347if (!HandlerObj)348{349return (AE_OK);350}351352/* Convert and validate the device handle */353354Node = AcpiNsValidateHandle (ObjHandle);355if (!Node)356{357return (AE_BAD_PARAMETER);358}359360/*361* We only care about regions and objects that are allowed to have362* address space handlers363*/364if ((Node->Type != ACPI_TYPE_DEVICE) &&365(Node->Type != ACPI_TYPE_REGION) &&366(Node != AcpiGbl_RootNode))367{368return (AE_OK);369}370371/* Check for an existing internal object */372373ObjDesc = AcpiNsGetAttachedObject (Node);374if (!ObjDesc)375{376/* No object, just exit */377378return (AE_OK);379}380381/* Devices are handled different than regions */382383if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE)384{385/* Check if this Device already has a handler for this address space */386387NextHandlerObj = AcpiEvFindRegionHandler (388HandlerObj->AddressSpace.SpaceId, ObjDesc->CommonNotify.Handler);389if (NextHandlerObj)390{391/* Found a handler, is it for the same address space? */392393ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,394"Found handler for region [%s] in device %p(%p) handler %p\n",395AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId),396ObjDesc, NextHandlerObj, HandlerObj));397398/*399* Since the object we found it on was a device, then it means400* that someone has already installed a handler for the branch401* of the namespace from this device on. Just bail out telling402* the walk routine to not traverse this branch. This preserves403* the scoping rule for handlers.404*/405return (AE_CTRL_DEPTH);406}407408/*409* As long as the device didn't have a handler for this space we410* don't care about it. We just ignore it and proceed.411*/412return (AE_OK);413}414415/* Object is a Region */416417if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId)418{419/* This region is for a different address space, just ignore it */420421return (AE_OK);422}423424/*425* Now we have a region and it is for the handler's address space type.426*427* First disconnect region for any previous handler (if any)428*/429AcpiEvDetachRegion (ObjDesc, FALSE);430431/* Connect the region to the new handler */432433Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE);434return (Status);435}436437438/*******************************************************************************439*440* FUNCTION: AcpiEvFindRegionHandler441*442* PARAMETERS: SpaceId - The address space ID443* HandlerObj - Head of the handler object list444*445* RETURN: Matching handler object. NULL if space ID not matched446*447* DESCRIPTION: Search a handler object list for a match on the address448* space ID.449*450******************************************************************************/451452ACPI_OPERAND_OBJECT *453AcpiEvFindRegionHandler (454ACPI_ADR_SPACE_TYPE SpaceId,455ACPI_OPERAND_OBJECT *HandlerObj)456{457458/* Walk the handler list for this device */459460while (HandlerObj)461{462/* Same SpaceId indicates a handler is installed */463464if (HandlerObj->AddressSpace.SpaceId == SpaceId)465{466return (HandlerObj);467}468469/* Next handler object */470471HandlerObj = HandlerObj->AddressSpace.Next;472}473474return (NULL);475}476477478/*******************************************************************************479*480* FUNCTION: AcpiEvInstallSpaceHandler481*482* PARAMETERS: Node - Namespace node for the device483* SpaceId - The address space ID484* Handler - Address of the handler485* Setup - Address of the setup function486* Context - Value passed to the handler on each access487*488* RETURN: Status489*490* DESCRIPTION: Install a handler for all OpRegions of a given SpaceId.491* Assumes namespace is locked492*493******************************************************************************/494495ACPI_STATUS496AcpiEvInstallSpaceHandler (497ACPI_NAMESPACE_NODE *Node,498ACPI_ADR_SPACE_TYPE SpaceId,499ACPI_ADR_SPACE_HANDLER Handler,500ACPI_ADR_SPACE_SETUP Setup,501void *Context)502{503ACPI_OPERAND_OBJECT *ObjDesc;504ACPI_OPERAND_OBJECT *HandlerObj;505ACPI_STATUS Status = AE_OK;506ACPI_OBJECT_TYPE Type;507UINT8 Flags = 0;508509510ACPI_FUNCTION_TRACE (EvInstallSpaceHandler);511512513/*514* This registration is valid for only the types below and the root.515* The root node is where the default handlers get installed.516*/517if ((Node->Type != ACPI_TYPE_DEVICE) &&518(Node->Type != ACPI_TYPE_PROCESSOR) &&519(Node->Type != ACPI_TYPE_THERMAL) &&520(Node != AcpiGbl_RootNode))521{522Status = AE_BAD_PARAMETER;523goto UnlockAndExit;524}525526if (Handler == ACPI_DEFAULT_HANDLER)527{528Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED;529530switch (SpaceId)531{532case ACPI_ADR_SPACE_SYSTEM_MEMORY:533534Handler = AcpiExSystemMemorySpaceHandler;535Setup = AcpiEvSystemMemoryRegionSetup;536break;537538case ACPI_ADR_SPACE_SYSTEM_IO:539540Handler = AcpiExSystemIoSpaceHandler;541Setup = AcpiEvIoSpaceRegionSetup;542break;543544case ACPI_ADR_SPACE_PCI_CONFIG:545546Handler = AcpiExPciConfigSpaceHandler;547Setup = AcpiEvPciConfigRegionSetup;548break;549550case ACPI_ADR_SPACE_CMOS:551552Handler = AcpiExCmosSpaceHandler;553Setup = AcpiEvCmosRegionSetup;554break;555556case ACPI_ADR_SPACE_PCI_BAR_TARGET:557558Handler = AcpiExPciBarSpaceHandler;559Setup = AcpiEvPciBarRegionSetup;560break;561562case ACPI_ADR_SPACE_DATA_TABLE:563564Handler = AcpiExDataTableSpaceHandler;565Setup = AcpiEvDataTableRegionSetup;566break;567568default:569570Status = AE_BAD_PARAMETER;571goto UnlockAndExit;572}573}574575/* If the caller hasn't specified a setup routine, use the default */576577if (!Setup)578{579Setup = AcpiEvDefaultRegionSetup;580}581582/* Check for an existing internal object */583584ObjDesc = AcpiNsGetAttachedObject (Node);585if (ObjDesc)586{587/*588* The attached device object already exists. Now make sure589* the handler is not already installed.590*/591HandlerObj = AcpiEvFindRegionHandler (SpaceId,592ObjDesc->CommonNotify.Handler);593594if (HandlerObj)595{596if (HandlerObj->AddressSpace.Handler == Handler)597{598/*599* It is (relatively) OK to attempt to install the SAME600* handler twice. This can easily happen with the601* PCI_Config space.602*/603Status = AE_SAME_HANDLER;604goto UnlockAndExit;605}606else607{608/* A handler is already installed */609610Status = AE_ALREADY_EXISTS;611}612613goto UnlockAndExit;614}615}616else617{618ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,619"Creating object on Device %p while installing handler\n",620Node));621622/* ObjDesc does not exist, create one */623624if (Node->Type == ACPI_TYPE_ANY)625{626Type = ACPI_TYPE_DEVICE;627}628else629{630Type = Node->Type;631}632633ObjDesc = AcpiUtCreateInternalObject (Type);634if (!ObjDesc)635{636Status = AE_NO_MEMORY;637goto UnlockAndExit;638}639640/* Init new descriptor */641642ObjDesc->Common.Type = (UINT8) Type;643644/* Attach the new object to the Node */645646Status = AcpiNsAttachObject (Node, ObjDesc, Type);647648/* Remove local reference to the object */649650AcpiUtRemoveReference (ObjDesc);651652if (ACPI_FAILURE (Status))653{654goto UnlockAndExit;655}656}657658ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,659"Installing address handler for region %s(%X) "660"on Device %4.4s %p(%p)\n",661AcpiUtGetRegionName (SpaceId), SpaceId,662AcpiUtGetNodeName (Node), Node, ObjDesc));663664/*665* Install the handler666*667* At this point there is no existing handler. Just allocate the object668* for the handler and link it into the list.669*/670HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER);671if (!HandlerObj)672{673Status = AE_NO_MEMORY;674goto UnlockAndExit;675}676677/* Init handler obj */678679Status = AcpiOsCreateMutex (&HandlerObj->AddressSpace.ContextMutex);680if (ACPI_FAILURE (Status))681{682AcpiUtRemoveReference (HandlerObj);683goto UnlockAndExit;684}685686HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId;687HandlerObj->AddressSpace.HandlerFlags = Flags;688HandlerObj->AddressSpace.RegionList = NULL;689HandlerObj->AddressSpace.Node = Node;690HandlerObj->AddressSpace.Handler = Handler;691HandlerObj->AddressSpace.Context = Context;692HandlerObj->AddressSpace.Setup = Setup;693694/* Install at head of Device.AddressSpace list */695696HandlerObj->AddressSpace.Next = ObjDesc->CommonNotify.Handler;697698/*699* The Device object is the first reference on the HandlerObj.700* Each region that uses the handler adds a reference.701*/702ObjDesc->CommonNotify.Handler = HandlerObj;703704/*705* Walk the namespace finding all of the regions this handler will706* manage.707*708* Start at the device and search the branch toward the leaf nodes709* until either the leaf is encountered or a device is detected that710* has an address handler of the same type.711*712* In either case, back up and search down the remainder of the branch713*/714Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node,715ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,716AcpiEvInstallHandler, NULL, HandlerObj, NULL);717718UnlockAndExit:719return_ACPI_STATUS (Status);720}721722723