ACPI_NAMESPACE_NODE * AcpiNsGetNextNodeTyped ( ACPI_OBJECT_TYPE Type, ACPI_NAMESPACE_NODE *ParentNode, ACPI_NAMESPACE_NODE *ChildNode) { ACPI_NAMESPACE_NODE *NextNode = NULL; ACPI_FUNCTION_ENTRY (); NextNode = AcpiNsGetNextNode (ParentNode, ChildNode); /* If any type is OK, we are done */ if (Type == ACPI_TYPE_ANY) { /* NextNode is NULL if we are at the end-of-list */ return (NextNode); } /* Must search for the node -- but within this scope only */ while (NextNode) { /* If type matches, we are done */ if (NextNode->Type == Type) { return (NextNode); } /* Otherwise, move on to the next peer node */ NextNode = NextNode->Peer; } /* Not found */ return (NULL); }
void AcpiNsDeleteNamespaceByOwner ( ACPI_OWNER_ID OwnerId) { ACPI_NAMESPACE_NODE *ChildNode; ACPI_NAMESPACE_NODE *DeletionNode; ACPI_NAMESPACE_NODE *ParentNode; UINT32 Level; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId); if (OwnerId == 0) { return_VOID; } /* Lock namespace for possible update */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_VOID; } DeletionNode = NULL; ParentNode = AcpiGbl_RootNode; ChildNode = NULL; Level = 1; /* * Traverse the tree of nodes until we bubble back up * to where we started. */ while (Level > 0) { /* * Get the next child of this parent node. When ChildNode is NULL, * the first child of the parent is returned */ ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); if (DeletionNode) { AcpiNsDeleteChildren (DeletionNode); AcpiNsRemoveNode (DeletionNode); DeletionNode = NULL; } if (ChildNode) { if (ChildNode->OwnerId == OwnerId) { /* Found a matching child node - detach any attached object */ AcpiNsDetachObject (ChildNode); } /* Check if this node has any children */ if (ChildNode->Child) { /* * There is at least one child of this node, * visit the node */ Level++; ParentNode = ChildNode; ChildNode = NULL; } else if (ChildNode->OwnerId == OwnerId) { DeletionNode = ChildNode; } } else { /* * No more children of this parent node. * Move up to the grandparent. */ Level--; if (Level != 0) { if (ParentNode->OwnerId == OwnerId) { DeletionNode = ParentNode; } } /* New "last child" is this parent node */ ChildNode = ParentNode; /* Move up the tree to the grandparent */ ParentNode = ParentNode->Parent; } } (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_VOID; }
void AcpiNsDeleteNamespaceSubtree ( ACPI_NAMESPACE_NODE *ParentNode) { ACPI_NAMESPACE_NODE *ChildNode = NULL; UINT32 Level = 1; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree); if (!ParentNode) { return_VOID; } /* Lock namespace for possible update */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_VOID; } /* * Traverse the tree of objects until we bubble back up * to where we started. */ while (Level > 0) { /* Get the next node in this scope (NULL if none) */ ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); if (ChildNode) { /* Found a child node - detach any attached object */ AcpiNsDetachObject (ChildNode); /* Check if this node has any children */ if (ChildNode->Child) { /* * There is at least one child of this node, * visit the node */ Level++; ParentNode = ChildNode; ChildNode = NULL; } } else { /* * No more children of this parent node. * Move up to the grandparent. */ Level--; /* * Now delete all of the children of this parent * all at the same time. */ AcpiNsDeleteChildren (ParentNode); /* New "last child" is this parent node */ ChildNode = ParentNode; /* Move up the tree to the grandparent */ ParentNode = ParentNode->Parent; } } (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_VOID; }
ACPI_STATUS AcpiNsWalkNamespace ( ACPI_OBJECT_TYPE Type, ACPI_HANDLE StartNode, UINT32 MaxDepth, UINT32 Flags, ACPI_WALK_CALLBACK DescendingCallback, ACPI_WALK_CALLBACK AscendingCallback, void *Context, void **ReturnValue) { ACPI_STATUS Status; ACPI_STATUS MutexStatus; ACPI_NAMESPACE_NODE *ChildNode; ACPI_NAMESPACE_NODE *ParentNode; ACPI_OBJECT_TYPE ChildType; UINT32 Level; BOOLEAN NodePreviouslyVisited = FALSE; ACPI_FUNCTION_TRACE (NsWalkNamespace); /* Special case for the namespace Root Node */ if (StartNode == ACPI_ROOT_OBJECT) { StartNode = AcpiGbl_RootNode; } /* Null child means "get first node" */ ParentNode = StartNode; ChildNode = AcpiNsGetNextNode (ParentNode, NULL); ChildType = ACPI_TYPE_ANY; Level = 1; /* * Traverse the tree of nodes until we bubble back up to where we * started. When Level is zero, the loop is done because we have * bubbled up to (and passed) the original parent handle (StartEntry) */ while (Level > 0 && ChildNode) { Status = AE_OK; /* Found next child, get the type if we are not searching for ANY */ if (Type != ACPI_TYPE_ANY) { ChildType = ChildNode->Type; } /* * Ignore all temporary namespace nodes (created during control * method execution) unless told otherwise. These temporary nodes * can cause a race condition because they can be deleted during * the execution of the user function (if the namespace is * unlocked before invocation of the user function.) Only the * debugger namespace dump will examine the temporary nodes. */ if ((ChildNode->Flags & ANOBJ_TEMPORARY) && !(Flags & ACPI_NS_WALK_TEMP_NODES)) { Status = AE_CTRL_DEPTH; } /* Type must match requested type */ else if (ChildType == Type) { /* * Found a matching node, invoke the user callback function. * Unlock the namespace if flag is set. */ if (Flags & ACPI_NS_WALK_UNLOCK) { MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (MutexStatus)) { return_ACPI_STATUS (MutexStatus); } } /* * Invoke the user function, either descending, ascending, * or both. */ if (!NodePreviouslyVisited) { if (DescendingCallback) { Status = DescendingCallback (ChildNode, Level, Context, ReturnValue); } } else { if (AscendingCallback) { Status = AscendingCallback (ChildNode, Level, Context, ReturnValue); } } if (Flags & ACPI_NS_WALK_UNLOCK) { MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (MutexStatus)) { return_ACPI_STATUS (MutexStatus); } } switch (Status) { case AE_OK: case AE_CTRL_DEPTH: /* Just keep going */ break; case AE_CTRL_TERMINATE: /* Exit now, with OK status */ return_ACPI_STATUS (AE_OK); default: /* All others are valid exceptions */ return_ACPI_STATUS (Status); } } /* * Depth first search: Attempt to go down another level in the * namespace if we are allowed to. Don't go any further if we have * reached the caller specified maximum depth or if the user * function has specified that the maximum depth has been reached. */ if (!NodePreviouslyVisited && (Level < MaxDepth) && (Status != AE_CTRL_DEPTH)) { if (ChildNode->Child) { /* There is at least one child of this node, visit it */ Level++; ParentNode = ChildNode; ChildNode = AcpiNsGetNextNode (ParentNode, NULL); continue; } } /* No more children, re-visit this node */ if (!NodePreviouslyVisited) { NodePreviouslyVisited = TRUE; continue; } /* No more children, visit peers */ ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); if (ChildNode) { NodePreviouslyVisited = FALSE; } /* No peers, re-visit parent */ else { /* * No more children of this node (AcpiNsGetNextNode failed), go * back upwards in the namespace tree to the node's parent. */ Level--; ChildNode = ParentNode; ParentNode = ParentNode->Parent; NodePreviouslyVisited = TRUE; } } /* Complete walk, not terminated by user function */ return_ACPI_STATUS (AE_OK); }
void AcpiNsDeleteNamespaceSubtree ( ACPI_NAMESPACE_NODE *ParentNode) { ACPI_NAMESPACE_NODE *ChildNode = NULL; UINT32 Level = 1; ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree); if (!ParentNode) { return_VOID; } /* * Traverse the tree of objects until we bubble back up * to where we started. */ while (Level > 0) { /* Get the next node in this scope (NULL if none) */ ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode); if (ChildNode) { /* Found a child node - detach any attached object */ AcpiNsDetachObject (ChildNode); /* Check if this node has any children */ if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, NULL)) { /* * There is at least one child of this node, * visit the node */ Level++; ParentNode = ChildNode; ChildNode = NULL; } } else { /* * No more children of this parent node. * Move up to the grandparent. */ Level--; /* * Now delete all of the children of this parent * all at the same time. */ AcpiNsDeleteChildren (ParentNode); /* New "last child" is this parent node */ ChildNode = ParentNode; /* Move up the tree to the grandparent */ ParentNode = AcpiNsGetParentNode (ParentNode); } } return_VOID; }
static void AcpiEvOrphanEcRegMethod ( ACPI_NAMESPACE_NODE *EcDeviceNode) { ACPI_HANDLE RegMethod; ACPI_NAMESPACE_NODE *NextNode; ACPI_STATUS Status; ACPI_OBJECT_LIST Args; ACPI_OBJECT Objects[2]; ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); if (!EcDeviceNode) { return_VOID; } /* Namespace is currently locked, must release */ (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); /* Get a handle to a _REG method immediately under the EC device */ Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod); if (ACPI_FAILURE (Status)) { goto Exit; /* There is no _REG method present */ } /* * Execute the _REG method only if there is no Operation Region in * this scope with the Embedded Controller space ID. Otherwise, it * will already have been executed. Note, this allows for Regions * with other space IDs to be present; but the code below will then * execute the _REG method with the EmbeddedControl SpaceID argument. */ NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); while (NextNode) { if ((NextNode->Type == ACPI_TYPE_REGION) && (NextNode->Object) && (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) { goto Exit; /* Do not execute the _REG */ } NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); } /* Evaluate the _REG(EmbeddedControl,Connect) method */ Args.Count = 2; Args.Pointer = Objects; Objects[0].Type = ACPI_TYPE_INTEGER; Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; Objects[1].Type = ACPI_TYPE_INTEGER; Objects[1].Integer.Value = ACPI_REG_CONNECT; Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); Exit: /* We ignore all errors from above, don't care */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); return_VOID; }
ACPI_STATUS AcpiGetNextObject ( ACPI_OBJECT_TYPE Type, ACPI_HANDLE Parent, ACPI_HANDLE Child, ACPI_HANDLE *RetHandle) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_NAMESPACE_NODE *ParentNode = NULL; ACPI_NAMESPACE_NODE *ChildNode = NULL; /* Parameter validation */ if (Type > ACPI_TYPE_EXTERNAL_MAX) { return (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return (Status); } /* If null handle, use the parent */ if (!Child) { /* Start search at the beginning of the specified scope */ ParentNode = AcpiNsMapHandleToNode (Parent); if (!ParentNode) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } } else { /* Non-null handle, ignore the parent */ /* Convert and validate the handle */ ChildNode = AcpiNsMapHandleToNode (Child); if (!ChildNode) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } } /* Internal function does the real work */ Node = AcpiNsGetNextNode (Type, ParentNode, ChildNode); if (!Node) { Status = AE_NOT_FOUND; goto UnlockAndExit; } if (RetHandle) { *RetHandle = AcpiNsConvertEntryToHandle (Node); } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return (Status); }