void AcpiEvAssociateRegMethod ( ACPI_OPERAND_OBJECT *RegionObj) { ACPI_NAME *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG; ACPI_NAMESPACE_NODE *MethodNode; ACPI_NAMESPACE_NODE *Node; ACPI_OPERAND_OBJECT *RegionObj2; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvAssociateRegMethod); RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); if (!RegionObj2) { return_VOID; } Node = RegionObj->Region.Node->Parent; /* 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; } return_VOID; }
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 AcpiEvExecuteRegMethod ( ACPI_OPERAND_OBJECT *RegionObj, UINT32 Function) { ACPI_EVALUATE_INFO *Info; ACPI_OPERAND_OBJECT *Args[3]; ACPI_OPERAND_OBJECT *RegionObj2; const ACPI_NAME *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG); ACPI_NAMESPACE_NODE *MethodNode; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvExecuteRegMethod); if (!AcpiGbl_NamespaceInitialized || RegionObj->Region.Handler == NULL) { return_ACPI_STATUS (AE_OK); } RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); if (!RegionObj2) { return_ACPI_STATUS (AE_NOT_EXIST); } /* * Find any "_REG" method associated with this region definition. * The method should always be updated as this function may be * invoked after a namespace change. */ Node = RegionObj->Region.Node->Parent; 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; } if (RegionObj2->Extra.Method_REG == NULL) { return_ACPI_STATUS (AE_OK); } /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */ if ((Function == ACPI_REG_CONNECT && RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) || (Function == ACPI_REG_DISCONNECT && !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED))) { return_ACPI_STATUS (AE_OK); } /* Allocate and initialize the evaluation information block */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { return_ACPI_STATUS (AE_NO_MEMORY); } Info->PrefixNode = RegionObj2->Extra.Method_REG; Info->RelativePathname = NULL; Info->Parameters = Args; Info->Flags = ACPI_IGNORE_RETURN_VALUE; /* * The _REG method has two arguments: * * Arg0 - Integer: * Operation region space ID Same value as RegionObj->Region.SpaceId * * Arg1 - Integer: * connection status 1 for connecting the handler, 0 for disconnecting * the handler (Passed as a parameter) */ Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); if (!Args[0]) { Status = AE_NO_MEMORY; goto Cleanup1; } Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); if (!Args[1]) { Status = AE_NO_MEMORY; goto Cleanup2; } Args[2] = NULL; /* Terminate list */ /* Execute the method, no return value */ ACPI_DEBUG_EXEC ( AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); Status = AcpiNsEvaluate (Info); AcpiUtRemoveReference (Args[1]); if (ACPI_FAILURE (Status)) { goto Cleanup2; } if (Function == ACPI_REG_CONNECT) { RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED; } else { RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED; } Cleanup2: AcpiUtRemoveReference (Args[0]); Cleanup1: ACPI_FREE (Info); return_ACPI_STATUS (Status); }