ACPI_STATUS AcpiEvInitializeRegion ( ACPI_OPERAND_OBJECT *RegionObj, BOOLEAN AcpiNsLocked) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_ADR_SPACE_TYPE SpaceId; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); if (!RegionObj) { return_ACPI_STATUS (AE_BAD_PARAMETER); } if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) { return_ACPI_STATUS (AE_OK); } RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; Node = RegionObj->Region.Node->Parent; SpaceId = RegionObj->Region.SpaceId; /* * The following loop depends upon the root Node having no parent * ie: AcpiGbl_RootNode->Parent being set to NULL */ while (Node) { /* Check to see if a handler exists */ HandlerObj = NULL; ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* Can only be a handler if the object exists */ switch (Node->Type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: HandlerObj = ObjDesc->CommonNotify.Handler; break; case ACPI_TYPE_METHOD: /* * If we are executing module level code, the original * Node's object was replaced by this Method object and we * saved the handler in the method object. * * See AcpiNsExecModuleCode */ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) { HandlerObj = ObjDesc->Method.Dispatch.Handler; } break; default: /* Ignore other objects */ break; } HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj); if (HandlerObj) { /* Found correct handler */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler %p for region %p in obj %p\n", HandlerObj, RegionObj, ObjDesc)); Status = AcpiEvAttachRegion (HandlerObj, RegionObj, AcpiNsLocked); /* * Tell all users that this region is usable by * running the _REG method */ if (AcpiNsLocked) { Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); if (AcpiNsLocked) { Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } return_ACPI_STATUS (AE_OK); } } /* This node does not have the handler we need; Pop up one level */ Node = Node->Parent; } /* If we get here, there is no handler for this region */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "No handler for RegionType %s(%X) (RegionObj %p)\n", AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); return_ACPI_STATUS (AE_NOT_EXIST); }
static ACPI_STATUS AcpiEvInstallHandler ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *NextHandlerObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_NAME (EvInstallHandler); HandlerObj = (ACPI_OPERAND_OBJECT *) Context; /* Parameter validation */ if (!HandlerObj) { return (AE_OK); } /* Convert and validate the device handle */ Node = AcpiNsValidateHandle (ObjHandle); if (!Node) { return (AE_BAD_PARAMETER); } /* * We only care about regions and objects that are allowed to have * address space handlers */ if ((Node->Type != ACPI_TYPE_DEVICE) && (Node->Type != ACPI_TYPE_REGION) && (Node != AcpiGbl_RootNode)) { return (AE_OK); } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* No object, just exit */ return (AE_OK); } /* Devices are handled different than regions */ if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) { /* Check if this Device already has a handler for this address space */ NextHandlerObj = AcpiEvFindRegionHandler ( HandlerObj->AddressSpace.SpaceId, ObjDesc->CommonNotify.Handler); if (NextHandlerObj) { /* Found a handler, is it for the same address space? */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler for region [%s] in device %p(%p) handler %p\n", AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), ObjDesc, NextHandlerObj, HandlerObj)); /* * Since the object we found it on was a device, then it means * that someone has already installed a handler for the branch * of the namespace from this device on. Just bail out telling * the walk routine to not traverse this branch. This preserves * the scoping rule for handlers. */ return (AE_CTRL_DEPTH); } /* * As long as the device didn't have a handler for this space we * don't care about it. We just ignore it and proceed. */ return (AE_OK); } /* Object is a Region */ if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) { /* This region is for a different address space, just ignore it */ return (AE_OK); } /* * Now we have a region and it is for the handler's address space type. * * First disconnect region for any previous handler (if any) */ AcpiEvDetachRegion (ObjDesc, FALSE); /* Connect the region to the new handler */ Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); return (Status); }
ACPI_STATUS AcpiEvAddrHandlerHelper ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *TmpObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_NAME ("EvAddrHandlerHelper"); HandlerObj = (ACPI_OPERAND_OBJECT *) Context; /* Parameter validation */ if (!HandlerObj) { return (AE_OK); } /* Convert and validate the device handle */ Node = AcpiNsMapHandleToNode (ObjHandle); if (!Node) { return (AE_BAD_PARAMETER); } /* * We only care about regions.and objects * that can have address handlers */ if ((Node->Type != ACPI_TYPE_DEVICE) && (Node->Type != ACPI_TYPE_REGION) && (Node != AcpiGbl_RootNode)) { return (AE_OK); } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* * The object DNE, we don't care about it */ return (AE_OK); } /* * Devices are handled different than regions */ if (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_DEVICE) { /* * See if this guy has any handlers */ TmpObj = ObjDesc->Device.AddrHandler; while (TmpObj) { /* * Now let's see if it's for the same address space. */ if (TmpObj->AddrHandler.SpaceId == HandlerObj->AddrHandler.SpaceId) { /* * It's for the same address space */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler for region [%s] in device %p(%p) handler %p\n", AcpiUtGetRegionName (HandlerObj->AddrHandler.SpaceId), ObjDesc, TmpObj, HandlerObj)); /* * Since the object we found it on was a device, then it * means that someone has already installed a handler for * the branch of the namespace from this device on. Just * bail out telling the walk routine to not traverse this * branch. This preserves the scoping rule for handlers. */ return (AE_CTRL_DEPTH); } /* * Move through the linked list of handlers */ TmpObj = TmpObj->AddrHandler.Next; } /* * As long as the device didn't have a handler for this * space we don't care about it. We just ignore it and * proceed. */ return (AE_OK); } /* * Only here if it was a region */ if (ObjDesc->Region.SpaceId != HandlerObj->AddrHandler.SpaceId) { /* * This region is for a different address space * ignore it */ return (AE_OK); } /* * Now we have a region and it is for the handler's address * space type. * * First disconnect region for any previous handler (if any) */ AcpiEvDetachRegion (ObjDesc, FALSE); /* * Then connect the region to the new handler */ Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); return (Status); }
ACPI_STATUS AcpiEvInitializeRegion ( ACPI_OPERAND_OBJECT *RegionObj, BOOLEAN AcpiNsLocked) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_ADR_SPACE_TYPE SpaceId; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_NAMESPACE_NODE *MethodNode; ACPI_NAME *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG; ACPI_OPERAND_OBJECT *RegionObj2; ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); if (!RegionObj) { return_ACPI_STATUS (AE_BAD_PARAMETER); } if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) { return_ACPI_STATUS (AE_OK); } RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); if (!RegionObj2) { return_ACPI_STATUS (AE_NOT_EXIST); } Node = AcpiNsGetParentNode (RegionObj->Region.Node); SpaceId = RegionObj->Region.SpaceId; /* Setup defaults */ RegionObj->Region.Handler = NULL; RegionObj2->Extra.Method_REG = NULL; RegionObj->Common.Flags &= ~(AOPOBJ_SETUP_COMPLETE); RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; /* Find any "_REG" method associated with this region definition */ Status = AcpiNsSearchOneScope ( *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode); if (ACPI_SUCCESS (Status)) { /* * The _REG method is optional and there can be only one per region * definition. This will be executed when the handler is attached * or removed */ RegionObj2->Extra.Method_REG = MethodNode; } /* * The following loop depends upon the root Node having no parent * ie: AcpiGbl_RootNode->ParentEntry being set to NULL */ while (Node) { /* Check to see if a handler exists */ HandlerObj = NULL; ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* Can only be a handler if the object exists */ switch (Node->Type) { case ACPI_TYPE_DEVICE: HandlerObj = ObjDesc->Device.Handler; break; case ACPI_TYPE_PROCESSOR: HandlerObj = ObjDesc->Processor.Handler; break; case ACPI_TYPE_THERMAL: HandlerObj = ObjDesc->ThermalZone.Handler; break; default: /* Ignore other objects */ break; } while (HandlerObj) { /* Is this handler of the correct type? */ if (HandlerObj->AddressSpace.SpaceId == SpaceId) { /* Found correct handler */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler %p for region %p in obj %p\n", HandlerObj, RegionObj, ObjDesc)); Status = AcpiEvAttachRegion (HandlerObj, RegionObj, AcpiNsLocked); /* * Tell all users that this region is usable by * running the _REG method */ if (AcpiNsLocked) { Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AcpiEvExecuteRegMethod (RegionObj, 1); if (AcpiNsLocked) { Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } return_ACPI_STATUS (AE_OK); } /* Try next handler in the list */ HandlerObj = HandlerObj->AddressSpace.Next; } } /* This node does not have the handler we need; Pop up one level */ Node = AcpiNsGetParentNode (Node); } /* If we get here, there is no handler for this region */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "No handler for RegionType %s(%X) (RegionObj %p)\n", AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); return_ACPI_STATUS (AE_NOT_EXIST); }
ACPI_STATUS AcpiEvInitializeRegion ( ACPI_OPERAND_OBJECT *RegionObj) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_ADR_SPACE_TYPE SpaceId; ACPI_NAMESPACE_NODE *Node; ACPI_FUNCTION_TRACE (EvInitializeRegion); if (!RegionObj) { return_ACPI_STATUS (AE_BAD_PARAMETER); } if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) { return_ACPI_STATUS (AE_OK); } RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; Node = RegionObj->Region.Node->Parent; SpaceId = RegionObj->Region.SpaceId; /* * The following loop depends upon the root Node having no parent * ie: AcpiGbl_RootNode->Parent being set to NULL */ while (Node) { /* Check to see if a handler exists */ HandlerObj = NULL; ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* Can only be a handler if the object exists */ switch (Node->Type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: HandlerObj = ObjDesc->CommonNotify.Handler; break; case ACPI_TYPE_METHOD: /* * If we are executing module level code, the original * Node's object was replaced by this Method object and we * saved the handler in the method object. * * Note: Only used for the legacy MLC support. Will * be removed in the future. * * See AcpiNsExecModuleCode */ if (!AcpiGbl_ExecuteTablesAsMethods && ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) { HandlerObj = ObjDesc->Method.Dispatch.Handler; } break; default: /* Ignore other objects */ break; } HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj); if (HandlerObj) { /* Found correct handler */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler %p for region %p in obj %p\n", HandlerObj, RegionObj, ObjDesc)); (void) AcpiEvAttachRegion (HandlerObj, RegionObj, FALSE); /* * Tell all users that this region is usable by * running the _REG method */ AcpiExExitInterpreter (); (void) AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); AcpiExEnterInterpreter (); return_ACPI_STATUS (AE_OK); } } /* This node does not have the handler we need; Pop up one level */ Node = Node->Parent; } /* * If we get here, there is no handler for this region. This is not * fatal because many regions get created before a handler is installed * for said region. */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "No handler for RegionType %s(%X) (RegionObj %p)\n", AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); return_ACPI_STATUS (AE_OK); }